diff options
Diffstat (limited to 'source/blender/editors')
92 files changed, 1485 insertions, 967 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index f69830fc015..87688ee343c 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -4025,7 +4025,7 @@ static bool acf_nlaaction_setting_valid(bAnimContext *UNUSED(ac), /* conditionally supported */ case ACHANNEL_SETTING_PINNED: /* pinned - map/unmap */ if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) { - /* this should only appear in tweakmode */ + /* This should only appear in tweak-mode. */ return true; } else { @@ -5176,7 +5176,7 @@ void ANIM_channel_draw_widgets(const bContext *C, } /* step 3) draw special toggles ................................. - * - in Graph Editor, checkboxes for visibility in curves area + * - in Graph Editor, check-boxes for visibility in curves area * - in NLA Editor, glowing dots for solo/not solo... * - in Grease Pencil mode, color swatches for layer color */ diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 136cdefd2ec..8f8c1c067d4 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -747,7 +747,7 @@ static bool animedit_poll_channels_active(bContext *C) return 1; } -/* poll callback for Animation Editor channels list region + not in NLA-tweakmode for NLA */ +/* Poll callback for Animation Editor channels list region + not in NLA-tweak-mode for NLA. */ static bool animedit_poll_channels_nla_tweakmode_off(bContext *C) { ScrArea *area = CTX_wm_area(C); @@ -763,7 +763,7 @@ static bool animedit_poll_channels_nla_tweakmode_off(bContext *C) return 0; } - /* NLA TweakMode test */ + /* NLA tweak-mode test. */ if (area->spacetype == SPACE_NLA) { if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON)) { return 0; @@ -1283,6 +1283,9 @@ static void split_groups_action_temp(bAction *act, bActionGroup *tgrp) else { group_fcurves_last->next->prev = group_fcurves_first->prev; } + + /* Clear links pointing outside the per-group list. */ + group_fcurves_first->prev = group_fcurves_last->next = NULL; } /* Initialize memory for temp-group */ @@ -1337,24 +1340,12 @@ static void join_groups_action_temp(bAction *act) if (agrp->flag & AGRP_TEMP) { LISTBASE_FOREACH (FCurve *, fcu, &agrp->channels) { fcu->grp = NULL; - if (fcu == agrp->channels.last) { - break; - } } BLI_remlink(&act->groups, agrp); break; } } - - /* BLI_movelisttolist() doesn't touch first->prev and last->next pointers in its "dst" list. - * Ensure that after the reshuffling the list is properly terminated. */ - if (!BLI_listbase_is_empty(&act->curves)) { - FCurve *act_fcurves_first = act->curves.first; - act_fcurves_first->prev = NULL; - FCurve *act_fcurves_last = act->curves.last; - act_fcurves_last->next = NULL; - } } /* Change the order of anim-channels within action diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 73b9b118148..6f3277397c5 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -51,8 +51,10 @@ #include "DEG_depsgraph.h" +#include "SEQ_iterator.h" #include "SEQ_sequencer.h" #include "SEQ_time.h" +#include "SEQ_transform.h" #include "anim_intern.h" @@ -81,6 +83,49 @@ static bool change_frame_poll(bContext *C) return false; } +static int seq_snap_threshold_get_frame_distance(bContext *C) +{ + const int snap_distance = SEQ_tool_settings_snap_distance_get(CTX_data_scene(C)); + const ARegion *region = CTX_wm_region(C); + return round_fl_to_int(UI_view2d_region_to_view_x(®ion->v2d, snap_distance) - + UI_view2d_region_to_view_x(®ion->v2d, 0)); +} + +static void seq_frame_snap_update_best(const int position, + const int timeline_frame, + int *r_best_frame, + int *r_best_distance) +{ + if (abs(position - timeline_frame) < *r_best_distance) { + *r_best_distance = abs(position - timeline_frame); + *r_best_frame = position; + } +} + +static int seq_frame_apply_snap(bContext *C, Scene *scene, const int timeline_frame) +{ + + ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene, false)); + SeqCollection *strips = SEQ_query_all_strips(seqbase); + + int best_frame = 0; + int best_distance = MAXFRAME; + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, strips) { + seq_frame_snap_update_best( + SEQ_transform_get_left_handle_frame(seq), timeline_frame, &best_frame, &best_distance); + seq_frame_snap_update_best( + SEQ_transform_get_right_handle_frame(seq), timeline_frame, &best_frame, &best_distance); + } + SEQ_collection_free(strips); + + if (best_distance < seq_snap_threshold_get_frame_distance(C)) { + return best_frame; + } + + return timeline_frame; +} + /* Set the new frame number */ static void change_frame_apply(bContext *C, wmOperator *op) { @@ -90,7 +135,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) if (do_snap) { if (CTX_wm_space_seq(C)) { - frame = SEQ_time_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false); + frame = seq_frame_apply_snap(C, scene, frame); } else { frame = BKE_scene_frame_snap_by_seconds(scene, 1.0, frame); @@ -181,6 +226,18 @@ static void change_frame_seq_preview_end(bContext *C) } } +static bool use_sequencer_snapping(bContext *C) +{ + if (!CTX_wm_space_seq(C)) { + return false; + } + + Scene *scene = CTX_data_scene(C); + short snap_flag = SEQ_tool_settings_snap_flag_get(scene); + return (scene->toolsettings->snap_flag & SCE_SNAP_SEQ) && + (snap_flag & SEQ_SNAP_CURRENT_FRAME_TO_STRIPS); +} + /* Modal Operator init */ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -190,6 +247,10 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event */ RNA_float_set(op->ptr, "frame", frame_from_event(C, event)); + if (use_sequencer_snapping(C)) { + RNA_boolean_set(op->ptr, "snap", true); + } + change_frame_seq_preview_begin(C, event); change_frame_apply(C, op); @@ -231,11 +292,22 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event) case EVT_LEFTCTRLKEY: case EVT_RIGHTCTRLKEY: - if (event->val == KM_RELEASE) { - RNA_boolean_set(op->ptr, "snap", false); + /* Use Ctrl key to invert snapping in sequencer. */ + if (use_sequencer_snapping(C)) { + if (event->val == KM_RELEASE) { + RNA_boolean_set(op->ptr, "snap", true); + } + else if (event->val == KM_PRESS) { + RNA_boolean_set(op->ptr, "snap", false); + } } - else if (event->val == KM_PRESS) { - RNA_boolean_set(op->ptr, "snap", true); + else { + if (event->val == KM_RELEASE) { + RNA_boolean_set(op->ptr, "snap", false); + } + else if (event->val == KM_PRESS) { + RNA_boolean_set(op->ptr, "snap", true); + } } break; } diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 16eb2f6b6f2..bfaa76b3bf9 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -80,7 +80,7 @@ FCurve *verify_driver_fcurve(ID *id, /* init animdata if none available yet */ adt = BKE_animdata_from_id(id); if (adt == NULL && creation_mode != DRIVER_FCURVE_LOOKUP_ONLY) { - adt = BKE_animdata_add_id(id); + adt = BKE_animdata_ensure_id(id); } if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 3751555f18c..0a499232ba9 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -85,6 +85,8 @@ static KeyingSet *keyingset_get_from_op_with_error(wmOperator *op, PropertyRNA *prop, Scene *scene); +static int delete_key_using_keying_set(bContext *C, wmOperator *op, KeyingSet *ks); + /* ************************************************** */ /* Keyframing Setting Wrangling */ @@ -140,7 +142,7 @@ bAction *ED_id_action_ensure(Main *bmain, ID *id) /* init animdata if none available yet */ adt = BKE_animdata_from_id(id); if (adt == NULL) { - adt = BKE_animdata_add_id(id); + adt = BKE_animdata_ensure_id(id); } if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ @@ -2079,42 +2081,19 @@ void ANIM_OT_keyframe_insert_menu(wmOperatorType *ot) static int delete_key_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - float cfra = (float)CFRA; /* XXX for now, don't bother about all the yucky offset crap */ - int num_channels; - KeyingSet *ks = keyingset_get_from_op_with_error(op, op->type->prop, scene); if (ks == NULL) { return OPERATOR_CANCELLED; } - const int prop_type = RNA_property_type(op->type->prop); - if (prop_type == PROP_ENUM) { - int type = RNA_property_enum_get(op->ptr, op->type->prop); - ks = ANIM_keyingset_get_from_enum_type(scene, type); - if (ks == NULL) { - BKE_report(op->reports, RPT_ERROR, "No active Keying Set"); - return OPERATOR_CANCELLED; - } - } - else if (prop_type == PROP_STRING) { - char type_id[MAX_ID_NAME - 2]; - RNA_property_string_get(op->ptr, op->type->prop, type_id); - ks = ANIM_keyingset_get_from_idname(scene, type_id); - - if (ks == NULL) { - BKE_reportf(op->reports, RPT_ERROR, "Active Keying Set '%s' not found", type_id); - return OPERATOR_CANCELLED; - } - } - else { - BLI_assert(0); - } + return delete_key_using_keying_set(C, op, ks); +} - /* report failure */ - if (ks == NULL) { - BKE_report(op->reports, RPT_ERROR, "No active Keying Set"); - return OPERATOR_CANCELLED; - } +static int delete_key_using_keying_set(bContext *C, wmOperator *op, KeyingSet *ks) +{ + Scene *scene = CTX_data_scene(C); + float cfra = (float)CFRA; /* XXX for now, don't bother about all the yucky offset crap */ + int num_channels; /* try to delete keyframes for the channels specified by KeyingSet */ num_channels = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_DELETE, cfra); @@ -2130,7 +2109,8 @@ static int delete_key_exec(bContext *C, wmOperator *op) if (num_channels > 0) { /* if the appropriate properties have been set, make a note that we've inserted something */ - if (RNA_boolean_get(op->ptr, "confirm_success")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "confirm_success"); + if (prop != NULL && RNA_property_boolean_get(op->ptr, prop)) { BKE_reportf(op->reports, RPT_INFO, "Successfully removed %d keyframes for keying set '%s'", @@ -2301,7 +2281,7 @@ void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static int delete_key_v3d_exec(bContext *C, wmOperator *op) +static int delete_key_v3d_without_keying_set(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); float cfra = (float)CFRA; @@ -2408,6 +2388,18 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int delete_key_v3d_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + KeyingSet *ks = ANIM_scene_get_active_keyingset(scene); + + if (ks == NULL) { + return delete_key_v3d_without_keying_set(C, op); + } + + return delete_key_using_keying_set(C, op, ks); +} + void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot) { /* identifiers */ diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c index 034378399b9..6af033f3cf2 100644 --- a/source/blender/editors/animation/time_scrub_ui.c +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -109,7 +109,7 @@ static void draw_current_frame(const Scene *scene, if (draw_line) { /* Draw vertical line to from the bottom of the current frame box to the bottom of the screen. */ - const float subframe_x = UI_view2d_view_to_region_x(v2d, BKE_scene_frame_get(scene)); + const float subframe_x = UI_view2d_view_to_region_x(v2d, BKE_scene_ctime_get(scene)); GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c index 725945f8edc..832e75b2a8b 100644 --- a/source/blender/editors/armature/editarmature_undo.c +++ b/source/blender/editors/armature/editarmature_undo.c @@ -206,7 +206,7 @@ static void armature_undosys_step_decode(struct bContext *C, } undoarm_to_editarm(&elem->data, arm); arm->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&arm->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c index 88f6398567d..210411c6eb5 100644 --- a/source/blender/editors/curve/editcurve_undo.c +++ b/source/blender/editors/curve/editcurve_undo.c @@ -267,7 +267,7 @@ static void curve_undosys_step_decode(struct bContext *C, } undocurve_to_editcurve(bmain, &elem->data, obedit->data, &obedit->shapenr); cu->editnurb->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c index b61506d9346..6eaf8971eb0 100644 --- a/source/blender/editors/curve/editfont_undo.c +++ b/source/blender/editors/curve/editfont_undo.c @@ -379,7 +379,7 @@ static void font_undosys_step_decode(struct bContext *C, Curve *cu = obedit->data; undofont_to_editfont(&us->data, cu); - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY); ED_undo_object_set_active_or_warn( CTX_data_scene(C), CTX_data_view_layer(C), obedit, us_p->name, &LOG); diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 7bc4c307935..4b0c5ccd285 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -1172,7 +1172,7 @@ static void annotation_stroke_eraser_dostroke(tGPsdata *p, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { if ((annotation_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) || diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 0b107aac8b9..d6f6dbb2b10 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1579,7 +1579,7 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(mval, radius, pc0[0], pc0[1], pc2[0], pc2[1])) { diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index 7ec64b2afd6..16605b6c634 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -910,7 +910,7 @@ static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * brush region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c index 6e396cd82e3..d14322e12b5 100644 --- a/source/blender/editors/gpencil/gpencil_weight_paint.c +++ b/source/blender/editors/gpencil/gpencil_weight_paint.c @@ -448,7 +448,7 @@ static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * brush region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 0493832c06f..673f629d6ef 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -468,7 +468,7 @@ bool fcurve_is_changed(struct PointerRNA ptr, * Checks whether a keyframe exists for the given ID-block one the given frame. * - It is recommended to call this method over the other keyframe-checkers directly, * in case some detail of the implementation changes... - * - frame: the value of this is quite often result of #BKE_scene_frame_get() + * - frame: the value of this is quite often result of #BKE_scene_ctime_get() */ bool id_frame_has_keyframe(struct ID *id, float frame, short filter); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 667540b8f63..2b73194afb2 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -86,7 +86,7 @@ void EDBM_mesh_clear(struct BMEditMesh *em); void EDBM_selectmode_to_scene(struct bContext *C); void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index); -void EDBM_mesh_free(struct BMEditMesh *em); +void EDBM_mesh_free_data(struct BMEditMesh *em); void EDBM_mesh_load_ex(struct Main *bmain, struct Object *ob, bool free_data); void EDBM_mesh_load(struct Main *bmain, struct Object *ob); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 7a8c14d0a35..802c175492f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -58,6 +58,7 @@ struct bNodeTree; struct bScreen; struct rctf; struct rcti; +struct uiBlockInteraction_Handle; struct uiButSearch; struct uiFontStyle; struct uiList; @@ -245,7 +246,7 @@ enum { #define UI_PANEL_BOX_STYLE_MARGIN (U.widget_unit * 0.2f) /* but->drawflag - these flags should only affect how the button is drawn. */ -/* NOTE: currently, these flags _are not passed_ to the widget's state() or draw() functions +/* NOTE: currently, these flags *are not passed* to the widget's state() or draw() functions * (except for the 'align' ones)! */ enum { @@ -514,6 +515,54 @@ typedef int (*uiButPushedStateFunc)(struct uiBut *but, const void *arg); typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event); +/* -------------------------------------------------------------------- */ +/** \name Custom Interaction + * + * Sometimes it's useful to create data that remains available + * while the user interacts with a button. + * + * A common case is dragging a number button or slider + * however this could be used in other cases too. + * \{ */ + +struct uiBlockInteraction_Params { + /** + * When true, this interaction is not modal + * (user clicking on a number button arrows or pasting a value for example). + */ + bool is_click; + /** + * Array of unique event ID's (values from #uiBut.retval). + * There may be more than one for multi-button editing (see #UI_BUT_DRAG_MULTI). + */ + int *unique_retval_ids; + uint unique_retval_ids_len; +}; + +/** Returns 'user_data', freed by #uiBlockInteractionEndFn. */ +typedef void *(*uiBlockInteractionBeginFn)(struct bContext *C, + const struct uiBlockInteraction_Params *params, + void *arg1); +typedef void (*uiBlockInteractionEndFn)(struct bContext *C, + const struct uiBlockInteraction_Params *params, + void *arg1, + void *user_data); +typedef void (*uiBlockInteractionUpdateFn)(struct bContext *C, + const struct uiBlockInteraction_Params *params, + void *arg1, + void *user_data); + +typedef struct uiBlockInteraction_CallbackData { + uiBlockInteractionBeginFn begin_fn; + uiBlockInteractionEndFn end_fn; + uiBlockInteractionUpdateFn update_fn; + void *arg1; +} uiBlockInteraction_CallbackData; + +void UI_block_interaction_set(uiBlock *block, uiBlockInteraction_CallbackData *callbacks); + +/** \} */ + /* Menu Callbacks */ typedef void (*uiMenuCreateFunc)(struct bContext *C, struct uiLayout *layout, void *arg1); @@ -663,7 +712,7 @@ enum { UI_BLOCK_THEME_STYLE_POPUP = 1, }; void UI_block_theme_style_set(uiBlock *block, char theme_style); -char UI_block_emboss_get(uiBlock *block); +eUIEmbossType UI_block_emboss_get(uiBlock *block); void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss); bool UI_block_is_search_only(const uiBlock *block); void UI_block_set_search_only(uiBlock *block, bool search_only); @@ -678,7 +727,7 @@ void UI_block_region_set(uiBlock *block, struct ARegion *region); void UI_block_lock_set(uiBlock *block, bool val, const char *lockstr); void UI_block_lock_clear(uiBlock *block); -/* automatic aligning, horiz or verical */ +/* Automatic aligning, horizontal or vertical. */ void UI_block_align_begin(uiBlock *block); void UI_block_align_end(uiBlock *block); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index e9784a59d70..32b86119753 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -3542,7 +3542,7 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, eU return block; } -char UI_block_emboss_get(uiBlock *block) +eUIEmbossType UI_block_emboss_get(uiBlock *block) { return block->emboss; } @@ -4106,7 +4106,6 @@ static uiBut *ui_def_but(uiBlock *block, UI_BTYPE_BLOCK, UI_BTYPE_BUT_MENU, UI_BTYPE_SEARCH_MENU, - UI_BTYPE_PROGRESS_BAR, UI_BTYPE_DATASETROW, UI_BTYPE_POPOVER)) { but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT); diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index de0d5a4a3d7..2a7611eabb1 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -560,7 +560,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) const bool is_overridable = (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0; /* Set the (button_pointer, button_prop) - * and pointer data for Python access to the hovered ui element. */ + * and pointer data for Python access to the hovered UI element. */ uiLayoutSetContextFromBut(layout, but); /* Keyframes */ diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 2bd1b404228..655fdda3069 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -229,7 +229,7 @@ void ui_draw_but_TAB_outline(const rcti *rect, {0.98, 0.805}, }; - /* mult */ + /* Multiply. */ for (a = 0; a < 4; a++) { mul_v2_fl(vec[a], rad); } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index bf81ccd280e..0e45970a165 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -35,10 +35,12 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "BLI_array_utils.h" #include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_rect.h" +#include "BLI_sort_utils.h" #include "BLI_string.h" #include "BLI_string_cursor_utf8.h" #include "BLI_string_utf8.h" @@ -170,6 +172,20 @@ static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but static void ui_textedit_string_set(uiBut *but, struct uiHandleButtonData *data, const char *str); static void button_tooltip_timer_reset(bContext *C, uiBut *but); +static void ui_block_interaction_begin_ensure(bContext *C, + uiBlock *block, + struct uiHandleButtonData *data, + const bool is_click); +static struct uiBlockInteraction_Handle *ui_block_interaction_begin(struct bContext *C, + uiBlock *block, + const bool is_click); +static void ui_block_interaction_end(struct bContext *C, + uiBlockInteraction_CallbackData *callbacks, + struct uiBlockInteraction_Handle *interaction); +static void ui_block_interaction_update(struct bContext *C, + uiBlockInteraction_CallbackData *callbacks, + struct uiBlockInteraction_Handle *interaction); + #ifdef USE_KEYNAV_LIMIT static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEvent *event); static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEvent *event); @@ -225,6 +241,19 @@ typedef enum uiMenuScrollType { MENU_SCROLL_BOTTOM, } uiMenuScrollType; +typedef struct uiBlockInteraction_Handle { + struct uiBlockInteraction_Params params; + void *user_data; + /** + * This is shared between #uiHandleButtonData and #uiAfterFunc, + * the last user runs the end callback and frees the data. + * + * This is needed as the order of freeing changes depending on + * accepting/canceling the operation. + */ + int user_count; +} uiBlockInteraction_Handle; + #ifdef USE_ALLSELECT /* Unfortunately there's no good way handle more generally: @@ -430,6 +459,8 @@ typedef struct uiHandleButtonData { uiSelectContextStore select_others; #endif + struct uiBlockInteraction_Handle *custom_interaction_handle; + /* Text field undo. */ struct uiUndoStack_Text *undo_stack_text; @@ -471,6 +502,9 @@ typedef struct uiAfterFunc { void *search_arg; uiFreeArgFunc search_arg_free_fn; + uiBlockInteraction_CallbackData custom_interaction_callbacks; + uiBlockInteraction_Handle *custom_interaction_handle; + bContextStore *context; char undostr[BKE_UNDO_STR_MAX]; @@ -769,72 +803,95 @@ static bool ui_afterfunc_check(const uiBlock *block, const uiBut *but) (block->handle && block->handle->popup_op)); } +/** + * These functions are postponed and only executed after all other + * handling is done, i.e. menus are closed, in order to avoid conflicts + * with these functions removing the buttons we are working with. + */ static void ui_apply_but_func(bContext *C, uiBut *but) { uiBlock *block = but->block; + if (!ui_afterfunc_check(block, but)) { + return; + } - /* these functions are postponed and only executed after all other - * handling is done, i.e. menus are closed, in order to avoid conflicts - * with these functions removing the buttons we are working with */ - - if (ui_afterfunc_check(block, but)) { - uiAfterFunc *after = ui_afterfunc_new(); + uiAfterFunc *after = ui_afterfunc_new(); - if (but->func && ELEM(but, but->func_arg1, but->func_arg2)) { - /* exception, this will crash due to removed button otherwise */ - but->func(C, but->func_arg1, but->func_arg2); - } - else { - after->func = but->func; - } + if (but->func && ELEM(but, but->func_arg1, but->func_arg2)) { + /* exception, this will crash due to removed button otherwise */ + but->func(C, but->func_arg1, but->func_arg2); + } + else { + after->func = but->func; + } - after->func_arg1 = but->func_arg1; - after->func_arg2 = but->func_arg2; + after->func_arg1 = but->func_arg1; + after->func_arg2 = but->func_arg2; - after->funcN = but->funcN; - after->func_argN = (but->func_argN) ? MEM_dupallocN(but->func_argN) : NULL; + after->funcN = but->funcN; + after->func_argN = (but->func_argN) ? MEM_dupallocN(but->func_argN) : NULL; - after->rename_func = but->rename_func; - after->rename_arg1 = but->rename_arg1; - after->rename_orig = but->rename_orig; /* needs free! */ + after->rename_func = but->rename_func; + after->rename_arg1 = but->rename_arg1; + after->rename_orig = but->rename_orig; /* needs free! */ - after->handle_func = block->handle_func; - after->handle_func_arg = block->handle_func_arg; - after->retval = but->retval; + after->handle_func = block->handle_func; + after->handle_func_arg = block->handle_func_arg; + after->retval = but->retval; - if (but->type == UI_BTYPE_BUT_MENU) { - after->butm_func = block->butm_func; - after->butm_func_arg = block->butm_func_arg; - after->a2 = but->a2; - } + if (but->type == UI_BTYPE_BUT_MENU) { + after->butm_func = block->butm_func; + after->butm_func_arg = block->butm_func_arg; + after->a2 = but->a2; + } - if (block->handle) { - after->popup_op = block->handle->popup_op; - } + if (block->handle) { + after->popup_op = block->handle->popup_op; + } - after->optype = but->optype; - after->opcontext = but->opcontext; - after->opptr = but->opptr; + after->optype = but->optype; + after->opcontext = but->opcontext; + after->opptr = but->opptr; - after->rnapoin = but->rnapoin; - after->rnaprop = but->rnaprop; + after->rnapoin = but->rnapoin; + after->rnaprop = but->rnaprop; - if (but->type == UI_BTYPE_SEARCH_MENU) { - uiButSearch *search_but = (uiButSearch *)but; - after->search_arg_free_fn = search_but->arg_free_fn; - after->search_arg = search_but->arg; - search_but->arg_free_fn = NULL; - search_but->arg = NULL; - } + if (but->type == UI_BTYPE_SEARCH_MENU) { + uiButSearch *search_but = (uiButSearch *)but; + after->search_arg_free_fn = search_but->arg_free_fn; + after->search_arg = search_but->arg; + search_but->arg_free_fn = NULL; + search_but->arg = NULL; + } - if (but->context) { - after->context = CTX_store_copy(but->context); + if (but->active != NULL) { + uiHandleButtonData *data = but->active; + if (data->custom_interaction_handle != NULL) { + after->custom_interaction_callbacks = block->custom_interaction_callbacks; + after->custom_interaction_handle = data->custom_interaction_handle; + + /* Ensure this callback runs once and last. */ + uiAfterFunc *after_prev = after->prev; + if (after_prev && + (after_prev->custom_interaction_handle == data->custom_interaction_handle)) { + after_prev->custom_interaction_handle = NULL; + memset(&after_prev->custom_interaction_callbacks, + 0x0, + sizeof(after_prev->custom_interaction_callbacks)); + } + else { + after->custom_interaction_handle->user_count++; + } } + } - but->optype = NULL; - but->opcontext = 0; - but->opptr = NULL; + if (but->context) { + after->context = CTX_store_copy(but->context); } + + but->optype = NULL; + but->opcontext = 0; + but->opptr = NULL; } /* typically call ui_apply_but_undo(), ui_apply_but_autokey() */ @@ -997,6 +1054,18 @@ static void ui_apply_but_funcs_after(bContext *C) after.search_arg_free_fn(after.search_arg); } + if (after.custom_interaction_handle != NULL) { + after.custom_interaction_handle->user_count--; + BLI_assert(after.custom_interaction_handle->user_count >= 0); + if (after.custom_interaction_handle->user_count == 0) { + ui_block_interaction_update( + C, &after.custom_interaction_callbacks, after.custom_interaction_handle); + ui_block_interaction_end( + C, &after.custom_interaction_callbacks, after.custom_interaction_handle); + } + after.custom_interaction_handle = NULL; + } + ui_afterfunc_update_preferences_dirty(&after); if (after.undostr[0]) { @@ -2283,6 +2352,11 @@ static void ui_apply_but( uiButCurveProfile *but_profile = (uiButCurveProfile *)but; but_profile->edit_profile = editprofile; } + + if (data->custom_interaction_handle != NULL) { + ui_block_interaction_update( + C, &block->custom_interaction_callbacks, data->custom_interaction_handle); + } } /** \} */ @@ -3268,7 +3342,7 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in } #ifdef WITH_INPUT_IME -/* enable ime, and set up uibut ime data */ +/* Enable IME, and setup #uiBut IME data. */ static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but)) { /* XXX Is this really needed? */ @@ -3284,7 +3358,7 @@ static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but)) wm_window_IME_begin(win, x, y, 0, 0, true); } -/* disable ime, and clear uibut ime data */ +/* Disable IME, and clear #uiBut IME data. */ static void ui_textedit_ime_end(wmWindow *win, uiBut *UNUSED(but)) { wm_window_IME_end(win); @@ -4852,6 +4926,8 @@ static bool ui_numedit_but_NUM(uiButNumber *number_but, return changed; } + ui_block_interaction_begin_ensure(but->block->evil_C, but->block, data, false); + if (ui_but_is_cursor_warp(but)) { const float softmin = but->softmin; const float softmax = but->softmax; @@ -5362,6 +5438,8 @@ static bool ui_numedit_but_SLI(uiBut *but, return changed; } + ui_block_interaction_begin_ensure(but->block->evil_C, but->block, data, false); + const PropertyScaleType scale_type = ui_but_scale_type(but); softmin = but->softmin; @@ -8239,6 +8317,16 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s but->flag &= ~UI_SELECT; } + if (state == BUTTON_STATE_TEXT_EDITING) { + ui_block_interaction_begin_ensure(C, but->block, data, true); + } + else if (state == BUTTON_STATE_EXIT) { + if (data->state == BUTTON_STATE_NUM_EDITING) { + /* This happens on pasting values for example. */ + ui_block_interaction_begin_ensure(C, but->block, data, true); + } + } + data->state = state; if (state != BUTTON_STATE_EXIT) { @@ -8467,6 +8555,21 @@ static void button_activate_exit( ED_region_tag_redraw_no_rebuild(data->region); ED_region_tag_refresh_ui(data->region); + if ((but->flag & UI_BUT_DRAG_MULTI) == 0) { + if (data->custom_interaction_handle != NULL) { + /* Should only set when the button is modal. */ + BLI_assert(but->active != NULL); + data->custom_interaction_handle->user_count--; + + BLI_assert(data->custom_interaction_handle->user_count >= 0); + if (data->custom_interaction_handle->user_count == 0) { + ui_block_interaction_end( + C, &but->block->custom_interaction_callbacks, data->custom_interaction_handle); + } + data->custom_interaction_handle = NULL; + } + } + /* clean up button */ if (but->active) { MEM_freeN(but->active); @@ -11314,3 +11417,100 @@ bool UI_but_active_drop_color(bContext *C) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name UI Block Interaction API + * \{ */ + +void UI_block_interaction_set(uiBlock *block, uiBlockInteraction_CallbackData *callbacks) +{ + block->custom_interaction_callbacks = *callbacks; +} + +static uiBlockInteraction_Handle *ui_block_interaction_begin(bContext *C, + uiBlock *block, + const bool is_click) +{ + BLI_assert(block->custom_interaction_callbacks.begin_fn != NULL); + uiBlockInteraction_Handle *interaction = MEM_callocN(sizeof(*interaction), __func__); + + int unique_retval_ids_len = 0; + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + if (but->active || (but->flag & UI_BUT_DRAG_MULTI)) { + unique_retval_ids_len++; + } + } + + int *unique_retval_ids = MEM_mallocN(sizeof(*unique_retval_ids) * unique_retval_ids_len, + __func__); + unique_retval_ids_len = 0; + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + if (but->active || (but->flag & UI_BUT_DRAG_MULTI)) { + unique_retval_ids[unique_retval_ids_len++] = but->retval; + } + } + + if (unique_retval_ids_len > 1) { + qsort(unique_retval_ids, unique_retval_ids_len, sizeof(int), BLI_sortutil_cmp_int); + unique_retval_ids_len = BLI_array_deduplicate_ordered(unique_retval_ids, + unique_retval_ids_len); + unique_retval_ids = MEM_reallocN(unique_retval_ids, + sizeof(*unique_retval_ids) * unique_retval_ids_len); + } + + interaction->params.is_click = is_click; + interaction->params.unique_retval_ids = unique_retval_ids; + interaction->params.unique_retval_ids_len = unique_retval_ids_len; + + interaction->user_data = block->custom_interaction_callbacks.begin_fn( + C, &interaction->params, block->custom_interaction_callbacks.arg1); + return interaction; +} + +static void ui_block_interaction_end(bContext *C, + uiBlockInteraction_CallbackData *callbacks, + uiBlockInteraction_Handle *interaction) +{ + BLI_assert(callbacks->end_fn != NULL); + callbacks->end_fn(C, &interaction->params, callbacks->arg1, interaction->user_data); + MEM_freeN(interaction->params.unique_retval_ids); + MEM_freeN(interaction); +} + +static void ui_block_interaction_update(bContext *C, + uiBlockInteraction_CallbackData *callbacks, + uiBlockInteraction_Handle *interaction) +{ + BLI_assert(callbacks->update_fn != NULL); + callbacks->update_fn(C, &interaction->params, callbacks->arg1, interaction->user_data); +} + +/** + * \note #ui_block_interaction_begin cannot be called when setting the button state + * (e.g. #BUTTON_STATE_NUM_EDITING) for the following reasons. + * + * - Other buttons may still be activated using #UI_BUT_DRAG_MULTI + * which is necessary before gathering all the #uiBut.retval values to initialize + * #uiBlockInteraction_Params.unique_retval_ids. + * - When clicking on a number button it's not known if the event is a click or a drag. + * + * Instead, it must be called immediately before the drag action begins. + */ +static void ui_block_interaction_begin_ensure(bContext *C, + uiBlock *block, + uiHandleButtonData *data, + const bool is_click) +{ + if (data->custom_interaction_handle) { + return; + } + if (block->custom_interaction_callbacks.begin_fn == NULL) { + return; + } + + uiBlockInteraction_Handle *interaction = ui_block_interaction_begin(C, block, is_click); + interaction->user_count = 1; + data->custom_interaction_handle = interaction; +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index c9253e1f675..aa957afbf8f 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1519,7 +1519,7 @@ static void icon_draw_rect(float x, draw_h = h; draw_x += (w - draw_w) / 2; } - /* if the image is squared, the draw_ initialization values are good */ + /* If the image is squared, the `draw_*` initialization values are good. */ /* first allocate imbuf for scaling and copy preview into it */ ima = IMB_allocImBuf(rw, rh, 32, IB_rect); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index a05afb6e542..40a9c67c630 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -511,6 +511,9 @@ struct uiBlock { uiBlockHandleFunc handle_func; void *handle_func_arg; + /** Custom interaction data. */ + uiBlockInteraction_CallbackData custom_interaction_callbacks; + /** Custom extra event handling. */ int (*block_event_func)(const struct bContext *C, struct uiBlock *, const struct wmEvent *); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index abebc09ace2..8b9539f1d33 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -1411,7 +1411,7 @@ BLI_INLINE bool ui_layout_is_radial(const uiLayout *layout) } /** - * Create ui items for enum items in \a item_array. + * Create UI items for enum items in \a item_array. * * A version of #uiItemsFullEnumO that takes pre-calculated item array. */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index e85ec40ac73..9c17486aea4 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2399,8 +2399,8 @@ static eAutoPropButsReturn template_operator_property_buts_draw_single( op->type->ui((bContext *)C, op); op->layout = NULL; - /* UI_LAYOUT_OP_SHOW_EMPTY ignored. retun_info is ignored too. We could - * allow ot.ui callback to return this, but not needed right now. */ + /* #UI_LAYOUT_OP_SHOW_EMPTY ignored. retun_info is ignored too. + * We could allow #wmOperatorType.ui callback to return this, but not needed right now. */ } else { wmWindowManager *wm = CTX_wm_manager(C); @@ -4015,23 +4015,23 @@ static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event) case UICURVE_FUNC_RESET_VIEW: BKE_curvemapping_reset_view(cumap); break; - case UICURVE_FUNC_HANDLE_VECTOR: /* set vector */ + case UICURVE_FUNC_HANDLE_VECTOR: /* Set vector. */ BKE_curvemap_handle_set(cuma, HD_VECT); BKE_curvemapping_changed(cumap, false); break; - case UICURVE_FUNC_HANDLE_AUTO: /* set auto */ + case UICURVE_FUNC_HANDLE_AUTO: /* Set auto. */ BKE_curvemap_handle_set(cuma, HD_AUTO); BKE_curvemapping_changed(cumap, false); break; - case UICURVE_FUNC_HANDLE_AUTO_ANIM: /* set auto-clamped */ + case UICURVE_FUNC_HANDLE_AUTO_ANIM: /* Set auto-clamped. */ BKE_curvemap_handle_set(cuma, HD_AUTO_ANIM); BKE_curvemapping_changed(cumap, false); break; - case UICURVE_FUNC_EXTEND_HOZ: /* extend horiz */ + case UICURVE_FUNC_EXTEND_HOZ: /* Extend horizontal. */ cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; BKE_curvemapping_changed(cumap, false); break; - case UICURVE_FUNC_EXTEND_EXP: /* extend extrapolate */ + case UICURVE_FUNC_EXTEND_EXP: /* Extend extrapolate. */ cumap->flag |= CUMA_EXTEND_EXTRAPOLATE; BKE_curvemapping_changed(cumap, false); break; diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 057c33c779c..7ea02226f02 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -701,7 +701,7 @@ int UI_calc_float_precision(int prec, double value) /* Check on the number of decimal places need to display the number, * this is so 0.00001 is not displayed as 0.00, - * _but_, this is only for small values si 10.0001 will not get the same treatment. + * _but_, this is only for small values as 10.0001 will not get the same treatment. */ value = fabs(value); if ((value < pow10_neg[prec]) && (value > (1.0 / max_pow))) { diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index f4d9c95ae09..72847fb2476 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1377,8 +1377,6 @@ static int ui_but_draw_menu_icon(const uiBut *but) static void widget_draw_icon( const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, const uchar mono_color[4]) { - float xs = 0.0f, ys = 0.0f; - if (but->flag & UI_BUT_ICON_PREVIEW) { GPU_blend(GPU_BLEND_ALPHA); widget_draw_preview(icon, alpha, rect); @@ -1420,6 +1418,7 @@ static void widget_draw_icon( if (icon && icon != ICON_BLANK1) { const float ofs = 1.0f / aspect; + float xs, ys; if (but->drawflag & UI_BUT_ICON_LEFT) { /* special case - icon_only pie buttons */ @@ -2088,7 +2087,7 @@ static void widget_draw_text(const uiFontStyle *fstyle, but_pos_ofs = but->pos; #ifdef WITH_INPUT_IME - /* if is ime compositing, move the cursor */ + /* If is IME compositing, move the cursor. */ if (ime_data && ime_data->composite_len && ime_data->cursor_pos != -1) { but_pos_ofs += ime_data->cursor_pos; } @@ -2140,12 +2139,12 @@ static void widget_draw_text(const uiFontStyle *fstyle, } #ifdef WITH_INPUT_IME - /* ime cursor following */ + /* IME cursor following. */ if (ime_reposition_window) { ui_but_ime_reposition(but, ime_win_x, ime_win_y, false); } if (ime_data && ime_data->composite_len) { - /* composite underline */ + /* Composite underline. */ widget_draw_text_ime_underline(fstyle, wcol, but, rect, ime_data, drawstr); } #endif @@ -3720,10 +3719,6 @@ static void widget_progressbar( /* "slider" bar color */ copy_v3_v3_uchar(wcol->inner, wcol->item); widgetbase_draw(&wtb_bar, wcol); - - /* raise text a bit */ - rect->xmin += (BLI_rcti_size_x(&rect_prog) / 2); - rect->xmax += (BLI_rcti_size_x(&rect_prog) / 2); } static void widget_datasetrow( diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 73bcaee735e..1fd1b6c984d 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1745,7 +1745,7 @@ typedef struct v2dScrollerMove { * This is a CUT DOWN VERSION of the 'real' version, which is defined in view2d.c, * as we only need focus bubble info. * - * \warning: The start of this struct must not change, + * \warning The start of this struct must not change, * so that it stays in sync with the 'real' version. * For now, we don't need to have a separate (internal) header for structs like this... */ diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 28838d677f0..12890552b1d 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -63,10 +63,26 @@ # include "WM_api.h" # include "WM_types.h" +# include "DEG_depsgraph.h" + # include "io_alembic.h" # include "ABC_alembic.h" +const EnumPropertyItem rna_enum_abc_export_evaluation_mode_items[] = { + {DAG_EVAL_RENDER, + "RENDER", + 0, + "Render", + "Use Render settings for object visibility, modifier settings, etc"}, + {DAG_EVAL_VIEWPORT, + "VIEWPORT", + 0, + "Viewport", + "Use Viewport settings for object visibility, modifier settings, etc"}, + {0, NULL, 0, NULL, NULL}, +}; + static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (!RNA_struct_property_is_set(op->ptr, "as_background_job")) { @@ -126,7 +142,6 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) .curves_as_mesh = RNA_boolean_get(op->ptr, "curves_as_mesh"), .flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"), .visible_objects_only = RNA_boolean_get(op->ptr, "visible_objects_only"), - .renderable_only = RNA_boolean_get(op->ptr, "renderable_only"), .face_sets = RNA_boolean_get(op->ptr, "face_sets"), .use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"), .export_hair = RNA_boolean_get(op->ptr, "export_hair"), @@ -137,6 +152,7 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) .triangulate = RNA_boolean_get(op->ptr, "triangulate"), .quad_method = RNA_enum_get(op->ptr, "quad_method"), .ngon_method = RNA_enum_get(op->ptr, "ngon_method"), + .evaluation_mode = RNA_enum_get(op->ptr, "evaluation_mode"), .global_scale = RNA_float_get(op->ptr, "global_scale"), }; @@ -194,9 +210,11 @@ static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr) sub = uiLayoutColumnWithHeading(col, true, IFACE_("Only")); uiItemR(sub, imfptr, "selected", 0, IFACE_("Selected Objects"), ICON_NONE); - uiItemR(sub, imfptr, "renderable_only", 0, IFACE_("Renderable Objects"), ICON_NONE); uiItemR(sub, imfptr, "visible_objects_only", 0, IFACE_("Visible Objects"), ICON_NONE); + col = uiLayoutColumn(box, true); + uiItemR(col, imfptr, "evaluation_mode", 0, NULL, ICON_NONE); + /* Object Data */ box = uiLayoutBox(layout); row = uiLayoutRow(box, false); @@ -355,12 +373,6 @@ void WM_OT_alembic_export(wmOperatorType *ot) ot->srna, "selected", 0, "Selected Objects Only", "Export only selected objects"); RNA_def_boolean(ot->srna, - "renderable_only", - 1, - "Renderable Objects Only", - "Export only objects marked renderable in the outliner"); - - RNA_def_boolean(ot->srna, "visible_objects_only", 0, "Visible Objects Only", @@ -468,6 +480,14 @@ void WM_OT_alembic_export(wmOperatorType *ot) "This option is deprecated; EXECUTE this operator to run in the foreground, and INVOKE it " "to run as a background job"); + RNA_def_enum(ot->srna, + "evaluation_mode", + rna_enum_abc_export_evaluation_mode_items, + DAG_EVAL_RENDER, + "Use Settings for", + "Determines visibility of objects, modifier settings, and other areas where there " + "are different settings for viewport and rendering"); + /* This dummy prop is used to check whether we need to init the start and * end frame values to that of the scene's, otherwise they are reset at * every change, draw update. */ diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c index d92a81179cc..23eaf991fd3 100644 --- a/source/blender/editors/lattice/editlattice_undo.c +++ b/source/blender/editors/lattice/editlattice_undo.c @@ -240,7 +240,7 @@ static void lattice_undosys_step_decode(struct bContext *C, } undolatt_to_editlatt(&elem->data, lt->editlatt); lt->editlatt->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(<->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index 942fe143787..09b17acf56d 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -30,6 +30,7 @@ #include "BKE_context.h" #include "BKE_curve.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index 993905462db..cccfc7e934c 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -126,7 +126,7 @@ static int geometry_extract_apply(bContext *C, .calc_face_normal = true, })); - BMEditMesh *em = BKE_editmesh_create(bm, false); + BMEditMesh *em = BKE_editmesh_create(bm); /* Generate the tags for deleting geometry in the extracted object. */ tag_fn(bm, params); @@ -206,7 +206,7 @@ static int geometry_extract_apply(bContext *C, }), mesh); - BKE_editmesh_free(em); + BKE_editmesh_free_data(em); MEM_freeN(em); if (new_mesh->totvert == 0) { diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index 593545ddcef..30a453a32ee 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -29,6 +29,7 @@ #include "DNA_windowmanager_types.h" #ifdef WITH_FREESTYLE +# include "BKE_customdata.h" # include "DNA_meshdata_types.h" #endif diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 132a442343c..830c9abb41e 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -35,6 +35,7 @@ #include "BLI_utildefines_stack.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_layer.h" diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index f52ab48785d..c452f7a7487 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -29,6 +29,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_layer.h" diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 4d383140d80..41a9f426798 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -44,6 +44,7 @@ #include "BLI_string.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_key.h" @@ -973,7 +974,7 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) #ifdef USE_FACE_CREATE_SEL_EXTEND /* normally we would want to leave the new geometry selected, * but being able to press F many times to add geometry is too useful! */ - if (ele_desel && (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) && + if (ele_desel && (BMO_slot_buffer_len(bmop.slots_out, "faces.out") == 1) && (ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out"))) { edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face); } @@ -2344,7 +2345,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) BMO_slot_buffer_hflag_enable( em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true); - const int tot_rotate = BMO_slot_buffer_count(bmop.slots_out, "edges.out"); + const int tot_rotate = BMO_slot_buffer_len(bmop.slots_out, "edges.out"); const int tot_failed = tot - tot_rotate; tot_rotate_all += tot_rotate; @@ -6560,7 +6561,7 @@ enum { typedef struct BMElemSort { /** Sort factor */ float srt; - /** Original index of this element _in its mempool_ */ + /** Original index of this element (in its #BLI_mempool). */ int org_idx; } BMElemSort; diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 112de68b52c..fc9e1aa8b1a 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -33,6 +33,7 @@ #include "BLI_listbase.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_key.h" #include "BKE_layer.h" @@ -671,7 +672,7 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key * em->bm->shapenr = um->shapenr; - EDBM_mesh_free(em); + EDBM_mesh_free_data(em); bm = BM_mesh_create(&allocsize, &((struct BMeshCreateParams){ @@ -681,13 +682,21 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key * BM_mesh_bm_from_me(bm, &um->me, (&(struct BMeshFromMeshParams){ - .calc_face_normal = true, + /* Handled with tessellation. */ + .calc_face_normal = false, .active_shapekey = um->shapenr, })); - em_tmp = BKE_editmesh_create(bm, true); + em_tmp = BKE_editmesh_create(bm); *em = *em_tmp; + /* Calculate face normals and tessellation at once since it's multi-threaded. + * The vertex normals are stored in the undo-mesh, so this doesn't need to be updated. */ + BKE_editmesh_looptri_calc_ex(em, + &(const struct BMeshCalcTessellation_Params){ + .face_normals = true, + }); + em->selectmode = um->selectmode; bm->selectmode = um->selectmode; @@ -865,7 +874,7 @@ static void mesh_undosys_step_decode(struct bContext *C, BMEditMesh *em = me->edit_mesh; undomesh_to_editmesh(&elem->data, obedit, em, me->key); em->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 4f416c94f62..85c646d689c 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -305,17 +305,13 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) if (me->edit_mesh) { /* this happens when switching shape keys */ - EDBM_mesh_free(me->edit_mesh); + EDBM_mesh_free_data(me->edit_mesh); MEM_freeN(me->edit_mesh); } - /* currently executing operators re-tessellates, so we can avoid doing here - * but at some point it may need to be added back. */ -#if 0 - me->edit_mesh = BKE_editmesh_create(bm, true); -#else - me->edit_mesh = BKE_editmesh_create(bm, false); -#endif + /* Executing operators re-tessellates, + * so we can avoid doing here but at some point it may need to be added back. */ + me->edit_mesh = BKE_editmesh_create(bm); me->edit_mesh->selectmode = me->edit_mesh->bm->selectmode = select_mode; me->edit_mesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0; @@ -326,7 +322,8 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) /** * \warning This can invalidate the #Mesh runtime cache of other objects (for linked duplicates). - * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913 + * Most callers should run #DEG_id_tag_update on `ob->data`, see: T46738, T46913. + * This ensures #BKE_object_free_derived_caches runs on all objects that use this mesh. */ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data) { @@ -346,25 +343,6 @@ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data) .calc_object_remap = true, .update_shapekey_indices = !free_data, })); - - /* Free derived mesh. usually this would happen through depsgraph but there - * are exceptions like file save that will not cause this, and we want to - * avoid ending up with an invalid derived mesh then. - * - * Do it for all objects which shares the same mesh datablock, since their - * derived meshes might also be referencing data which was just freed, - * - * Annoying enough, but currently seems most efficient way to avoid access - * of freed data on scene update, especially in cases when there are dependency - * cycles. - */ -#if 0 - for (Object *other_object = bmain->objects.first; other_object != NULL; other_object = other_object->id.next) { - if (other_object->data == ob->data) { - BKE_object_free_derived_caches(other_object); - } - } -#endif } void EDBM_mesh_clear(BMEditMesh *em) @@ -372,8 +350,8 @@ void EDBM_mesh_clear(BMEditMesh *em) /* clear bmesh */ BM_mesh_clear(em->bm); - /* free derived meshes */ - BKE_editmesh_free_derivedmesh(em); + /* Free evaluated meshes & cache. */ + BKE_editmesh_free_derived_caches(em); /* free tessellation data */ em->tottri = 0; @@ -389,9 +367,9 @@ void EDBM_mesh_load(Main *bmain, Object *ob) } /** - * Should only be called on the active editmesh, otherwise call #BKE_editmesh_free + * Should only be called on the active edit-mesh, otherwise call #BKE_editmesh_free_data. */ -void EDBM_mesh_free(BMEditMesh *em) +void EDBM_mesh_free_data(BMEditMesh *em) { /* These tables aren't used yet, so it's not strictly necessary * to 'end' them but if someone tries to start using them, @@ -399,7 +377,7 @@ void EDBM_mesh_free(BMEditMesh *em) ED_mesh_mirror_spatial_table_end(NULL); ED_mesh_mirror_topo_table_end(NULL); - BKE_editmesh_free(em); + BKE_editmesh_free_data(em); } /** \} */ @@ -1471,8 +1449,8 @@ void EDBM_update(Mesh *mesh, const struct EDBMUpdate_Params *params) BM_lnorspace_invalidate(em->bm, false); em->bm->spacearr_dirty &= ~BM_SPACEARR_BMO_SET; } - /* don't keep stale derivedMesh data around, see: T38872. */ - BKE_editmesh_free_derivedmesh(em); + /* Don't keep stale evaluated mesh data around, see: T38872. */ + BKE_editmesh_free_derived_caches(em); #ifdef DEBUG { diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 2b78d83a9f5..73b3fb9724e 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -34,6 +34,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" #include "BKE_report.h" diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c index a8b471a7c92..f7b53b5513f 100644 --- a/source/blender/editors/metaball/editmball_undo.c +++ b/source/blender/editors/metaball/editmball_undo.c @@ -215,7 +215,7 @@ static void mball_undosys_step_decode(struct bContext *C, } undomball_to_editmball(&elem->data, mb); mb->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&mb->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 6d22da2c2bc..8ae74fbfafa 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1845,7 +1845,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) * ready to be moved around to re-time the sound and/or make new sound clips. */ { /* create new data for NLA hierarchy */ - AnimData *adt = BKE_animdata_add_id(&ob->id); + AnimData *adt = BKE_animdata_ensure_id(&ob->id); NlaTrack *nlt = BKE_nlatrack_add(adt, NULL, is_liboverride); NlaStrip *strip = BKE_nla_add_soundstrip(bmain, scene, ob->data); strip->start = CFRA; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 1cb6a5c8ff5..6108691b2f1 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -557,7 +557,7 @@ static bool ED_object_editmode_load_free_ex(Main *bmain, } if (free_data) { - EDBM_mesh_free(me->edit_mesh); + EDBM_mesh_free_data(me->edit_mesh); MEM_freeN(me->edit_mesh); me->edit_mesh = NULL; } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 30f75e9a150..d7177eabcba 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2061,6 +2061,23 @@ static void single_object_action_users( FOREACH_OBJECT_FLAG_END; } +static void single_objectdata_action_users( + Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag) +{ + FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) { + if (!ID_IS_LINKED(ob) && ob->data != NULL) { + ID *id_obdata = (ID *)ob->data; + AnimData *adt = BKE_animdata_from_id(id_obdata); + ID *id_act = (ID *)adt->action; + if (id_act && id_act->us > 1) { + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + BKE_animdata_copy_id_action(bmain, id_obdata); + } + } + } + FOREACH_OBJECT_FLAG_END; +} + static void single_mat_users( Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag) { @@ -2643,6 +2660,10 @@ static int make_single_user_exec(bContext *C, wmOperator *op) single_object_action_users(bmain, scene, view_layer, v3d, flag); } + if (RNA_boolean_get(op->ptr, "obdata_animation")) { + single_objectdata_action_users(bmain, scene, view_layer, v3d, flag); + } + BKE_main_id_newptr_and_tag_clear(bmain); WM_event_add_notifier(C, NC_WINDOW, NULL); @@ -2684,8 +2705,16 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot) RNA_def_boolean(ot->srna, "object", 0, "Object", "Make single user objects"); RNA_def_boolean(ot->srna, "obdata", 0, "Object Data", "Make single user object data"); RNA_def_boolean(ot->srna, "material", 0, "Materials", "Make materials local to each data-block"); - RNA_def_boolean( - ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object"); + RNA_def_boolean(ot->srna, + "animation", + 0, + "Object Animation", + "Make object animation data local to each object"); + RNA_def_boolean(ot->srna, + "obdata_animation", + 0, + "Object Data Animation", + "Make object data (mesh, curve etc.) animation data local to each object"); } /** \} */ diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index e350653e178..4c4727f51ee 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1152,51 +1152,53 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) for (int object_index = 0; object_index < num_objects; object_index++) { Object *ob = objects[object_index]; + if (ob->flag & OB_DONE) { + continue; + } - if ((ob->flag & OB_DONE) == 0) { - bool do_inverse_offset = false; - ob->flag |= OB_DONE; + bool do_inverse_offset = false; + ob->flag |= OB_DONE; - if (centermode == ORIGIN_TO_CURSOR) { - copy_v3_v3(cent, cursor); - invert_m4_m4(ob->imat, ob->obmat); - mul_m4_v3(ob->imat, cent); - } + if (centermode == ORIGIN_TO_CURSOR) { + copy_v3_v3(cent, cursor); + invert_m4_m4(ob->imat, ob->obmat); + mul_m4_v3(ob->imat, cent); + } - if (ob->data == NULL) { - /* special support for dupligroups */ - if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection && - (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) { - if (ID_IS_LINKED(ob->instance_collection)) { - tot_lib_error++; + if (ob->data == NULL) { + /* special support for dupligroups */ + if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection && + (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) { + if (ID_IS_LINKED(ob->instance_collection)) { + tot_lib_error++; + } + else { + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ } else { - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else { - float min[3], max[3]; - /* only bounds support */ - INIT_MINMAX(min, max); - BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true); - mid_v3_v3v3(cent, min, max); - invert_m4_m4(ob->imat, ob->obmat); - mul_m4_v3(ob->imat, cent); - } + float min[3], max[3]; + /* only bounds support */ + INIT_MINMAX(min, max); + BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true); + mid_v3_v3v3(cent, min, max); + invert_m4_m4(ob->imat, ob->obmat); + mul_m4_v3(ob->imat, cent); + } - add_v3_v3(ob->instance_collection->instance_offset, cent); + add_v3_v3(ob->instance_collection->instance_offset, cent); - tot_change++; - ob->instance_collection->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; - } + tot_change++; + ob->instance_collection->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; } } - else if (ID_IS_LINKED(ob->data)) { - tot_lib_error++; - } - - if (obedit == NULL && ob->type == OB_MESH) { + } + else if (ID_IS_LINKED(ob->data)) { + tot_lib_error++; + } + else if (ob->type == OB_MESH) { + if (obedit == NULL) { Mesh *me = ob->data; if (centermode == ORIGIN_TO_CURSOR) { @@ -1222,265 +1224,265 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) me->id.tag |= LIB_TAG_DOIT; do_inverse_offset = true; } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { - Curve *cu = ob->data; + } + else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + Curve *cu = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else if (around == V3D_AROUND_CENTER_BOUNDS) { - BKE_curve_center_bounds(cu, cent); - } - else { /* #V3D_AROUND_CENTER_MEDIAN. */ - BKE_curve_center_median(cu, cent); - } + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ + } + else if (around == V3D_AROUND_CENTER_BOUNDS) { + BKE_curve_center_bounds(cu, cent); + } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_curve_center_median(cu, cent); + } - /* don't allow Z change if curve is 2D */ - if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) { - cent[2] = 0.0; - } + /* don't allow Z change if curve is 2D */ + if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) { + cent[2] = 0.0; + } - negate_v3_v3(cent_neg, cent); - BKE_curve_translate(cu, cent_neg, 1); + negate_v3_v3(cent_neg, cent); + BKE_curve_translate(cu, cent_neg, 1); - tot_change++; - cu->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; + tot_change++; + cu->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; - if (obedit) { - if (centermode == GEOMETRY_TO_ORIGIN) { - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); - } - break; + if (obedit) { + if (centermode == GEOMETRY_TO_ORIGIN) { + DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } + break; } - else if (ob->type == OB_FONT) { - /* Get from bounding-box. */ + } + else if (ob->type == OB_FONT) { + /* Get from bounding-box. */ - Curve *cu = ob->data; + Curve *cu = ob->data; - if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) { - /* Do nothing. */ + if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) { + /* Do nothing. */ + } + else { + if (centermode == ORIGIN_TO_CURSOR) { + /* Done. */ } else { - if (centermode == ORIGIN_TO_CURSOR) { - /* Done. */ - } - else { - /* extra 0.5 is the height o above line */ - cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]); - cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]); - } + /* extra 0.5 is the height o above line */ + cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]); + cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]); + } - cent[2] = 0.0f; + cent[2] = 0.0f; - cu->xof = cu->xof - cent[0]; - cu->yof = cu->yof - cent[1]; + cu->xof = cu->xof - cent[0]; + cu->yof = cu->yof - cent[1]; - tot_change++; - cu->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; - } + tot_change++; + cu->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; } - else if (ob->type == OB_ARMATURE) { - bArmature *arm = ob->data; + } + else if (ob->type == OB_ARMATURE) { + bArmature *arm = ob->data; - if (ID_REAL_USERS(arm) > 1) { + if (ID_REAL_USERS(arm) > 1) { #if 0 BKE_report(op->reports, RPT_ERROR, "Cannot apply to a multi user armature"); return; #endif - tot_multiuser_arm_error++; - } - else { - /* Function to recenter armatures in editarmature.c - * Bone + object locations are handled there. - */ - ED_armature_origin_set(bmain, ob, cursor, centermode, around); + tot_multiuser_arm_error++; + } + else { + /* Function to recenter armatures in editarmature.c + * Bone + object locations are handled there. + */ + ED_armature_origin_set(bmain, ob, cursor, centermode, around); - tot_change++; - arm->id.tag |= LIB_TAG_DOIT; - /* do_inverse_offset = true; */ /* docenter_armature() handles this */ + tot_change++; + arm->id.tag |= LIB_TAG_DOIT; + /* do_inverse_offset = true; */ /* docenter_armature() handles this */ - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - BKE_object_transform_copy(ob_eval, ob); - BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); - BKE_object_where_is_calc(depsgraph, scene, ob_eval); - BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */ + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + BKE_object_transform_copy(ob_eval, ob); + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); + BKE_object_where_is_calc(depsgraph, scene, ob_eval); + BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */ - ignore_parent_tx(bmain, depsgraph, scene, ob); + ignore_parent_tx(bmain, depsgraph, scene, ob); - if (obedit) { - break; - } + if (obedit) { + break; } } - else if (ob->type == OB_MBALL) { - MetaBall *mb = ob->data; + } + else if (ob->type == OB_MBALL) { + MetaBall *mb = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else if (around == V3D_AROUND_CENTER_BOUNDS) { - BKE_mball_center_bounds(mb, cent); - } - else { /* #V3D_AROUND_CENTER_MEDIAN. */ - BKE_mball_center_median(mb, cent); - } + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ + } + else if (around == V3D_AROUND_CENTER_BOUNDS) { + BKE_mball_center_bounds(mb, cent); + } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_mball_center_median(mb, cent); + } - negate_v3_v3(cent_neg, cent); - BKE_mball_translate(mb, cent_neg); + negate_v3_v3(cent_neg, cent); + BKE_mball_translate(mb, cent_neg); - tot_change++; - mb->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; + tot_change++; + mb->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; - if (obedit) { - if (centermode == GEOMETRY_TO_ORIGIN) { - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); - } - break; + if (obedit) { + if (centermode == GEOMETRY_TO_ORIGIN) { + DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } + break; } - else if (ob->type == OB_LATTICE) { - Lattice *lt = ob->data; + } + else if (ob->type == OB_LATTICE) { + Lattice *lt = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else if (around == V3D_AROUND_CENTER_BOUNDS) { - BKE_lattice_center_bounds(lt, cent); - } - else { /* #V3D_AROUND_CENTER_MEDIAN. */ - BKE_lattice_center_median(lt, cent); - } + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ + } + else if (around == V3D_AROUND_CENTER_BOUNDS) { + BKE_lattice_center_bounds(lt, cent); + } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_lattice_center_median(lt, cent); + } - negate_v3_v3(cent_neg, cent); - BKE_lattice_translate(lt, cent_neg, 1); + negate_v3_v3(cent_neg, cent); + BKE_lattice_translate(lt, cent_neg, 1); - tot_change++; - lt->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; - } - else if (ob->type == OB_GPENCIL) { - bGPdata *gpd = ob->data; - float gpcenter[3]; - if (gpd) { - if (centermode == ORIGIN_TO_GEOMETRY) { - zero_v3(gpcenter); - BKE_gpencil_centroid_3d(gpd, gpcenter); - add_v3_v3(gpcenter, ob->obmat[3]); - } - if (centermode == ORIGIN_TO_CURSOR) { - copy_v3_v3(gpcenter, cursor); - } - if (ELEM(centermode, ORIGIN_TO_GEOMETRY, ORIGIN_TO_CURSOR)) { - bGPDspoint *pt; - float imat[3][3], bmat[3][3]; - float offset_global[3]; - float offset_local[3]; - int i; - - sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]); - copy_m3_m4(bmat, obact->obmat); - invert_m3_m3(imat, bmat); - mul_m3_v3(imat, offset_global); - mul_v3_m3v3(offset_local, imat, offset_global); - - float diff_mat[4][4]; - float inverse_diff_mat[4][4]; - - /* recalculate all strokes - * (all layers are considered without evaluating lock attributes) */ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* calculate difference matrix */ - BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); - /* undo matrix */ - invert_m4_m4(inverse_diff_mat, diff_mat); - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - float mpt[3]; - mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x); - sub_v3_v3(mpt, offset_local); - mul_v3_m4v3(&pt->x, diff_mat, mpt); - } + tot_change++; + lt->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; + } + else if (ob->type == OB_GPENCIL) { + bGPdata *gpd = ob->data; + float gpcenter[3]; + if (gpd) { + if (centermode == ORIGIN_TO_GEOMETRY) { + zero_v3(gpcenter); + BKE_gpencil_centroid_3d(gpd, gpcenter); + add_v3_v3(gpcenter, ob->obmat[3]); + } + if (centermode == ORIGIN_TO_CURSOR) { + copy_v3_v3(gpcenter, cursor); + } + if (ELEM(centermode, ORIGIN_TO_GEOMETRY, ORIGIN_TO_CURSOR)) { + bGPDspoint *pt; + float imat[3][3], bmat[3][3]; + float offset_global[3]; + float offset_local[3]; + int i; + + sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]); + copy_m3_m4(bmat, obact->obmat); + invert_m3_m3(imat, bmat); + mul_m3_v3(imat, offset_global); + mul_v3_m3v3(offset_local, imat, offset_global); + + float diff_mat[4][4]; + float inverse_diff_mat[4][4]; + + /* recalculate all strokes + * (all layers are considered without evaluating lock attributes) */ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* calculate difference matrix */ + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + /* undo matrix */ + invert_m4_m4(inverse_diff_mat, diff_mat); + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + float mpt[3]; + mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x); + sub_v3_v3(mpt, offset_local); + mul_v3_m4v3(&pt->x, diff_mat, mpt); } } } - tot_change++; - if (centermode == ORIGIN_TO_GEOMETRY) { - copy_v3_v3(ob->loc, gpcenter); - } - DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); - - ob->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; } - else { - BKE_report(op->reports, - RPT_WARNING, - "Grease Pencil Object does not support this set origin option"); + tot_change++; + if (centermode == ORIGIN_TO_GEOMETRY) { + copy_v3_v3(ob->loc, gpcenter); } + DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); + + ob->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; + } + else { + BKE_report(op->reports, + RPT_WARNING, + "Grease Pencil Object does not support this set origin option"); } } + } - /* offset other selected objects */ - if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) { - float obmat[4][4]; + /* offset other selected objects */ + if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) { + float obmat[4][4]; - /* was the object data modified - * NOTE: the functions above must set 'cent'. */ + /* was the object data modified + * NOTE: the functions above must set 'cent'. */ - /* convert the offset to parent space */ - BKE_object_to_mat4(ob, obmat); - mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */ + /* convert the offset to parent space */ + BKE_object_to_mat4(ob, obmat); + mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */ - add_v3_v3(ob->loc, centn); + add_v3_v3(ob->loc, centn); - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - BKE_object_transform_copy(ob_eval, ob); - BKE_object_where_is_calc(depsgraph, scene, ob_eval); - if (ob->type == OB_ARMATURE) { - /* needed for bone parents */ - BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); - BKE_pose_where_is(depsgraph, scene, ob_eval); - } - - ignore_parent_tx(bmain, depsgraph, scene, ob); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + BKE_object_transform_copy(ob_eval, ob); + BKE_object_where_is_calc(depsgraph, scene, ob_eval); + if (ob->type == OB_ARMATURE) { + /* needed for bone parents */ + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); + BKE_pose_where_is(depsgraph, scene, ob_eval); + } - /* other users? */ - // CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects) - //{ - - /* use existing context looper */ - for (int other_object_index = 0; other_object_index < num_objects; other_object_index++) { - Object *ob_other = objects[other_object_index]; - - if ((ob_other->flag & OB_DONE) == 0 && - ((ob->data && (ob->data == ob_other->data)) || - (ob->instance_collection == ob_other->instance_collection && - (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION))) { - ob_other->flag |= OB_DONE; - DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - - mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */ - add_v3_v3(ob_other->loc, centn); - - Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other); - BKE_object_transform_copy(ob_other_eval, ob_other); - BKE_object_where_is_calc(depsgraph, scene, ob_other_eval); - if (ob_other->type == OB_ARMATURE) { - /* needed for bone parents */ - BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); - BKE_pose_where_is(depsgraph, scene, ob_other_eval); - } - ignore_parent_tx(bmain, depsgraph, scene, ob_other); + ignore_parent_tx(bmain, depsgraph, scene, ob); + + /* other users? */ + // CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects) + //{ + + /* use existing context looper */ + for (int other_object_index = 0; other_object_index < num_objects; other_object_index++) { + Object *ob_other = objects[other_object_index]; + + if ((ob_other->flag & OB_DONE) == 0 && + ((ob->data && (ob->data == ob_other->data)) || + (ob->instance_collection == ob_other->instance_collection && + (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION))) { + ob_other->flag |= OB_DONE; + DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + + mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */ + add_v3_v3(ob_other->loc, centn); + + Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other); + BKE_object_transform_copy(ob_other_eval, ob_other); + BKE_object_where_is_calc(depsgraph, scene, ob_other_eval); + if (ob_other->type == OB_ARMATURE) { + /* needed for bone parents */ + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); + BKE_pose_where_is(depsgraph, scene, ob_other_eval); } + ignore_parent_tx(bmain, depsgraph, scene, ob_other); } - // CTX_DATA_END; } + // CTX_DATA_END; } } MEM_freeN(objects); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index c591931805d..39de63c22a9 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1539,8 +1539,8 @@ static void region_rect_recursive( region->winx = BLI_rcti_size_x(®ion->winrct) + 1; region->winy = BLI_rcti_size_y(®ion->winrct) + 1; - /* if region opened normally, we store this for hide/reveal usage */ - /* prevent rounding errors for UI_DPI_FAC mult and divide */ + /* If region opened normally, we store this for hide/reveal usage. */ + /* Prevent rounding errors for UI_DPI_FAC multiply and divide. */ if (region->winx > 1) { region->sizex = (region->winx + 0.5f) / UI_DPI_FAC; } diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index a888958b9be..bd05d309421 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -2052,7 +2052,7 @@ static bool line_clip_rect2f(const rctf *cliprect, float l2_clip[2]) { /* first account for horizontal, then vertical lines */ - /* horiz */ + /* Horizontal. */ if (fabsf(l1[1] - l2[1]) < PROJ_PIXEL_TOLERANCE) { /* is the line out of range on its Y axis? */ if (l1[1] < rect->ymin || l1[1] > rect->ymax) { diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index da34723eed4..d968b6cc319 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -293,8 +293,8 @@ typedef struct SculptGestureContext { /* These store the view origin and normal in world space, which is used in some gestures to * generate geometry aligned from the view directly in world space. */ /* World space view origin and normal are not affected by object symmetry when doing symmetry - * passes, so there is no separate variables with the true_ prefix to store their original values - * without symmetry modifications. */ + * passes, so there is no separate variables with the `true_` prefix to store their original + * values without symmetry modifications. */ float world_space_view_origin[3]; float world_space_view_normal[3]; diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index fe7029c7457..f21c900941b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -1608,7 +1608,7 @@ void ED_sculpt_undosys_type(UndoType *ut) ut->step_decode = sculpt_undosys_step_decode; ut->step_free = sculpt_undosys_step_free; - ut->flags = 0; + ut->flags = UNDOTYPE_FLAG_DECODE_ACTIVE_STEP; ut->step_size = sizeof(SculptUndoStep); } diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index 9e69b0a72db..d69c7ab8d48 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -813,7 +813,7 @@ static int action_layer_next_exec(bContext *C, wmOperator *op) NlaTrack *act_track; Scene *scene = CTX_data_scene(C); - float ctime = BKE_scene_frame_get(scene); + float ctime = BKE_scene_ctime_get(scene); /* Get active track */ act_track = BKE_nlatrack_find_tweaked(adt); @@ -925,7 +925,7 @@ static int action_layer_prev_exec(bContext *C, wmOperator *op) NlaTrack *nlt; Scene *scene = CTX_data_scene(C); - float ctime = BKE_scene_frame_get(scene); + float ctime = BKE_scene_ctime_get(scene); /* Sanity Check */ if (adt == NULL) { diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 4d568017b4f..faa4b3cc9cc 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -523,6 +523,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) char orgname[FILE_MAX + 12]; char filename[FILE_MAX + 12]; wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); ARegion *region = CTX_wm_region(C); FileSelectParams *params = ED_fileselect_get_active_params(sfile); @@ -542,12 +543,16 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) else { /* If rename is successful, scroll to newly renamed entry. */ BLI_strncpy(params->renamefile, filename, sizeof(params->renamefile)); - file_params_invoke_rename_postscroll(wm, CTX_wm_window(C), sfile); + file_params_invoke_rename_postscroll(wm, win, sfile); } /* to make sure we show what is on disk */ ED_fileselect_clear(wm, sfile); } + else { + /* Renaming failed, reset the name for further renaming handling. */ + BLI_strncpy(params->renamefile, oldname, sizeof(params->renamefile)); + } ED_region_tag_redraw(region); } @@ -812,6 +817,8 @@ static void draw_details_columns(const FileSelectParams *params, void file_draw_list(const bContext *C, ARegion *region) { + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileLayout *layout = ED_fileselect_get_layout(sfile, region); @@ -882,12 +889,12 @@ void file_draw_list(const bContext *C, ARegion *region) // printf("%s: preview task: %d\n", __func__, previews_running); if (previews_running && !sfile->previews_timer) { sfile->previews_timer = WM_event_add_timer_notifier( - CTX_wm_manager(C), CTX_wm_window(C), NC_SPACE | ND_SPACE_FILE_PREVIEW, 0.01); + wm, win, NC_SPACE | ND_SPACE_FILE_PREVIEW, 0.01); } if (!previews_running && sfile->previews_timer) { /* Preview is not running, no need to keep generating update events! */ // printf("%s: Inactive preview task, sleeping!\n", __func__); - WM_event_remove_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C), sfile->previews_timer); + WM_event_remove_timer_notifier(wm, win, sfile->previews_timer); sfile->previews_timer = NULL; } } @@ -998,8 +1005,19 @@ void file_draw_list(const bContext *C, ARegion *region) UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* allow non utf8 names */ UI_but_flag_disable(but, UI_BUT_UNDO); if (false == UI_but_active_only(C, region, block, but)) { - file_selflag = filelist_entry_select_set( - sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL); + /* Note that this is the only place where we can also handle a cancelled renaming. */ + + file_params_rename_end(wm, win, sfile, file); + + /* After the rename button is removed, we need to make sure the view is redrawn once more, + * in case selection changed. Usually UI code would trigger that redraw, but the rename + * operator may have been called from a different region. + * Tagging regions for redrawing while drawing is rightfully prevented. However, this + * active button removing basically introduces handling logic to drawing code. So a + * notifier should be an acceptable workaround. */ + WM_event_add_notifier_ex(wm, win, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + + file_selflag = filelist_entry_select_get(sfile->files, file, CHECK_ALL); } } diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index b2182c45f2a..0bbed65671c 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -109,6 +109,7 @@ FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d, float file_string_width(const char *str); float file_font_pointsize(void); +void file_select_deselect_all(SpaceFile *sfile, uint flag); int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file); int autocomplete_directory(struct bContext *C, char *str, void *arg_v); int autocomplete_file(struct bContext *C, char *str, void *arg_v); @@ -120,6 +121,10 @@ void file_params_renamefile_clear(struct FileSelectParams *params); void file_params_invoke_rename_postscroll(struct wmWindowManager *wm, struct wmWindow *win, SpaceFile *sfile); +void file_params_rename_end(struct wmWindowManager *wm, + struct wmWindow *win, + SpaceFile *sfile, + struct FileDirEntry *rename_file); void file_params_renamefile_activate(struct SpaceFile *sfile, struct FileSelectParams *params); typedef void *onReloadFnData; diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 612f3a67aa3..995383d9d0e 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -104,15 +104,6 @@ static FileSelection find_file_mouse_rect(SpaceFile *sfile, return sel; } -static void file_deselect_all(SpaceFile *sfile, uint flag) -{ - FileSelection sel; - sel.first = 0; - sel.last = filelist_files_ensure(sfile->files) - 1; - - filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL); -} - typedef enum FileSelect { FILE_SELECT_NOTHING = 0, FILE_SELECT_DIR = 1, @@ -239,7 +230,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen) } /** - * \warning: loops over all files so better use cautiously + * \warning Loops over all files so better use cautiously. */ static bool file_is_any_selected(struct FileList *files) { @@ -444,7 +435,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve if ((sel.first != params->sel_first) || (sel.last != params->sel_last)) { int idx; - file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); + file_select_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); filelist_entries_select_index_range_set( sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); @@ -472,7 +463,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve params->highlight_file = -1; params->sel_first = params->sel_last = -1; fileselect_file_set(sfile, params->active_file); - file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); + file_select_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); } @@ -491,7 +482,7 @@ static int file_box_select_exec(bContext *C, wmOperator *op) const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); const bool select = (sel_op != SEL_OP_SUB); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - file_deselect_all(sfile, FILE_SEL_SELECTED); + file_select_deselect_all(sfile, FILE_SEL_SELECTED); } ED_fileselect_layout_isect_rect(sfile->layout, ®ion->v2d, &rect, &rect); @@ -573,7 +564,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) if ((idx >= 0) && (idx < numfiles)) { /* single select, deselect all selected first */ if (!extend) { - file_deselect_all(sfile, FILE_SEL_SELECTED); + file_select_deselect_all(sfile, FILE_SEL_SELECTED); } } } @@ -588,7 +579,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (ret == FILE_SELECT_NOTHING) { if (deselect_all) { - file_deselect_all(sfile, FILE_SEL_SELECTED); + file_select_deselect_all(sfile, FILE_SEL_SELECTED); } } else if (ret == FILE_SELECT_DIR) { @@ -721,7 +712,7 @@ static bool file_walk_select_selection_set(wmWindow *win, } else { /* deselect all first */ - file_deselect_all(sfile, FILE_SEL_SELECTED); + file_select_deselect_all(sfile, FILE_SEL_SELECTED); /* highlight file under mouse pos */ params->highlight_file = -1; @@ -2349,6 +2340,7 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) /* If we don't enter the directory directly, remember file to jump into editing. */ if (do_diropen == false) { + BLI_assert(params->rename_id == NULL || !"File rename handling should immediately clear rename_id when done, because otherwise it will keep taking precedence over renamefile."); BLI_strncpy(params->renamefile, name, FILE_MAXFILE); rename_flag = FILE_PARAMS_RENAME_PENDING; } diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index ecd21907ed1..0e15538e03b 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -2016,19 +2016,21 @@ FileDirEntry *filelist_file(struct FileList *filelist, int index) return filelist_file_ex(filelist, index, true); } -int filelist_file_findpath(struct FileList *filelist, const char *filename) +/** + * Find a file from a file name, or more precisely, its file-list relative path, inside the + * filtered items. \return The index of the found file or -1. + */ +int filelist_file_find_path(struct FileList *filelist, const char *filename) { - int fidx = -1; - if (filelist->filelist.nbr_entries_filtered == FILEDIR_NBR_ENTRIES_UNSET) { - return fidx; + return -1; } /* XXX TODO: Cache could probably use a ghash on paths too? Not really urgent though. * This is only used to find again renamed entry, * annoying but looks hairy to get rid of it currently. */ - for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) { + for (int fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) { FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx]; if (STREQ(entry->relpath, filename)) { return fidx; @@ -2039,6 +2041,26 @@ int filelist_file_findpath(struct FileList *filelist, const char *filename) } /** + * Find a file representing \a id. + * \return The index of the found file or -1. + */ +int filelist_file_find_id(const FileList *filelist, const ID *id) +{ + if (filelist->filelist.nbr_entries_filtered == FILEDIR_NBR_ENTRIES_UNSET) { + return -1; + } + + for (int fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) { + FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx]; + if (entry->local_data.id == id) { + return fidx; + } + } + + return -1; +} + +/** * Get the ID a file represents (if any). For #FILE_MAIN, #FILE_MAIN_ASSET. */ ID *filelist_file_get_id(const FileDirEntry *file) @@ -2068,9 +2090,6 @@ void filelist_uid_unset(FileUID *r_uid) *r_uid = FILE_UID_UNSET; } -/** - * \warning: The UID will only be valid for the current session. Use as runtime data only! - */ void filelist_file_cache_slidingwindow_set(FileList *filelist, size_t window_size) { /* Always keep it power of 2, in [256, 8192] range for now, diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index e6c4b8e1a07..0aace74e621 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -97,7 +97,8 @@ int filelist_needs_reading(struct FileList *filelist); FileDirEntry *filelist_file(struct FileList *filelist, int index); FileDirEntry *filelist_file_ex(struct FileList *filelist, int index, bool use_request); -int filelist_file_findpath(struct FileList *filelist, const char *file); +int filelist_file_find_path(struct FileList *filelist, const char *file); +int filelist_file_find_id(const struct FileList *filelist, const struct ID *id); struct ID *filelist_file_get_id(const struct FileDirEntry *file); bool filelist_uid_is_set(const FileUID uid); void filelist_uid_unset(FileUID *r_uid); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 4e59e4ba06e..b7accbf71e5 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -1086,6 +1086,15 @@ void ED_file_change_dir(bContext *C) ED_file_change_dir_ex(C, area); } +void file_select_deselect_all(SpaceFile *sfile, uint flag) +{ + FileSelection sel; + sel.first = 0; + sel.last = filelist_files_ensure(sfile->files) - 1; + + filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL); +} + int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file) { int match = 0; @@ -1237,7 +1246,7 @@ void file_params_smoothscroll_timer_clear(wmWindowManager *wm, wmWindow *win, Sp * Set the renaming-state to #FILE_PARAMS_RENAME_POSTSCROLL_PENDING and trigger the smooth-scroll * timer. To be used right after a file was renamed. * Note that the caller is responsible for setting the correct rename-file info - * (#FileSelectParams.renamefile or #FileSelectParams.renamefile_uuid). + * (#FileSelectParams.renamefile or #FileSelectParams.rename_id). */ void file_params_invoke_rename_postscroll(wmWindowManager *wm, wmWindow *win, SpaceFile *sfile) { @@ -1252,12 +1261,40 @@ void file_params_invoke_rename_postscroll(wmWindowManager *wm, wmWindow *win, Sp sfile->scroll_offset = 0; } +/** + * To be executed whenever renaming ends (successfully or not). + */ +void file_params_rename_end(wmWindowManager *wm, + wmWindow *win, + SpaceFile *sfile, + FileDirEntry *rename_file) +{ + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + + filelist_entry_select_set( + sfile->files, rename_file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL); + + /* Ensure smooth-scroll timer is active, even if not needed, because that way rename state is + * handled properly. */ + file_params_invoke_rename_postscroll(wm, win, sfile); + /* Also always activate the rename file, even if renaming was cancelled. */ + file_params_renamefile_activate(sfile, params); +} + void file_params_renamefile_clear(FileSelectParams *params) { params->renamefile[0] = '\0'; + params->rename_id = NULL; params->rename_flag = 0; } +static int file_params_find_renamed(const FileSelectParams *params, struct FileList *filelist) +{ + /* Find the file either through the local ID/asset it represents or its relative path. */ + return (params->rename_id != NULL) ? filelist_file_find_id(filelist, params->rename_id) : + filelist_file_find_path(filelist, params->renamefile); +} + /** * Helper used by both main update code, and smooth-scroll timer, * to try to enable rename editing from #FileSelectParams.renamefile name. @@ -1271,20 +1308,26 @@ void file_params_renamefile_activate(SpaceFile *sfile, FileSelectParams *params) return; } - BLI_assert(params->renamefile[0] != '\0'); + BLI_assert(params->renamefile[0] != '\0' || params->rename_id != NULL); - const int idx = filelist_file_findpath(sfile->files, params->renamefile); + const int idx = file_params_find_renamed(params, sfile->files); if (idx >= 0) { FileDirEntry *file = filelist_file(sfile->files, idx); BLI_assert(file != NULL); + params->active_file = idx; + filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL); + if ((params->rename_flag & FILE_PARAMS_RENAME_PENDING) != 0) { filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL); params->rename_flag = FILE_PARAMS_RENAME_ACTIVE; } else if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_PENDING) != 0) { - filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL); - params->renamefile[0] = '\0'; + file_select_deselect_all(sfile, FILE_SEL_SELECTED); + filelist_entry_select_set( + sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED | FILE_SEL_HIGHLIGHTED, CHECK_ALL); + params->active_file = idx; + file_params_renamefile_clear(params); params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE; } } diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 64b43ac74a5..05d484d8e2e 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -32,6 +32,7 @@ #include "BKE_appdir.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_main.h" #include "BKE_screen.h" #include "RNA_access.h" @@ -469,10 +470,19 @@ static void file_listener(const wmSpaceTypeListenerParams *listener_params) break; case NC_ID: { switch (wmn->action) { - case NA_RENAME: + case NA_RENAME: { + const ID *active_file_id = ED_fileselect_active_asset_get(sfile); + /* If a renamed ID is active in the file browser, update scrolling to keep it in view. */ + if (active_file_id && (wmn->reference == active_file_id)) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + params->rename_id = active_file_id; + file_params_invoke_rename_postscroll(G_MAIN->wm.first, listener_params->window, sfile); + } + /* Force list to update sorting (with a full reset for now). */ file_reset_filelist_showing_main_data(area, sfile); break; + } } break; } diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c index 082f66b57af..cc6effd0f71 100644 --- a/source/blender/editors/space_image/image_undo.c +++ b/source/blender/editors/space_image/image_undo.c @@ -1006,7 +1006,7 @@ void ED_image_undosys_type(UndoType *ut) * specific case, see `image_undosys_step_encode` code. We cannot specify * `UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE` though, as it can be called with a NULL context by * current code. */ - ut->flags = 0; + ut->flags = UNDOTYPE_FLAG_DECODE_ACTIVE_STEP; ut->step_size = sizeof(ImageUndoStep); } diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index aaf9852e212..94e53958524 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -564,12 +564,11 @@ void FILE_OT_find_missing_files(wmOperatorType *ot) /** \name Report Box Operator * \{ */ -/* Hard to decide whether to keep this as an operator, - * or turn it into a hardcoded ui control feature, - * handling TIMER events for all regions in interface_handlers.c +/* NOTE(matt): Hard to decide whether to keep this as an operator, + * or turn it into a hard_coded UI control feature, + * handling TIMER events for all regions in `interface_handlers.c`. * Not sure how good that is to be accessing UI data from - * inactive regions, so use this for now. --matt - */ + * inactive regions, so use this for now. */ #define INFO_TIMEOUT 5.0f #define ERROR_TIMEOUT 10.0f diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index f2cea23af76..0498964c549 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -288,14 +288,14 @@ static int mouse_nla_channels( /* button region... */ if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) { if (nlaedit_is_tweakmode_on(ac) == 0) { - /* 'push-down' action - only usable when not in TweakMode */ + /* 'push-down' action - only usable when not in tweak-mode */ /* TODO: make this use the operator instead of calling the function directly * however, calling the operator requires that we supply the args, * and that works with proper buttons only */ BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(ale->id)); } else { - /* when in tweakmode, this button becomes the toggle for mapped editing */ + /* When in tweak-mode, this button becomes the toggle for mapped editing. */ adt->flag ^= ADT_NLA_EDIT_NOMAP; } @@ -308,13 +308,13 @@ static int mouse_nla_channels( /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block * - this is useful when there's no clear divider, and makes more sense in * the case of users trying to use this to change actions - * - in tweakmode, clicking here gets us out of tweakmode, as changing selection - * while in tweakmode is really evil! + * - in tweak-mode, clicking here gets us out of tweak-mode, as changing selection + * while in tweak-mode is really evil! * - we disable "solo" flags too, to make it easier to work with stashed actions * with less trouble */ if (nlaedit_is_tweakmode_on(ac)) { - /* exit tweakmode immediately */ + /* Exit tweak-mode immediately. */ nlaedit_disable_tweakmode(ac, true); /* changes to NLA-Action occurred */ @@ -515,7 +515,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* 'push-down' action - only usable when not in TweakMode */ + /* 'push-down' action - only usable when not in Tweak-mode. */ BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(id)); struct Main *bmain = CTX_data_main(C); @@ -874,7 +874,7 @@ static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op)) /* operate on selected objects... */ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { /* ensure that object has AnimData... that's all */ - BKE_animdata_add_id(&ob->id); + BKE_animdata_ensure_id(&ob->id); } CTX_DATA_END; diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index ae86efc0e6a..56efcd8571f 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -135,7 +135,7 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op) for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ale->data; - /* try entering tweakmode if valid */ + /* Try entering tweak-mode if valid. */ ok |= BKE_nla_tweakmode_enter(adt); /* mark the active track as being "solo"? */ @@ -154,9 +154,8 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op) ANIM_animdata_update(&ac, &anim_data); ANIM_animdata_freelist(&anim_data); - /* if we managed to enter tweakmode on at least one AnimData block, - * set the flag for this in the active scene and send notifiers - */ + /* If we managed to enter tweak-mode on at least one AnimData block, + * set the flag for this in the active scene and send notifiers. */ if (ac.scene && ok) { /* set editing flag */ ac.scene->flag |= SCE_NLA_EDIT_ON; @@ -206,7 +205,7 @@ void NLA_OT_tweakmode_enter(wmOperatorType *ot) /** \name Disable Tweak-Mode Operator * \{ */ -/* NLA Editor internal API function for exiting tweakmode */ +/* NLA Editor internal API function for exiting tweak-mode. */ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) { ListBase anim_data = {NULL, NULL}; @@ -232,7 +231,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) BKE_nlatrack_solo_toggle(adt, NULL); } - /* to be sure that we're doing everything right, just exit tweakmode... */ + /* To be sure that we're doing everything right, just exit tweak-mode. */ BKE_nla_tweakmode_exit(adt); ale->update |= ANIM_UPDATE_DEPS; @@ -242,7 +241,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) ANIM_animdata_update(ac, &anim_data); ANIM_animdata_freelist(&anim_data); - /* if we managed to enter tweakmode on at least one AnimData block, + /* if we managed to enter tweak-mode on at least one AnimData block, * set the flag for this in the active scene and send notifiers */ if (ac->scene) { @@ -257,7 +256,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) return true; } -/* exit tweakmode operator callback */ +/* Exit tweak-mode operator callback. */ static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op) { bAnimContext ac; diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 631dc2e550c..28f194877fa 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -39,17 +39,16 @@ /* ************************** poll callbacks for operators **********************************/ -/* tweakmode is NOT enabled */ +/* Tweak-mode is NOT enabled. */ bool nlaop_poll_tweakmode_off(bContext *C) { Scene *scene; /* for now, we check 2 things: * 1) active editor must be NLA - * 2) tweakmode is currently set as a 'per-scene' flag + * 2) tweak-mode is currently set as a 'per-scene' flag * so that it will affect entire NLA data-sets, - * but not all AnimData blocks will be in tweakmode for - * various reasons + * but not all AnimData blocks will be in tweak-mode for various reasons. */ if (ED_operator_nla_active(C) == 0) { return 0; @@ -63,17 +62,16 @@ bool nlaop_poll_tweakmode_off(bContext *C) return 1; } -/* tweakmode IS enabled */ +/* Tweak-mode IS enabled. */ bool nlaop_poll_tweakmode_on(bContext *C) { Scene *scene; /* for now, we check 2 things: * 1) active editor must be NLA - * 2) tweakmode is currently set as a 'per-scene' flag + * 2) tweak-mode is currently set as a 'per-scene' flag * so that it will affect entire NLA data-sets, - * but not all AnimData blocks will be in tweakmode for - * various reasons + * but not all AnimData blocks will be in tweak-mode for various reasons. */ if (ED_operator_nla_active(C) == 0) { return 0; @@ -87,7 +85,7 @@ bool nlaop_poll_tweakmode_on(bContext *C) return 1; } -/* is tweakmode enabled - for use in NLA operator code */ +/* is tweak-mode enabled - for use in NLA operator code */ bool nlaedit_is_tweakmode_on(bAnimContext *ac) { if (ac && ac->scene) { diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index dc95a01a021..246c3e0156a 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -453,7 +453,7 @@ static void nlaedit_select_leftright(bContext *C, Scene *scene = ac->scene; float xmin, xmax; - /* if currently in tweakmode, exit tweakmode first */ + /* if currently in tweak-mode, exit tweak-mode first */ if (scene->flag & SCE_NLA_EDIT_ON) { WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); } @@ -612,7 +612,7 @@ static int mouse_nla_strips(bContext *C, nlaedit_strip_at_region_position(ac, mval[0], mval[1], &ale, &strip); - /* if currently in tweakmode, exit tweakmode before changing selection states + /* if currently in tweak-mode, exit tweak-mode before changing selection states * now that we've found our target... */ if (scene->flag & SCE_NLA_EDIT_ON) { diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index 6e234c5b2ce..80d3b43bf6b 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../compositor ../../depsgraph ../../draw + ../../functions ../../gpu ../../imbuf ../../makesdna @@ -39,7 +40,6 @@ set(INC set(SRC drawnode.cc node_add.cc - node_buttons.c node_draw.cc node_edit.cc node_geometry_attribute_search.cc @@ -78,4 +78,20 @@ if(WITH_OPENSUBDIV) add_definitions(-DWITH_OPENSUBDIV) endif() +if(WITH_TBB) + add_definitions(-DWITH_TBB) + if(WIN32) + # TBB includes Windows.h which will define min/max macros + # that will collide with the stl versions. + add_definitions(-DNOMINMAX) + endif() + list(APPEND INC_SYS + ${TBB_INCLUDE_DIRS} + ) + + list(APPEND LIB + ${TBB_LIBRARIES} + ) +endif() + blender_add_lib(bf_editor_space_node "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c deleted file mode 100644 index 336b0c46a81..00000000000 --- a/source/blender/editors/space_node/node_buttons.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup spnode - */ - -#include "MEM_guardedalloc.h" - -#include "DNA_node_types.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" - -#include "BLT_translation.h" - -#include "BKE_context.h" -#include "BKE_global.h" -#include "BKE_node.h" -#include "BKE_screen.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "RNA_access.h" - -#include "ED_screen.h" - -#include "UI_resources.h" - -#include "node_intern.h" /* own include */ - -/* ******************* node space & buttons ************** */ - -#if 0 -/* poll for active nodetree */ -static bool active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - return (snode && snode->nodetree); -} -#endif - -static bool node_sockets_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - return (snode && snode->nodetree && G.debug_value == 777); -} - -static void node_sockets_panel(const bContext *C, Panel *panel) -{ - SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */ - bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */ - bNode *node = nodeGetActive(ntree); - if (node == NULL) { - return; - } - - LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { - char name[UI_MAX_NAME_STR]; - BLI_snprintf(name, sizeof(name), "%s:", socket->name); - - uiLayout *split = uiLayoutSplit(panel->layout, 0.35f, false); - uiItemL(split, name, ICON_NONE); - uiTemplateNodeLink(split, (bContext *)C, ntree, node, socket); - } -} - -static bool node_tree_interface_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - return (snode && snode->edittree && - (snode->edittree->inputs.first || snode->edittree->outputs.first)); -} - -static bNodeSocket *node_tree_find_active_socket(bNodeTree *ntree, const eNodeSocketInOut in_out) -{ - ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs; - LISTBASE_FOREACH (bNodeSocket *, socket, sockets) { - if (socket->flag & SELECT) { - return socket; - } - } - return NULL; -} - -static void draw_socket_list(const bContext *C, - uiLayout *layout, - bNodeTree *ntree, - const eNodeSocketInOut in_out) -{ - PointerRNA tree_ptr; - RNA_id_pointer_create((ID *)ntree, &tree_ptr); - - uiLayout *split = uiLayoutRow(layout, false); - uiLayout *list_col = uiLayoutColumn(split, true); - uiTemplateList(list_col, - (bContext *)C, - "NODE_UL_interface_sockets", - (in_out == SOCK_IN) ? "inputs" : "outputs", - &tree_ptr, - (in_out == SOCK_IN) ? "inputs" : "outputs", - &tree_ptr, - (in_out == SOCK_IN) ? "active_input" : "active_output", - NULL, - 0, - 0, - 0, - 0, - false, - false); - PointerRNA opptr; - uiLayout *ops_col = uiLayoutColumn(split, false); - uiLayout *add_remove_col = uiLayoutColumn(ops_col, true); - wmOperatorType *ot = WM_operatortype_find("NODE_OT_tree_socket_add", false); - uiItemFullO_ptr(add_remove_col, ot, "", ICON_ADD, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); - RNA_enum_set(&opptr, "in_out", in_out); - ot = WM_operatortype_find("NODE_OT_tree_socket_remove", false); - uiItemFullO_ptr(add_remove_col, ot, "", ICON_REMOVE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); - RNA_enum_set(&opptr, "in_out", in_out); - - uiItemS(ops_col); - - uiLayout *up_down_col = uiLayoutColumn(ops_col, true); - ot = WM_operatortype_find("NODE_OT_tree_socket_move", false); - uiItemFullO_ptr(up_down_col, ot, "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); - RNA_enum_set(&opptr, "direction", 1); - RNA_enum_set(&opptr, "in_out", in_out); - uiItemFullO_ptr(up_down_col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); - RNA_enum_set(&opptr, "direction", 2); - RNA_enum_set(&opptr, "in_out", in_out); - - bNodeSocket *socket = node_tree_find_active_socket(ntree, in_out); - if (socket != NULL) { - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - PointerRNA socket_ptr; - RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, socket, &socket_ptr); - uiItemR(layout, &socket_ptr, "name", 0, NULL, ICON_NONE); - - /* Display descriptions only for Geometry Nodes, since it's only used in the modifier panel. */ - if (ntree->type == NTREE_GEOMETRY) { - uiItemR(layout, &socket_ptr, "description", 0, NULL, ICON_NONE); - } - - if (socket->typeinfo->interface_draw) { - socket->typeinfo->interface_draw((bContext *)C, layout, &socket_ptr); - } - } -} - -static void node_tree_interface_inputs_panel(const bContext *C, Panel *panel) -{ - SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */ - bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */ - - draw_socket_list(C, panel->layout, ntree, SOCK_IN); -} - -static void node_tree_interface_outputs_panel(const bContext *C, Panel *panel) -{ - SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */ - bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */ - - draw_socket_list(C, panel->layout, ntree, SOCK_OUT); -} - -/* ******************* node buttons registration ************** */ - -void node_buttons_register(ARegionType *art) -{ - { - PanelType *pt = MEM_callocN(sizeof(PanelType), __func__); - strcpy(pt->idname, "NODE_PT_sockets"); - strcpy(pt->category, N_("Node")); - strcpy(pt->label, N_("Sockets")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = node_sockets_panel; - pt->poll = node_sockets_poll; - pt->flag |= PANEL_TYPE_DEFAULT_CLOSED; - BLI_addtail(&art->paneltypes, pt); - } - - { - PanelType *pt = MEM_callocN(sizeof(PanelType), __func__); - strcpy(pt->idname, "NODE_PT_node_tree_interface_inputs"); - strcpy(pt->category, N_("Group")); - strcpy(pt->label, N_("Inputs")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = node_tree_interface_inputs_panel; - pt->poll = node_tree_interface_poll; - BLI_addtail(&art->paneltypes, pt); - } - { - PanelType *pt = MEM_callocN(sizeof(PanelType), __func__); - strcpy(pt->idname, "NODE_PT_node_tree_interface_outputs"); - strcpy(pt->category, N_("Group")); - strcpy(pt->label, N_("Outputs")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = node_tree_interface_outputs_panel; - pt->poll = node_tree_interface_poll; - BLI_addtail(&art->paneltypes, pt); - } -} diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 8a341da0b5c..d4f178603b8 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -48,7 +48,6 @@ #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_node.h" -#include "BKE_node_ui_storage.hh" #include "BKE_object.h" #include "DEG_depsgraph.h" @@ -76,6 +75,8 @@ #include "RNA_access.h" +#include "NOD_geometry_nodes_eval_log.hh" + #include "node_intern.h" /* own include */ #ifdef WITH_COMPOSITOR @@ -86,6 +87,9 @@ using blender::Map; using blender::Set; using blender::Span; using blender::Vector; +using blender::fn::CPPType; +using blender::fn::GPointer; +namespace geo_log = blender::nodes::geometry_nodes_eval_log; extern "C" { /* XXX interface.h */ @@ -1185,14 +1189,14 @@ void node_draw_sockets(const View2D *v2d, } } -static int node_error_type_to_icon(const NodeWarningType type) +static int node_error_type_to_icon(const geo_log::NodeWarningType type) { switch (type) { - case NodeWarningType::Error: + case geo_log::NodeWarningType::Error: return ICON_ERROR; - case NodeWarningType::Warning: + case geo_log::NodeWarningType::Warning: return ICON_ERROR; - case NodeWarningType::Info: + case geo_log::NodeWarningType::Info: return ICON_INFO; } @@ -1200,14 +1204,14 @@ static int node_error_type_to_icon(const NodeWarningType type) return ICON_ERROR; } -static uint8_t node_error_type_priority(const NodeWarningType type) +static uint8_t node_error_type_priority(const geo_log::NodeWarningType type) { switch (type) { - case NodeWarningType::Error: + case geo_log::NodeWarningType::Error: return 3; - case NodeWarningType::Warning: + case geo_log::NodeWarningType::Warning: return 2; - case NodeWarningType::Info: + case geo_log::NodeWarningType::Info: return 1; } @@ -1215,11 +1219,11 @@ static uint8_t node_error_type_priority(const NodeWarningType type) return 0; } -static NodeWarningType node_error_highest_priority(Span<NodeWarning> warnings) +static geo_log::NodeWarningType node_error_highest_priority(Span<geo_log::NodeWarning> warnings) { uint8_t highest_priority = 0; - NodeWarningType highest_priority_type = NodeWarningType::Info; - for (const NodeWarning &warning : warnings) { + geo_log::NodeWarningType highest_priority_type = geo_log::NodeWarningType::Info; + for (const geo_log::NodeWarning &warning : warnings) { const uint8_t priority = node_error_type_priority(warning.type); if (priority > highest_priority) { highest_priority = priority; @@ -1229,15 +1233,17 @@ static NodeWarningType node_error_highest_priority(Span<NodeWarning> warnings) return highest_priority_type; } +struct NodeErrorsTooltipData { + Span<geo_log::NodeWarning> warnings; +}; + static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char *UNUSED(tip)) { - const NodeUIStorage **storage_pointer_alloc = static_cast<const NodeUIStorage **>(argN); - const NodeUIStorage *node_ui_storage = *storage_pointer_alloc; - Span<NodeWarning> warnings = node_ui_storage->warnings; + NodeErrorsTooltipData &data = *(NodeErrorsTooltipData *)argN; std::string complete_string; - for (const NodeWarning &warning : warnings.drop_back(1)) { + for (const geo_log::NodeWarning &warning : data.warnings.drop_back(1)) { complete_string += warning.message; /* Adding the period is not ideal for multi-line messages, but it is consistent * with other tooltip implementations in Blender, so it is added here. */ @@ -1246,7 +1252,7 @@ static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char } /* Let the tooltip system automatically add the last period. */ - complete_string += warnings.last().message; + complete_string += data.warnings.last().message; return BLI_strdupn(complete_string.c_str(), complete_string.size()); } @@ -1254,20 +1260,26 @@ static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char #define NODE_HEADER_ICON_SIZE (0.8f * U.widget_unit) static void node_add_error_message_button( - const bContext *C, bNodeTree &ntree, bNode &node, const rctf &rect, float &icon_offset) + const bContext *C, bNodeTree &UNUSED(ntree), bNode &node, const rctf &rect, float &icon_offset) { - const NodeUIStorage *node_ui_storage = BKE_node_tree_ui_storage_get_from_context(C, ntree, node); - if (node_ui_storage == nullptr || node_ui_storage->warnings.is_empty()) { + SpaceNode *snode = CTX_wm_space_node(C); + const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(*snode, + node); + if (node_log == nullptr) { + return; + } + + Span<geo_log::NodeWarning> warnings = node_log->warnings(); + + if (warnings.is_empty()) { return; } - /* The UI API forces us to allocate memory for each error button, because the - * ownership of #UI_but_func_tooltip_set's argument is transferred to the button. */ - const NodeUIStorage **storage_pointer_alloc = (const NodeUIStorage **)MEM_mallocN( - sizeof(NodeUIStorage *), __func__); - *storage_pointer_alloc = node_ui_storage; + NodeErrorsTooltipData *tooltip_data = (NodeErrorsTooltipData *)MEM_mallocN( + sizeof(NodeErrorsTooltipData), __func__); + tooltip_data->warnings = warnings; - const NodeWarningType display_type = node_error_highest_priority(node_ui_storage->warnings); + const geo_log::NodeWarningType display_type = node_error_highest_priority(warnings); icon_offset -= NODE_HEADER_ICON_SIZE; UI_block_emboss_set(node.block, UI_EMBOSS_NONE); @@ -1285,7 +1297,7 @@ static void node_add_error_message_button( 0, 0, nullptr); - UI_but_func_tooltip_set(but, node_errors_tooltip_fn, storage_pointer_alloc, MEM_freeN); + UI_but_func_tooltip_set(but, node_errors_tooltip_fn, tooltip_data, MEM_freeN); UI_block_emboss_set(node.block, UI_EMBOSS); } diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 9a6603eb589..5dd935bdd76 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -2414,6 +2414,109 @@ void NODE_OT_tree_socket_remove(wmOperatorType *ot) RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", ""); } +/********************** Change interface socket type operator *********************/ + +static int ntree_socket_change_type_exec(bContext *C, wmOperator *op) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree = snode->edittree; + const eNodeSocketInOut in_out = (eNodeSocketInOut)RNA_enum_get(op->ptr, "in_out"); + const bNodeSocketType *socket_type = rna_node_socket_type_from_enum( + RNA_enum_get(op->ptr, "socket_type")); + ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs; + + Main *main = CTX_data_main(C); + + bNodeSocket *iosock = ntree_get_active_interface_socket(sockets); + if (iosock == nullptr) { + return OPERATOR_CANCELLED; + } + + /* The type remains the same, so we don't need to change anything. */ + if (iosock->typeinfo == socket_type) { + return OPERATOR_FINISHED; + } + + /* Don't handle subtypes for now. */ + nodeModifySocketType(ntree, nullptr, iosock, socket_type->idname); + + /* Need the extra update here because the loop above does not check for valid links in the node + * group we're currently editing. */ + ntree->update |= NTREE_UPDATE_GROUP | NTREE_UPDATE_LINKS; + + /* Deactivate sockets. */ + LISTBASE_FOREACH (bNodeSocket *, socket_iter, sockets) { + socket_iter->flag &= ~SELECT; + } + /* Make the new socket active. */ + iosock->flag |= SELECT; + + ntreeUpdateTree(main, ntree); + + snode_notify(C, snode); + snode_dag_update(C, snode); + + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); + + return OPERATOR_FINISHED; +} + +static bool socket_change_poll_type(void *userdata, bNodeSocketType *socket_type) +{ + /* Check if the node tree supports the socket type. */ + bNodeTreeType *ntreetype = (bNodeTreeType *)userdata; + if (ntreetype->valid_socket_type && !ntreetype->valid_socket_type(ntreetype, socket_type)) { + return false; + } + + /* Only use basic socket types for this enum. */ + if (socket_type->subtype != PROP_NONE) { + return false; + } + + return true; +} + +static const EnumPropertyItem *socket_change_type_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) +{ + if (!C) { + return DummyRNA_NULL_items; + } + + SpaceNode *snode = CTX_wm_space_node(C); + if (!snode || !snode->edittree) { + return DummyRNA_NULL_items; + } + + return rna_node_socket_type_itemf(snode->edittree->typeinfo, socket_change_poll_type, r_free); +} + +void NODE_OT_tree_socket_change_type(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Change Node Tree Interface Socket Type"; + ot->description = "Change the type of a socket of the current node tree"; + ot->idname = "NODE_OT_tree_socket_change_type"; + + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = ntree_socket_change_type_exec; + ot->poll = ED_operator_node_editable; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", ""); + prop = RNA_def_enum(ot->srna, "socket_type", DummyRNA_DEFAULT_items, 0, "Socket Type", ""); + RNA_def_enum_funcs(prop, socket_change_type_itemf); + ot->prop = prop; +} + /********************** Move interface socket operator *********************/ static const EnumPropertyItem move_direction_items[] = { diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc index 94080a7b616..a6901c21862 100644 --- a/source/blender/editors/space_node/node_geometry_attribute_search.cc +++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc @@ -27,7 +27,6 @@ #include "DNA_space_types.h" #include "BKE_context.h" -#include "BKE_node_ui_storage.hh" #include "BKE_object.h" #include "RNA_access.h" @@ -40,17 +39,21 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "NOD_geometry_nodes_eval_log.hh" + #include "node_intern.h" using blender::IndexRange; using blender::Map; using blender::Set; using blender::StringRef; +namespace geo_log = blender::nodes::geometry_nodes_eval_log; +using geo_log::GeometryAttributeInfo; struct AttributeSearchData { - AvailableAttributeInfo &dummy_info_for_search; - const NodeUIStorage &ui_storage; - bNodeSocket &socket; + const bNodeTree *tree; + const bNode *node; + bNodeSocket *socket; }; /* This class must not have a destructor, since it is used by buttons and freed with #MEM_freeN. */ @@ -73,7 +76,7 @@ static StringRef attribute_domain_string(const AttributeDomain domain) /* Unicode arrow. */ #define MENU_SEP "\xe2\x96\xb6" -static bool attribute_search_item_add(uiSearchItems *items, const AvailableAttributeInfo &item) +static bool attribute_search_item_add(uiSearchItems *items, const GeometryAttributeInfo &item) { const StringRef data_type_name = attribute_data_type_string(item.data_type); const StringRef domain_name = attribute_domain_string(item.domain); @@ -84,31 +87,47 @@ static bool attribute_search_item_add(uiSearchItems *items, const AvailableAttri items, search_item_text.c_str(), (void *)&item, ICON_NONE, UI_BUT_HAS_SEP_CHAR, 0); } -static void attribute_search_update_fn(const bContext *UNUSED(C), - void *arg, - const char *str, - uiSearchItems *items, - const bool is_first) +static GeometryAttributeInfo &get_dummy_item_info() +{ + static GeometryAttributeInfo info; + return info; +} + +static void attribute_search_update_fn( + const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first) { AttributeSearchData *data = static_cast<AttributeSearchData *>(arg); - const Set<AvailableAttributeInfo> &attribute_hints = data->ui_storage.attribute_hints; + SpaceNode *snode = CTX_wm_space_node(C); + const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context( + *snode, *data->node); + if (node_log == nullptr) { + return; + } + blender::Vector<const GeometryAttributeInfo *> infos = node_log->lookup_available_attributes(); + + GeometryAttributeInfo &dummy_info = get_dummy_item_info(); /* Any string may be valid, so add the current search string along with the hints. */ if (str[0] != '\0') { - /* Note that the attribute domain and data type are dummies, since - * #AvailableAttributeInfo equality is only based on the string. */ - if (!attribute_hints.contains(AvailableAttributeInfo{str, ATTR_DOMAIN_AUTO, CD_PROP_BOOL})) { - data->dummy_info_for_search.name = std::string(str); - UI_search_item_add(items, str, &data->dummy_info_for_search, ICON_ADD, 0, 0); + bool contained = false; + for (const GeometryAttributeInfo *attribute_info : infos) { + if (attribute_info->name == str) { + contained = true; + break; + } + } + if (!contained) { + dummy_info.name = str; + UI_search_item_add(items, str, &dummy_info, ICON_ADD, 0, 0); } } if (str[0] == '\0' && !is_first) { /* Allow clearing the text field when the string is empty, but not on the first pass, * or opening an attribute field for the first time would show this search item. */ - data->dummy_info_for_search.name = std::string(str); - UI_search_item_add(items, str, &data->dummy_info_for_search, ICON_X, 0, 0); + dummy_info.name = str; + UI_search_item_add(items, str, &dummy_info, ICON_X, 0, 0); } /* Don't filter when the menu is first opened, but still run the search @@ -116,15 +135,15 @@ static void attribute_search_update_fn(const bContext *UNUSED(C), const char *string = is_first ? "" : str; StringSearch *search = BLI_string_search_new(); - for (const AvailableAttributeInfo &item : attribute_hints) { - BLI_string_search_add(search, item.name.c_str(), (void *)&item); + for (const GeometryAttributeInfo *item : infos) { + BLI_string_search_add(search, item->name.c_str(), (void *)item); } - AvailableAttributeInfo **filtered_items; + GeometryAttributeInfo **filtered_items; const int filtered_amount = BLI_string_search_query(search, string, (void ***)&filtered_items); for (const int i : IndexRange(filtered_amount)) { - const AvailableAttributeInfo *item = filtered_items[i]; + const GeometryAttributeInfo *item = filtered_items[i]; if (!attribute_search_item_add(items, *item)) { break; } @@ -136,32 +155,25 @@ static void attribute_search_update_fn(const bContext *UNUSED(C), static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v) { + if (item_v == nullptr) { + return; + } AttributeSearchData *data = static_cast<AttributeSearchData *>(data_v); - AvailableAttributeInfo *item = static_cast<AvailableAttributeInfo *>(item_v); + GeometryAttributeInfo *item = (GeometryAttributeInfo *)item_v; - bNodeSocket &socket = data->socket; + bNodeSocket &socket = *data->socket; bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket.default_value); BLI_strncpy(value->value, item->name.c_str(), MAX_NAME); ED_undo_push(C, "Assign Attribute Name"); } -void node_geometry_add_attribute_search_button(const bContext *C, +void node_geometry_add_attribute_search_button(const bContext *UNUSED(C), const bNodeTree *node_tree, const bNode *node, PointerRNA *socket_ptr, uiLayout *layout) { - const NodeUIStorage *ui_storage = BKE_node_tree_ui_storage_get_from_context( - C, *node_tree, *node); - - if (ui_storage == nullptr) { - uiItemR(layout, socket_ptr, "default_value", 0, "", 0); - return; - } - - const NodeTreeUIStorage *tree_ui_storage = node_tree->ui_storage; - uiBlock *block = uiLayoutGetBlock(layout); uiBut *but = uiDefIconTextButR(block, UI_BTYPE_SEARCH_MENU, @@ -181,10 +193,8 @@ void node_geometry_add_attribute_search_button(const bContext *C, 0.0f, ""); - AttributeSearchData *data = OBJECT_GUARDED_NEW(AttributeSearchData, - {tree_ui_storage->dummy_info_for_search, - *ui_storage, - *static_cast<bNodeSocket *>(socket_ptr->data)}); + AttributeSearchData *data = OBJECT_GUARDED_NEW( + AttributeSearchData, {node_tree, node, (bNodeSocket *)socket_ptr->data}); UI_but_func_search_set_results_are_suggestions(but, true); UI_but_func_search_set_sep_string(but, MENU_SEP); diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index e69f0cbea7f..09e5a110a45 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -140,9 +140,6 @@ void node_to_view(const struct bNode *node, float x, float y, float *rx, float * void node_to_updated_rect(const struct bNode *node, rctf *r_rect); void node_from_view(const struct bNode *node, float x, float y, float *rx, float *ry); -/* node_buttons.c */ -void node_buttons_register(struct ARegionType *art); - /* node_toolbar.c */ void node_toolbar_register(struct ARegionType *art); @@ -296,6 +293,7 @@ void NODE_OT_clipboard_paste(struct wmOperatorType *ot); void NODE_OT_tree_socket_add(struct wmOperatorType *ot); void NODE_OT_tree_socket_remove(struct wmOperatorType *ot); +void NODE_OT_tree_socket_change_type(struct wmOperatorType *ot); void NODE_OT_tree_socket_move(struct wmOperatorType *ot); void NODE_OT_shader_script_update(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index ce65fe93f20..610c2889e7a 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -119,6 +119,7 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_tree_socket_add); WM_operatortype_append(NODE_OT_tree_socket_remove); + WM_operatortype_append(NODE_OT_tree_socket_change_type); WM_operatortype_append(NODE_OT_tree_socket_move); WM_operatortype_append(NODE_OT_cryptomatte_layer_add); diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index d7e16dd69f1..ff848a7bb95 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -651,6 +651,10 @@ static void node_main_region_init(wmWindowManager *wm, ARegion *region) lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW); WM_event_add_dropbox_handler(®ion->handlers, lb); + + /* The backdrop image gizmo needs to change together with the view. So always refresh gizmos on + * region size changes. */ + WM_gizmomap_tag_refresh(region->gizmo_map); } static void node_main_region_draw(const bContext *C, ARegion *region) @@ -1094,8 +1098,6 @@ void ED_spacetype_node(void) art->draw = node_buttons_region_draw; BLI_addhead(&st->regiontypes, art); - node_buttons_register(art); - /* regions: toolbar */ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region"); art->regionid = RGN_TYPE_TOOLS; diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index d1fb36979b4..db37c8c1c8c 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -2964,7 +2964,8 @@ static void outliner_draw_iconrow(bContext *C, te->flag &= ~(TE_ICONROW | TE_ICONROW_MERGED); /* object hierarchy always, further constrained on level */ - if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB))) { + if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) || + ELEM(tselem->type, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL)) { /* active blocks get white circle */ if (tselem->type == TSE_SOME_ID) { if (te->idcode == ID_OB) { diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh index f089a149805..96af8258010 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.hh +++ b/source/blender/editors/space_outliner/tree/tree_display.hh @@ -86,7 +86,7 @@ class TreeDisplayViewLayer final : public AbstractTreeDisplay { ListBase buildTree(const TreeSourceData &source_data) override; private: - void add_view_layer(ListBase &, TreeElement &); + void add_view_layer(Scene &, ListBase &, TreeElement *); void add_layer_collections_recursive(ListBase &, ListBase &, TreeElement &); void add_layer_collection_objects(ListBase &, LayerCollection &, TreeElement &); void add_layer_collection_objects_children(TreeElement &); diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library.cc index 3059f8bfe0c..a17bf174a74 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_override_library.cc @@ -150,27 +150,25 @@ TreeElement *TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar, } /* Create data-block list parent element on demand. */ - if (id != nullptr) { - TreeElement *ten; + TreeElement *ten; - if (filter_id_type) { - ten = tenlib; - } - else { - ten = outliner_add_element( - &space_outliner_, &tenlib->subtree, lbarray[a], nullptr, TSE_ID_BASE, 0); - ten->directdata = lbarray[a]; - ten->name = outliner_idcode_to_plural(GS(id->name)); - } + if (filter_id_type) { + ten = tenlib; + } + else { + ten = outliner_add_element( + &space_outliner_, &tenlib->subtree, lbarray[a], nullptr, TSE_ID_BASE, 0); + ten->directdata = lbarray[a]; + ten->name = outliner_idcode_to_plural(GS(id->name)); + } - for (ID *id : List<ID>(lbarray[a])) { - if (override_library_id_filter_poll(lib, id)) { - TreeElement *override_tree_element = outliner_add_element( - &space_outliner_, &ten->subtree, id, ten, TSE_LIBRARY_OVERRIDE_BASE, 0); + for (ID *id : List<ID>(lbarray[a])) { + if (override_library_id_filter_poll(lib, id)) { + TreeElement *override_tree_element = outliner_add_element( + &space_outliner_, &ten->subtree, id, ten, TSE_LIBRARY_OVERRIDE_BASE, 0); - if (BLI_listbase_is_empty(&override_tree_element->subtree)) { - outliner_free_tree_element(override_tree_element, &ten->subtree); - } + if (BLI_listbase_is_empty(&override_tree_element->subtree)) { + outliner_free_tree_element(override_tree_element, &ten->subtree); } } } diff --git a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc index 402526bbe8d..c3d0aecd3cb 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc @@ -70,74 +70,69 @@ TreeDisplayViewLayer::TreeDisplayViewLayer(SpaceOutliner &space_outliner) ListBase TreeDisplayViewLayer::buildTree(const TreeSourceData &source_data) { ListBase tree = {nullptr}; - Scene *scene = source_data.scene; show_objects_ = !(space_outliner_.filter & SO_FILTER_NO_OBJECT); - const bool show_children = (space_outliner_.filter & SO_FILTER_NO_CHILDREN) == 0; - for (auto *view_layer : ListBaseWrapper<ViewLayer>(scene->view_layers)) { + view_layer_ = view_layer; + if (space_outliner_.filter & SO_FILTER_NO_VIEW_LAYERS) { if (view_layer != source_data.view_layer) { continue; } - } - TreeElement &te_view_layer = *outliner_add_element( - &space_outliner_, &tree, scene, nullptr, TSE_R_LAYER, 0); - TREESTORE(&te_view_layer)->flag &= ~TSE_CLOSED; - te_view_layer.name = view_layer->name; - te_view_layer.directdata = view_layer; - view_layer_ = view_layer; - - if (space_outliner_.filter & SO_FILTER_NO_COLLECTION) { - /* Show objects in the view layer. */ - for (Base *base : List<Base>(view_layer_->object_bases)) { - TreeElement *te_object = outliner_add_element(&space_outliner_, - &te_view_layer.subtree, - base->object, - &te_view_layer, - TSE_SOME_ID, - 0); - te_object->directdata = base; - } - - if (show_children) { - outliner_make_object_parent_hierarchy(&tree); - } + add_view_layer(*scene, tree, (TreeElement *)nullptr); } else { - /* Show collections in the view layer. */ - TreeElement &ten = *outliner_add_element(&space_outliner_, - &te_view_layer.subtree, - source_data.scene, - &te_view_layer, - TSE_VIEW_COLLECTION_BASE, - 0); - ten.name = IFACE_("Scene Collection"); - TREESTORE(&ten)->flag &= ~TSE_CLOSED; - - add_view_layer(ten.subtree, ten); - if (show_children) { - add_layer_collection_objects_children(ten); - } + TreeElement &te_view_layer = *outliner_add_element( + &space_outliner_, &tree, scene, nullptr, TSE_R_LAYER, 0); + TREESTORE(&te_view_layer)->flag &= ~TSE_CLOSED; + te_view_layer.name = view_layer->name; + te_view_layer.directdata = view_layer; + + add_view_layer(*scene, te_view_layer.subtree, &te_view_layer); } } return tree; } -void TreeDisplayViewLayer::add_view_layer(ListBase &tree, TreeElement &parent) +void TreeDisplayViewLayer::add_view_layer(Scene &scene, ListBase &tree, TreeElement *parent) { - /* First layer collection is for master collection, don't show it. */ - LayerCollection *lc = static_cast<LayerCollection *>(view_layer_->layer_collections.first); - if (lc == nullptr) { - return; + const bool show_children = (space_outliner_.filter & SO_FILTER_NO_CHILDREN) == 0; + + if (space_outliner_.filter & SO_FILTER_NO_COLLECTION) { + /* Show objects in the view layer. */ + for (Base *base : List<Base>(view_layer_->object_bases)) { + TreeElement *te_object = outliner_add_element( + &space_outliner_, &tree, base->object, parent, TSE_SOME_ID, 0); + te_object->directdata = base; + } + + if (show_children) { + outliner_make_object_parent_hierarchy(&tree); + } } + else { + /* Show collections in the view layer. */ + TreeElement &ten = *outliner_add_element( + &space_outliner_, &tree, &scene, parent, TSE_VIEW_COLLECTION_BASE, 0); + ten.name = IFACE_("Scene Collection"); + TREESTORE(&ten)->flag &= ~TSE_CLOSED; + + /* First layer collection is for master collection, don't show it. */ + LayerCollection *lc = static_cast<LayerCollection *>(view_layer_->layer_collections.first); + if (lc == nullptr) { + return; + } - add_layer_collections_recursive(tree, lc->layer_collections, parent); - if (show_objects_) { - add_layer_collection_objects(tree, *lc, parent); + add_layer_collections_recursive(ten.subtree, lc->layer_collections, ten); + if (show_objects_) { + add_layer_collection_objects(ten.subtree, *lc, ten); + } + if (show_children) { + add_layer_collection_objects_children(ten); + } } } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 9669ca2d7c2..8371a634a78 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -2479,10 +2479,12 @@ void draw_timeline_seq_display(const bContext *C, ARegion *region) const SpaceSeq *sseq = CTX_wm_space_seq(C); View2D *v2d = ®ion->v2d; - if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) { + if (scene->ed != NULL) { UI_view2d_view_ortho(v2d); draw_cache_view(C); - draw_overlap_frame_indicator(scene, v2d); + if (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) { + draw_overlap_frame_indicator(scene, v2d); + } UI_view2d_view_restore(C); } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 45c6931364d..75cf8542f67 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -2414,6 +2414,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op) (LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_FREE_NO_MAIN)); seqbase_clipboard_frame = scene->r.cfra; + SEQ_clipboard_active_seq_name_store(scene); /* Remove anything that references the current scene. */ LISTBASE_FOREACH (Sequence *, seq, &seqbase_clipboard) { @@ -2504,6 +2505,10 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op) BLI_movelisttolist(ed->seqbasep, &nseqbase); for (iseq = iseq_first; iseq; iseq = iseq->next) { + if (SEQ_clipboard_pasted_seq_was_active(iseq)) { + SEQ_select_active_set(scene, iseq); + } + /* Make sure, that pasted strips have unique names. */ SEQ_ensure_unique_name(iseq, scene); /* Translate after name has been changed, otherwise this will affect animdata of original diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index 8cc8b4a007b..5d857f62b47 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -624,8 +624,6 @@ static void vectorscope_put_cross(uchar r, uchar g, uchar b, char *tgt, int w, i { float rgb[3], yuv[3]; char *p; - int x = 0; - int y = 0; rgb[0] = (float)r / 255.0f; rgb[1] = (float)g / 255.0f; @@ -638,8 +636,8 @@ static void vectorscope_put_cross(uchar r, uchar g, uchar b, char *tgt, int w, i r = 255; } - for (y = -size; y <= size; y++) { - for (x = -size; x <= size; x++) { + for (int y = -size; y <= size; y++) { + for (int x = -size; x <= size; x++) { char *q = p + 4 * (y * w + x); q[0] = r; q[1] = g; diff --git a/source/blender/editors/space_spreadsheet/CMakeLists.txt b/source/blender/editors/space_spreadsheet/CMakeLists.txt index 1ea6593588a..e903feeec1b 100644 --- a/source/blender/editors/space_spreadsheet/CMakeLists.txt +++ b/source/blender/editors/space_spreadsheet/CMakeLists.txt @@ -27,6 +27,7 @@ set(INC ../../gpu ../../makesdna ../../makesrna + ../../nodes ../../windowmanager ../../../../intern/glew-mx ../../../../intern/guardedalloc @@ -34,8 +35,8 @@ set(INC set(SRC space_spreadsheet.cc - spreadsheet_context.cc spreadsheet_column.cc + spreadsheet_context.cc spreadsheet_data_source.cc spreadsheet_data_source_geometry.cc spreadsheet_dataset_draw.cc @@ -46,10 +47,10 @@ set(SRC spreadsheet_row_filter.cc spreadsheet_row_filter_ui.cc - spreadsheet_context.hh spreadsheet_cell_value.hh spreadsheet_column.hh spreadsheet_column_values.hh + spreadsheet_context.hh spreadsheet_data_source.hh spreadsheet_data_source_geometry.hh spreadsheet_dataset_draw.hh diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index e42f70611c4..e38c70afd0f 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -31,11 +31,15 @@ #include "ED_spreadsheet.h" +#include "NOD_geometry_nodes_eval_log.hh" + #include "bmesh.h" #include "spreadsheet_data_source_geometry.hh" #include "spreadsheet_intern.hh" +namespace geo_log = blender::nodes::geometry_nodes_eval_log; + namespace blender::ed::spreadsheet { void GeometryDataSource::foreach_default_column_ids( @@ -436,13 +440,18 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread } } else { - if (object_eval->runtime.geometry_set_previews != nullptr) { - GHash *ghash = (GHash *)object_eval->runtime.geometry_set_previews; - const uint64_t key = ED_spreadsheet_context_path_hash(sspreadsheet); - GeometrySet *geometry_set_preview = (GeometrySet *)BLI_ghash_lookup_default( - ghash, POINTER_FROM_UINT(key), nullptr); - if (geometry_set_preview != nullptr) { - geometry_set = *geometry_set_preview; + const geo_log::NodeLog *node_log = + geo_log::ModifierLog::find_node_by_spreadsheet_editor_context(*sspreadsheet); + if (node_log != nullptr) { + for (const geo_log::SocketLog &input_log : node_log->input_logs()) { + if (const geo_log::GeometryValueLog *geo_value_log = + dynamic_cast<const geo_log::GeometryValueLog *>(input_log.value())) { + const GeometrySet *full_geometry = geo_value_log->full_geometry(); + if (full_geometry != nullptr) { + geometry_set = *full_geometry; + break; + } + } } } } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc index 5b5c5ed0b04..abbad8c7088 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc @@ -38,9 +38,9 @@ namespace blender::ed::spreadsheet { * Definition for the component->attribute-domain hierarchy. * Constructed at compile time. * - * \warning: Order of attribute-domains matters! It __must__ match the #AttributeDomain definition - * and fill gaps with unset optionals (i.e. `std::nullopt`). Would be nice to use array - * designators for this (which C++ doesn't support). + * \warning Order of attribute-domains matters! It __must__ match the #AttributeDomain + * definition and fill gaps with unset optionals (i.e. `std::nullopt`). Would be nice to use + * array designators for this (which C++ doesn't support). */ constexpr DatasetComponentLayoutInfo DATASET_layout_hierarchy[] = { { diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c index f55db8c3cc9..80af7d8c9f6 100644 --- a/source/blender/editors/space_text/text_undo.c +++ b/source/blender/editors/space_text/text_undo.c @@ -265,7 +265,7 @@ void ED_text_undosys_type(UndoType *ut) ut->step_foreach_ID_ref = text_undosys_foreach_ID_ref; - ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE; + ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE | UNDOTYPE_FLAG_DECODE_ACTIVE_STEP; ut->step_size = sizeof(TextUndoStep); } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index d5e52785937..3428a738dde 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -39,6 +39,8 @@ #include "BLT_translation.h" +#include "BLI_array_utils.h" +#include "BLI_bitmap.h" #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -112,10 +114,94 @@ typedef struct { float ob_dims[3]; /* Floats only (treated as an array). */ TransformMedian ve_median, median; + bool tag_for_update; } TransformProperties; #define TRANSFORM_MEDIAN_ARRAY_LEN (sizeof(TransformMedian) / sizeof(float)) +static TransformProperties *v3d_transform_props_ensure(View3D *v3d); + +/* -------------------------------------------------------------------- */ +/** \name Edit Mesh Partial Updates + * \{ */ + +static void *editmesh_partial_update_begin_fn(struct bContext *UNUSED(C), + const struct uiBlockInteraction_Params *params, + void *arg1) +{ + const int retval_test = B_TRANSFORM_PANEL_MEDIAN; + if (BLI_array_findindex( + params->unique_retval_ids, params->unique_retval_ids_len, &retval_test) == -1) { + return NULL; + } + + BMEditMesh *em = arg1; + + int verts_mask_count = 0; + BMIter iter; + BMVert *eve; + int i; + + BLI_bitmap *verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); + BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { + if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + continue; + } + BLI_BITMAP_ENABLE(verts_mask, i); + verts_mask_count += 1; + } + + BMPartialUpdate *bmpinfo = BM_mesh_partial_create_from_verts_group_single( + em->bm, + &(BMPartialUpdate_Params){ + .do_tessellate = true, + .do_normals = true, + }, + verts_mask, + verts_mask_count); + + MEM_freeN(verts_mask); + + return bmpinfo; +} + +static void editmesh_partial_update_end_fn(struct bContext *UNUSED(C), + const struct uiBlockInteraction_Params *UNUSED(params), + void *UNUSED(arg1), + void *user_data) +{ + BMPartialUpdate *bmpinfo = user_data; + if (bmpinfo == NULL) { + return; + } + BM_mesh_partial_destroy(bmpinfo); +} + +static void editmesh_partial_update_update_fn( + struct bContext *C, + const struct uiBlockInteraction_Params *UNUSED(params), + void *arg1, + void *user_data) +{ + BMPartialUpdate *bmpinfo = user_data; + if (bmpinfo == NULL) { + return; + } + + View3D *v3d = CTX_wm_view3d(C); + TransformProperties *tfp = v3d_transform_props_ensure(v3d); + if (tfp->tag_for_update == false) { + return; + } + tfp->tag_for_update = false; + + BMEditMesh *em = arg1; + + BKE_editmesh_looptri_and_normals_calc_with_partial(em, bmpinfo); +} + +/** \} */ + /* Helper function to compute a median changed value, * when the value should be clamped in [0.0, 1.0]. * Returns either 0.0, 1.0 (both can be applied directly), a positive scale factor @@ -840,6 +926,20 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } UI_block_align_end(block); + + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_mesh; + if (em != NULL) { + UI_block_interaction_set(block, + &(uiBlockInteraction_CallbackData){ + .begin_fn = editmesh_partial_update_begin_fn, + .end_fn = editmesh_partial_update_end_fn, + .update_fn = editmesh_partial_update_update_fn, + .arg1 = em, + }); + } + } } else { /* apply */ memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median)); @@ -927,9 +1027,8 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } if (apply_vcos) { - /* TODO: use the #BKE_editmesh_looptri_and_normals_calc_with_partial - * This requires begin/end states for UI interaction (which currently aren't supported). */ - BKE_editmesh_looptri_and_normals_calc(em); + /* Tell the update callback to run. */ + tfp->tag_for_update = true; } /* Edges */ @@ -1152,7 +1251,7 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event) ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = view_layer->basact->object; ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); } @@ -1466,7 +1565,7 @@ static void v3d_posearmature_buts(uiLayout *layout, Object *ob) /* XXX: RNA buts show data in native types (i.e. quats, 4-component axis/angle, etc.) * but old-school UI shows in eulers always. Do we want to be able to still display in Eulers? - * Maybe needs RNA/ui options to display rotations as different types... */ + * Maybe needs RNA/UI options to display rotations as different types. */ v3d_transform_butsR(col, &pchanptr); } @@ -1570,7 +1669,7 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event case B_TRANSFORM_PANEL_MEDIAN: if (ob) { v3d_editvertex_buts(NULL, v3d, ob, 1.0); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY); } break; case B_TRANSFORM_PANEL_DIMS: diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index ea9d9a8c010..c97ba7ba7e9 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1404,7 +1404,7 @@ static void draw_selected_name( /* color depends on whether there is a keyframe */ if (id_frame_has_keyframe( - (ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) { + (ID *)ob, /* BKE_scene_ctime_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) { UI_FontThemeColor(font_id, TH_TIME_KEYFRAME); } else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) { diff --git a/source/blender/editors/space_view3d/view3d_navigate_fly.c b/source/blender/editors/space_view3d/view3d_navigate_fly.c index e2fa0fdc6a5..5752837c40f 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_fly.c +++ b/source/blender/editors/space_view3d/view3d_navigate_fly.c @@ -122,7 +122,7 @@ void fly_modal_keymap(wmKeyConfig *keyconf) {FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""}, {FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"}, - {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "X Axis Correction", "Z axis correction (toggle)"}, + {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction (toggle)"}, {FLY_MODAL_PRECISION_ENABLE, "PRECISION_ENABLE", 0, "Precision", ""}, {FLY_MODAL_PRECISION_DISABLE, "PRECISION_DISABLE", 0, "Precision (Off)", ""}, diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index 435d74aa591..09936b41a74 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -98,9 +98,10 @@ enum { WALK_MODAL_JUMP, WALK_MODAL_JUMP_STOP, WALK_MODAL_TELEPORT, - WALK_MODAL_TOGGLE, + WALK_MODAL_GRAVITY_TOGGLE, WALK_MODAL_ACCELERATE, WALK_MODAL_DECELERATE, + WALK_MODAL_AXIS_LOCK_Z, }; enum { @@ -129,6 +130,18 @@ typedef enum eWalkGravityState { WALK_GRAVITY_STATE_ON, } eWalkGravityState; +/* Relative view axis z axis locking. */ +typedef enum eWalkLockState { + /* Disabled. */ + WALK_AXISLOCK_STATE_OFF = 0, + + /* Moving. */ + WALK_AXISLOCK_STATE_ACTIVE = 2, + + /* Done moving, it cannot be activated again. */ + WALK_AXISLOCK_STATE_DONE = 3, +} eWalkLockState; + /* Called in transform_ops.c, on each regeneration of key-maps. */ void walk_modal_keymap(wmKeyConfig *keyconf) { @@ -164,7 +177,9 @@ void walk_modal_keymap(wmKeyConfig *keyconf) {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"}, {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"}, - {WALK_MODAL_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"}, + {WALK_MODAL_GRAVITY_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"}, + + {WALK_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction"}, {0, NULL, 0, NULL, NULL}, }; @@ -292,6 +307,10 @@ typedef struct WalkInfo { /** To use for fast/slow speeds. */ float speed_factor; + eWalkLockState zlock; + /** Nicer dynamics. */ + float zlock_momentum; + struct SnapObjectContext *snap_context; struct View3DCameraControl *v3d_camera_control; @@ -540,6 +559,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->jump_height = U.walk_navigation.jump_height; walk->speed = U.walk_navigation.walk_speed; walk->speed_factor = U.walk_navigation.walk_speed_factor; + walk->zlock = WALK_AXISLOCK_STATE_OFF; walk->gravity_state = WALK_GRAVITY_STATE_OFF; @@ -708,8 +728,6 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) walk->is_cursor_absolute = true; copy_v2_v2_int(walk->prev_mval, event->mval); copy_v2_v2_int(walk->center_mval, event->mval); - /* Without this we can't turn 180d with the default speed of 1.0. */ - walk->mouse_speed *= 4.0f; } #endif /* USE_TABLET_SUPPORT */ @@ -941,7 +959,7 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) #undef JUMP_TIME_MAX #undef JUMP_SPEED_MIN - case WALK_MODAL_TOGGLE: + case WALK_MODAL_GRAVITY_TOGGLE: if (walk->navigation_mode == WALK_MODE_GRAVITY) { walk_navigation_mode_set(walk, WALK_MODE_FREE); } @@ -949,6 +967,13 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) walk_navigation_mode_set(walk, WALK_MODE_GRAVITY); } break; + + case WALK_MODAL_AXIS_LOCK_Z: + if (walk->zlock != WALK_AXISLOCK_STATE_DONE) { + walk->zlock = WALK_AXISLOCK_STATE_ACTIVE; + walk->zlock_momentum = 0.0f; + } + break; } } } @@ -982,12 +1007,14 @@ static float getVelocityZeroTime(const float gravity, const float velocity) static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) { -#define WALK_ROTATE_RELATIVE_FAC 2.2f /* More is faster, relative to region size. */ -#define WALK_ROTATE_CONSTANT_FAC DEG2RAD(0.15f) /* More is faster, radians per-pixel. */ +#define WALK_ROTATE_TABLET_FAC 8.8f /* Higher is faster, relative to region size. */ +#define WALK_ROTATE_CONSTANT_FAC DEG2RAD(0.15f) /* Higher is faster, radians per-pixel. */ #define WALK_TOP_LIMIT DEG2RADF(85.0f) #define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f) #define WALK_MOVE_SPEED base_speed #define WALK_BOOST_FACTOR ((void)0, walk->speed_factor) +#define WALK_ZUP_CORRECT_FAC 0.1f /* Amount to correct per step. */ +#define WALK_ZUP_CORRECT_ACCEL 0.05f /* Increase upright momentum each step. */ RegionView3D *rv3d = walk->rv3d; ARegion *region = walk->region; @@ -1022,20 +1049,25 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) /* Should we redraw? */ if ((walk->active_directions) || moffset[0] || moffset[1] || - walk->teleport.state == WALK_TELEPORT_STATE_ON || - walk->gravity_state != WALK_GRAVITY_STATE_OFF || is_confirm) { + walk->zlock == WALK_AXISLOCK_STATE_ACTIVE || + walk->gravity_state != WALK_GRAVITY_STATE_OFF || + walk->teleport.state == WALK_TELEPORT_STATE_ON || is_confirm) { float dvec_tmp[3]; /* time how fast it takes for us to redraw, * this is so simple scenes don't walk too fast */ double time_current; float time_redraw; + float time_redraw_clamped; #ifdef NDOF_WALK_DRAW_TOOMUCH walk->redraw = 1; #endif time_current = PIL_check_seconds_timer(); time_redraw = (float)(time_current - walk->time_lastdraw); + /* Clamp redraw time to avoid jitter in roll correction. */ + time_redraw_clamped = min_ff(0.05f, time_redraw); + walk->time_lastdraw = time_current; /* base speed in m/s */ @@ -1064,7 +1096,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) #ifdef USE_TABLET_SUPPORT if (walk->is_cursor_absolute) { y /= region->winy; - y *= WALK_ROTATE_RELATIVE_FAC; + y *= WALK_ROTATE_TABLET_FAC; } else #endif @@ -1113,7 +1145,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) #ifdef USE_TABLET_SUPPORT if (walk->is_cursor_absolute) { x /= region->winx; - x *= WALK_ROTATE_RELATIVE_FAC; + x *= WALK_ROTATE_TABLET_FAC; } else #endif @@ -1128,6 +1160,32 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) axis_angle_to_quat_single(tmp_quat, 'Z', x); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); } + + if (walk->zlock == WALK_AXISLOCK_STATE_ACTIVE) { + float upvec[3]; + copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); + mul_m3_v3(mat, upvec); + + /* Make sure we have some z rolling. */ + if (fabsf(upvec[2]) > 0.00001f) { + float roll = upvec[2] * 5.0f; + /* Rotate the view about this axis. */ + copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); + mul_m3_v3(mat, upvec); + /* Rotate about the relative up vec. */ + axis_angle_to_quat(tmp_quat, + upvec, + roll * time_redraw_clamped * walk->zlock_momentum * + WALK_ZUP_CORRECT_FAC); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); + + walk->zlock_momentum += WALK_ZUP_CORRECT_ACCEL; + } + else { + /* Lock fixed, don't need to check it ever again. */ + walk->zlock = WALK_AXISLOCK_STATE_DONE; + } + } } /* WASD - 'move' translation code */ @@ -1318,7 +1376,8 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) add_v3_v3(rv3d->ofs, dvec_tmp); if (rv3d->persp == RV3D_CAMOB) { - walk->need_rotation_keyframe |= (moffset[0] || moffset[1]); + walk->need_rotation_keyframe |= (moffset[0] || moffset[1] || + walk->zlock == WALK_AXISLOCK_STATE_ACTIVE); walk->need_translation_keyframe |= (len_squared_v3(dvec_tmp) > FLT_EPSILON); walkMoveCamera( C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm); @@ -1333,7 +1392,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) } return OPERATOR_FINISHED; -#undef WALK_ROTATE_RELATIVE_FAC +#undef WALK_ROTATE_TABLET_FAC #undef WALK_TOP_LIMIT #undef WALK_BOTTOM_LIMIT #undef WALK_MOVE_SPEED diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index a19e92f229a..4482e5897ca 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -511,47 +511,47 @@ static int snap_selected_to_location(bContext *C, for (int ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; + if (ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) { + continue; + } - if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) { - - float cursor_parent[3]; /* parent-relative */ - - if (use_offset) { - add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); - } - else { - copy_v3_v3(cursor_parent, snap_target_global); - } + float cursor_parent[3]; /* parent-relative */ - sub_v3_v3(cursor_parent, ob->obmat[3]); + if (use_offset) { + add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); + } + else { + copy_v3_v3(cursor_parent, snap_target_global); + } - if (ob->parent) { - float originmat[3][3], parentmat[4][4]; - /* Use the evaluated object here because sometimes - * `ob->parent->runtime.curve_cache` is required. */ - BKE_scene_graph_evaluated_ensure(depsgraph, bmain); - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + sub_v3_v3(cursor_parent, ob->obmat[3]); - BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat); - mul_m3_m4m4(originmat, parentmat, ob->parentinv); - invert_m3_m3(imat, originmat); - mul_m3_v3(imat, cursor_parent); - } - if ((ob->protectflag & OB_LOCK_LOCX) == 0) { - ob->loc[0] += cursor_parent[0]; - } - if ((ob->protectflag & OB_LOCK_LOCY) == 0) { - ob->loc[1] += cursor_parent[1]; - } - if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { - ob->loc[2] += cursor_parent[2]; - } + if (ob->parent) { + float originmat[3][3], parentmat[4][4]; + /* Use the evaluated object here because sometimes + * `ob->parent->runtime.curve_cache` is required. */ + BKE_scene_graph_evaluated_ensure(depsgraph, bmain); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + + BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat); + mul_m3_m4m4(originmat, parentmat, ob->parentinv); + invert_m3_m3(imat, originmat); + mul_m3_v3(imat, cursor_parent); + } + if ((ob->protectflag & OB_LOCK_LOCX) == 0) { + ob->loc[0] += cursor_parent[0]; + } + if ((ob->protectflag & OB_LOCK_LOCY) == 0) { + ob->loc[1] += cursor_parent[1]; + } + if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { + ob->loc[2] += cursor_parent[2]; + } - /* auto-keyframing */ - ED_autokeyframe_object(C, scene, ob, ks); + /* auto-keyframing */ + ED_autokeyframe_object(C, scene, ob, ks); - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); - } + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); } if (objects) { diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index c1ee6edfef6..18cd62a0baf 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -2094,7 +2094,7 @@ void recalcData_mesh(TransInfo *t) tc_mesh_partial_types_calc(t, &partial_state); FOREACH_TRANS_DATA_CONTAINER (t, tc) { - DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY); + DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY_DEFORM); tc_mesh_partial_update(t, tc, &partial_state); } diff --git a/source/blender/editors/transform/transform_convert_mesh_edge.c b/source/blender/editors/transform/transform_convert_mesh_edge.c index 3b1191a3401..2db3e259153 100644 --- a/source/blender/editors/transform/transform_convert_mesh_edge.c +++ b/source/blender/editors/transform/transform_convert_mesh_edge.c @@ -28,6 +28,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" diff --git a/source/blender/editors/transform/transform_convert_mesh_uv.c b/source/blender/editors/transform/transform_convert_mesh_uv.c index d91a2a8be4b..61397b6ef4b 100644 --- a/source/blender/editors/transform/transform_convert_mesh_uv.c +++ b/source/blender/editors/transform/transform_convert_mesh_uv.c @@ -30,6 +30,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh_mapping.h" diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index c217478bd04..ee6cb391fdc 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -153,7 +153,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) if (t->mode != TFM_DUMMY && ob->rigidbody_object) { float rot[3][3], scale[3]; - float ctime = BKE_scene_frame_get(scene); + float ctime = BKE_scene_ctime_get(scene); /* only use rigid body transform if simulation is running, * avoids problems with initial setup of rigid bodies */ @@ -978,7 +978,7 @@ void special_aftertrans_update__object(bContext *C, TransInfo *t) /* restore rigid body transform */ if (ob->rigidbody_object && canceled) { - float ctime = BKE_scene_frame_get(t->scene); + float ctime = BKE_scene_ctime_get(t->scene); if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime)) { BKE_rigidbody_aftertrans_update(ob, td->ext->oloc, diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 8a4c8f410c0..2d98d756dba 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -535,7 +535,7 @@ static void iter_snap_objects(SnapObjectContext *sctx, * \{ */ /* Store all ray-hits - * Support for storing all depths, not just the first (raycast 'all') */ + * Support for storing all depths, not just the first (ray-cast 'all'). */ struct RayCastAll_Data { void *bvhdata; @@ -626,7 +626,7 @@ static bool raycast_tri_backface_culling_test( return dot_v3v3(no, dir) < 0.0f; } -/* Callback to raycast with backface culling (Mesh). */ +/* Callback to ray-cast with back-face culling (#Mesh). */ static void mesh_looptri_raycast_backface_culling_cb(void *userdata, int index, const BVHTreeRay *ray, @@ -653,7 +653,7 @@ static void mesh_looptri_raycast_backface_culling_cb(void *userdata, } } -/* Callback to raycast with backface culling (EditMesh). */ +/* Callback to ray-cast with back-face culling (#EditMesh). */ static void editmesh_looptri_raycast_backface_culling_cb(void *userdata, int index, const BVHTreeRay *ray, diff --git a/source/blender/editors/uvedit/uvedit_islands.c b/source/blender/editors/uvedit/uvedit_islands.c index 93948b5ae1b..56bcbc63de1 100644 --- a/source/blender/editors/uvedit/uvedit_islands.c +++ b/source/blender/editors/uvedit/uvedit_islands.c @@ -36,6 +36,7 @@ #include "BLI_math.h" #include "BLI_rect.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "DEG_depsgraph.h" diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index eb4ca2e13b2..f97403a0919 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -2154,7 +2154,7 @@ static void p_collapse_cost_vertex(PVert *vert, float *r_mincost, PEdge **r_mine static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed) { - /* move to collapsed_ */ + /* Move to `collapsed_*`. */ PVert *v, *nextv = NULL, *verts = chart->verts; PEdge *e, *nexte = NULL, *edges = chart->edges, *laste = NULL; @@ -2224,7 +2224,7 @@ static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed) static void p_chart_post_split_flush(PChart *chart) { - /* move from collapsed_ */ + /* Move from `collapsed_*`. */ PVert *v, *nextv = NULL; PEdge *e, *nexte = NULL; @@ -2259,7 +2259,7 @@ static void p_chart_post_split_flush(PChart *chart) static void p_chart_simplify_compute(PChart *chart) { /* Computes a list of edge collapses / vertex splits. The collapsed - * simplices go in the chart->collapsed_* lists, The original and + * simplices go in the `chart->collapsed_*` lists, The original and * collapsed may then be view as stacks, where the next collapse/split * is at the top of the respective lists. */ |