diff options
Diffstat (limited to 'source/blender/editors')
173 files changed, 3088 insertions, 1696 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 4780352e5dc..edb6d188ab8 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -668,7 +668,7 @@ static int acf_object_icon(bAnimListElem *ale) return ICON_OUTLINER_OB_MESH; case OB_CAMERA: return ICON_OUTLINER_OB_CAMERA; - case OB_CURVE: + case OB_CURVES_LEGACY: return ICON_OUTLINER_OB_CURVE; case OB_MBALL: return ICON_OUTLINER_OB_META; @@ -4601,7 +4601,7 @@ void ANIM_channel_draw( /* Draw slider: * - Even if we can draw sliders for this view, * we must also check that the channel-type supports them - * (only only F-Curves really can support them for now). + * (only F-Curves really can support them for now). * - Slider should start before the toggles (if they're visible) * to keep a clean line down the side. */ @@ -5336,7 +5336,7 @@ void ANIM_channel_draw_widgets(const bContext *C, /* Draw slider: * - Even if we can draw sliders for this view, we must also check that the channel-type - * supports them (only only F-Curves really can support them for now). + * supports them (only F-Curves really can support them for now). * - To make things easier, we use RNA-autobuts for this so that changes are * reflected immediately, wherever they occurred. * BUT, we don't use the layout engine, otherwise we'd get wrong alignment, diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index d6163f21c79..0389e57627a 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -2530,9 +2530,9 @@ static size_t animdata_filter_ds_obdata( expanded = FILTER_LAM_OBJD(la); break; } - case OB_CURVE: /* ------- Curve ---------- */ - case OB_SURF: /* ------- Nurbs Surface ---------- */ - case OB_FONT: /* ------- Text Curve ---------- */ + case OB_CURVES_LEGACY: /* ------- Curve ---------- */ + case OB_SURF: /* ------- Nurbs Surface ---------- */ + case OB_FONT: /* ------- Text Curve ---------- */ { Curve *cu = (Curve *)ob->data; diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 9566402ad85..95125516fe8 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -700,7 +700,7 @@ static void MARKER_OT_add(wmOperatorType *ot) typedef struct MarkerMove { SpaceLink *slink; ListBase *markers; - int event_type; /* store invoke-event, to verify */ + short event_type, event_val; /* store invoke-event, to verify */ int *oldframe, evtx, firstx; NumInput num; } MarkerMove; @@ -844,6 +844,7 @@ static int ed_marker_move_invoke(bContext *C, wmOperator *op, const wmEvent *eve mm->evtx = event->xy[0]; mm->firstx = event->xy[0]; mm->event_type = event->type; + mm->event_val = event->val; /* add temp handler */ WM_event_add_modal_handler(C, op); @@ -941,7 +942,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *even case EVT_PADENTER: case LEFTMOUSE: case MIDDLEMOUSE: - if (WM_event_is_modal_tweak_exit(event, mm->event_type)) { + if (WM_event_is_modal_drag_exit(event, mm->event_type, mm->event_val)) { ed_marker_move_exit(C, op); WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); @@ -960,7 +961,13 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *even mm->evtx = event->xy[0]; fac = ((float)(event->xy[0] - mm->firstx) * dx); - apply_keyb_grid(event->shift, event->ctrl, &fac, 0.0, FPS, 0.1 * FPS, 0); + apply_keyb_grid((event->modifier & KM_SHIFT) != 0, + (event->modifier & KM_CTRL) != 0, + &fac, + 0.0, + FPS, + 0.1 * FPS, + 0); RNA_int_set(op->ptr, "frames", (int)fac); ed_marker_move_apply(C, op); diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c index 539227933cf..2c99cd1cc1f 100644 --- a/source/blender/editors/animation/anim_motion_paths.c +++ b/source/blender/editors/animation/anim_motion_paths.c @@ -340,6 +340,55 @@ static void motionpath_free_free_tree_data(ListBase *targets) } } +void animviz_motionpath_compute_range(Object *ob, Scene *scene) +{ + struct AnimKeylist *keylist = ED_keylist_create(); + bAnimVizSettings *avs; + if (ob->mode == OB_MODE_POSE) { + avs = &ob->pose->avs; + bArmature *arm = ob->data; + + if (!ELEM(NULL, ob->adt, ob->adt->action, arm->adt)) { + /* Loop through all the fcurves and get only the keylists for the bone location fcurves */ + LISTBASE_FOREACH (FCurve *, fcu, &ob->adt->action->curves) { + if (strstr(fcu->rna_path, "pose.bones[") && strstr(fcu->rna_path, "location")) { + fcurve_to_keylist(arm->adt, fcu, keylist, 0); + } + } + } + } + else { + avs = &ob->avs; + + if (!ELEM(NULL, ob->adt, ob->adt->action)) { + /* Loop through all the fcurves and get only the keylists for the location fcurves */ + LISTBASE_FOREACH (FCurve *, fcu, &ob->adt->action->curves) { + if (strcmp(fcu->rna_path, "location") == 0) { + fcurve_to_keylist(ob->adt, fcu, keylist, 0); + } + } + } + } + + if (ED_keylist_is_empty(keylist) || (avs->path_range == MOTIONPATH_RANGE_SCENE)) { + /* Apply scene frame range if no keys where found or if scene range is selected */ + avs->path_sf = PSFRA; + avs->path_ef = PEFRA; + } + else { + /* Compute keys range */ + Range2f frame_range; + const bool only_selected = avs->path_range == MOTIONPATH_RANGE_KEYS_SELECTED; + /* Get range for all keys if selected_only is false or if no keys are selected */ + if (!(only_selected && ED_keylist_selected_keys_frame_range(keylist, &frame_range))) { + ED_keylist_all_keys_frame_range(keylist, &frame_range); + } + avs->path_sf = frame_range.min; + avs->path_ef = frame_range.max; + } + ED_keylist_free(keylist); +} + void animviz_calc_motionpaths(Depsgraph *depsgraph, Main *bmain, Scene *scene, diff --git a/source/blender/editors/animation/keyframes_keylist.cc b/source/blender/editors/animation/keyframes_keylist.cc index 3f9592fb4ae..0b795fea278 100644 --- a/source/blender/editors/animation/keyframes_keylist.cc +++ b/source/blender/editors/animation/keyframes_keylist.cc @@ -304,7 +304,21 @@ const struct ListBase *ED_keylist_listbase(const AnimKeylist *keylist) return &keylist->key_columns; } -bool ED_keylist_frame_range(const struct AnimKeylist *keylist, Range2f *r_frame_range) +static void keylist_first_last(const struct AnimKeylist *keylist, + const struct ActKeyColumn **first_column, + const struct ActKeyColumn **last_column) +{ + if (keylist->is_runtime_initialized) { + *first_column = &keylist->runtime.key_columns[0]; + *last_column = &keylist->runtime.key_columns[keylist->column_len - 1]; + } + else { + *first_column = static_cast<const ActKeyColumn *>(keylist->key_columns.first); + *last_column = static_cast<const ActKeyColumn *>(keylist->key_columns.last); + } +} + +bool ED_keylist_all_keys_frame_range(const struct AnimKeylist *keylist, Range2f *r_frame_range) { BLI_assert(r_frame_range); @@ -314,13 +328,33 @@ bool ED_keylist_frame_range(const struct AnimKeylist *keylist, Range2f *r_frame_ const ActKeyColumn *first_column; const ActKeyColumn *last_column; - if (keylist->is_runtime_initialized) { - first_column = &keylist->runtime.key_columns[0]; - last_column = &keylist->runtime.key_columns[keylist->column_len - 1]; + keylist_first_last(keylist, &first_column, &last_column); + r_frame_range->min = first_column->cfra; + r_frame_range->max = last_column->cfra; + + return true; +} + +bool ED_keylist_selected_keys_frame_range(const struct AnimKeylist *keylist, + Range2f *r_frame_range) +{ + BLI_assert(r_frame_range); + + if (ED_keylist_is_empty(keylist)) { + return false; } - else { - first_column = static_cast<const ActKeyColumn *>(keylist->key_columns.first); - last_column = static_cast<const ActKeyColumn *>(keylist->key_columns.last); + + const ActKeyColumn *first_column; + const ActKeyColumn *last_column; + keylist_first_last(keylist, &first_column, &last_column); + while (first_column && !(first_column->sel & SELECT)) { + first_column = first_column->next; + } + while (last_column && !(last_column->sel & SELECT)) { + last_column = last_column->prev; + } + if (!first_column || !last_column || first_column == last_column) { + return false; } r_frame_range->min = first_column->cfra; r_frame_range->max = last_column->cfra; diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index e227e69f9e1..128126e515e 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -220,8 +220,8 @@ static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEven bAnimVizSettings *avs = &ob->pose->avs; PointerRNA avs_ptr; - RNA_int_set(op->ptr, "start_frame", avs->path_sf); - RNA_int_set(op->ptr, "end_frame", avs->path_ef); + RNA_enum_set(op->ptr, "display_type", avs->path_type); + RNA_enum_set(op->ptr, "range", avs->path_range); RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr); RNA_enum_set(op->ptr, "bake_location", RNA_enum_get(&avs_ptr, "bake_location")); @@ -229,7 +229,7 @@ static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEven /* show popup dialog to allow editing of range... */ /* FIXME: hard-coded dimensions here are just arbitrary. */ - return WM_operator_props_dialog_popup(C, op, 200); + return WM_operator_props_dialog_popup(C, op, 270); } /* For the object with pose/action: create path curves for selected bones @@ -249,8 +249,9 @@ static int pose_calculate_paths_exec(bContext *C, wmOperator *op) bAnimVizSettings *avs = &ob->pose->avs; PointerRNA avs_ptr; - avs->path_sf = RNA_int_get(op->ptr, "start_frame"); - avs->path_ef = RNA_int_get(op->ptr, "end_frame"); + avs->path_type = RNA_enum_get(op->ptr, "display_type"); + avs->path_range = RNA_enum_get(op->ptr, "range"); + animviz_motionpath_compute_range(ob, scene); RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr); RNA_enum_set(&avs_ptr, "bake_location", RNA_enum_get(op->ptr, "bake_location")); @@ -258,7 +259,6 @@ static int pose_calculate_paths_exec(bContext *C, wmOperator *op) /* set up path data for bones being calculated */ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones_from_active_object) { - /* verify makes sure that the selected bone has a bone with the appropriate settings */ animviz_verify_motionpaths(op->reports, scene, ob, pchan); } CTX_DATA_END; @@ -281,6 +281,19 @@ static int pose_calculate_paths_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static bool pose_calculate_paths_poll(bContext *C) +{ + if (!ED_operator_posemode_exclusive(C)) { + return false; + } + Object *ob = CTX_data_active_object(C); + bArmature *arm = ob->data; + if (ELEM(NULL, ob, arm, ob->pose)) { + return false; + } + return true; +} + void POSE_OT_paths_calculate(wmOperatorType *ot) { /* identifiers */ @@ -291,30 +304,24 @@ void POSE_OT_paths_calculate(wmOperatorType *ot) /* api callbacks */ ot->invoke = pose_calculate_paths_invoke; ot->exec = pose_calculate_paths_exec; - ot->poll = ED_operator_posemode_exclusive; + ot->poll = pose_calculate_paths_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_int(ot->srna, - "start_frame", - 1, - MINAFRAME, - MAXFRAME, - "Start", - "First frame to calculate bone paths on", - MINFRAME, - MAXFRAME / 2.0); - RNA_def_int(ot->srna, - "end_frame", - 250, - MINAFRAME, - MAXFRAME, - "End", - "Last frame to calculate bone paths on", - MINFRAME, - MAXFRAME / 2.0); + RNA_def_enum(ot->srna, + "display_type", + rna_enum_motionpath_display_type_items, + MOTIONPATH_TYPE_RANGE, + "Display type", + ""); + RNA_def_enum(ot->srna, + "range", + rna_enum_motionpath_range_items, + MOTIONPATH_RANGE_SCENE, + "Computation Range", + ""); RNA_def_enum(ot->srna, "bake_location", @@ -336,7 +343,7 @@ static bool pose_update_paths_poll(bContext *C) return false; } -static int pose_update_paths_exec(bContext *C, wmOperator *UNUSED(op)) +static int pose_update_paths_exec(bContext *C, wmOperator *op) { Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); Scene *scene = CTX_data_scene(C); @@ -344,6 +351,13 @@ static int pose_update_paths_exec(bContext *C, wmOperator *UNUSED(op)) if (ELEM(NULL, ob, scene)) { return OPERATOR_CANCELLED; } + animviz_motionpath_compute_range(ob, scene); + + /* set up path data for bones being calculated */ + CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones_from_active_object) { + animviz_verify_motionpaths(op->reports, scene, ob, pchan); + } + CTX_DATA_END; /* Calculate the bones that now have motion-paths. */ /* TODO: only make for the selected bones? */ @@ -427,7 +441,7 @@ static int pose_clear_paths_exec(bContext *C, wmOperator *op) /* operator callback/wrapper */ static int pose_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if ((event->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) { + if ((event->modifier & KM_SHIFT) && !RNA_struct_property_is_set(op->ptr, "only_selected")) { RNA_boolean_set(op->ptr, "only_selected", true); } return pose_clear_paths_exec(C, op); diff --git a/source/blender/editors/asset/intern/asset_library_reference.cc b/source/blender/editors/asset/intern/asset_library_reference.cc index 04f77821114..5096b9d653d 100644 --- a/source/blender/editors/asset/intern/asset_library_reference.cc +++ b/source/blender/editors/asset/intern/asset_library_reference.cc @@ -17,9 +17,9 @@ AssetLibraryReferenceWrapper::AssetLibraryReferenceWrapper(const AssetLibraryRef bool operator==(const AssetLibraryReferenceWrapper &a, const AssetLibraryReferenceWrapper &b) { - return (a.type == b.type) && (a.type == ASSET_LIBRARY_CUSTOM) ? - (a.custom_library_index == b.custom_library_index) : - true; + return (a.type == b.type) && + ((a.type == ASSET_LIBRARY_CUSTOM) ? (a.custom_library_index == b.custom_library_index) : + true); } uint64_t AssetLibraryReferenceWrapper::hash() const diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 20a2251b6e1..a33fbb29f85 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -72,7 +72,7 @@ static bool curve_delete_vertices(Object *obedit, View3D *v3d); ListBase *object_editcurve_get(Object *ob) { - if (ob && ELEM(ob->type, OB_CURVE, OB_SURF)) { + if (ob && ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) { Curve *cu = ob->data; return &cu->editnurb->nurbs; } @@ -1238,7 +1238,7 @@ void ED_curve_editnurb_load(Main *bmain, Object *obedit) return; } - if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { + if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { Curve *cu = obedit->data; ListBase newnurb = {NULL, NULL}, oldnurb = cu->nurb; @@ -1273,7 +1273,7 @@ void ED_curve_editnurb_make(Object *obedit) EditNurb *editnurb = cu->editnurb; KeyBlock *actkey; - if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { + if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { actkey = BKE_keyblock_from_object(obedit); if (actkey) { @@ -5637,7 +5637,7 @@ static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op)) } /* First test: curve? */ - if (obedit->type != OB_CURVE) { + if (obedit->type != OB_CURVES_LEGACY) { LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if ((nu->pntsv == 1) && (ED_curve_nurb_select_count(v3d, nu) < nu->pntsu)) { as_curve = true; @@ -5646,7 +5646,7 @@ static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op)) } } - if (obedit->type == OB_CURVE || as_curve) { + if (obedit->type == OB_CURVES_LEGACY || as_curve) { changed = ed_editcurve_extrude(cu, editnurb, v3d); } else { @@ -6715,7 +6715,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) Object *obedit = objects[ob_index]; ListBase *editnurb = object_editcurve_get(obedit); - if (obedit->type != OB_CURVE) { + if (obedit->type != OB_CURVES_LEGACY) { continue; } @@ -6874,7 +6874,7 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op) cu = ob_active->data; BLI_movelisttolist(&cu->nurb, &tempbase); - if (ob_active->type == OB_CURVE && CU_IS_2D(cu)) { + if (ob_active->type == OB_CURVES_LEGACY && CU_IS_2D(cu)) { /* Account for mixed 2D/3D curves when joining */ BKE_curve_dimension_update(cu); } @@ -6984,7 +6984,7 @@ static bool match_texture_space_poll(bContext *C) { Object *object = CTX_data_active_object(C); - return object && ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT); + return object && ELEM(object->type, OB_CURVES_LEGACY, OB_SURF, OB_FONT); } static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index 2aaebf494a6..d7201495f75 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -53,25 +53,25 @@ static const char *get_curve_defname(int type) if ((type & CU_TYPE) == CU_BEZIER) { switch (stype) { case CU_PRIM_CURVE: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCurve"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "BezierCurve"); case CU_PRIM_CIRCLE: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCircle"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "BezierCircle"); case CU_PRIM_PATH: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "CurvePath"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "CurvePath"); default: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "Curve"); } } else { switch (stype) { case CU_PRIM_CURVE: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCurve"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "NurbsCurve"); case CU_PRIM_CIRCLE: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCircle"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "NurbsCircle"); case CU_PRIM_PATH: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsPath"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "NurbsPath"); default: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "Curve"); } } } @@ -82,17 +82,17 @@ static const char *get_surf_defname(int type) switch (stype) { case CU_PRIM_CURVE: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCurve"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "SurfCurve"); case CU_PRIM_CIRCLE: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCircle"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "SurfCircle"); case CU_PRIM_PATCH: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfPatch"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "SurfPatch"); case CU_PRIM_SPHERE: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfSphere"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "SurfSphere"); case CU_PRIM_DONUT: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfTorus"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "SurfTorus"); default: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Surface"); + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "Surface"); } } @@ -510,11 +510,11 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) } if (!isSurf) { /* adding curve */ - if (obedit == NULL || obedit->type != OB_CURVE) { + if (obedit == NULL || obedit->type != OB_CURVES_LEGACY) { const char *name = get_curve_defname(type); Curve *cu; - obedit = ED_object_add_type(C, OB_CURVE, name, loc, rot, true, local_view_bits); + obedit = ED_object_add_type(C, OB_CURVES_LEGACY, name, loc, rot, true, local_view_bits); newob = true; cu = (Curve *)obedit->data; diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c index 7b68c859b43..888bb2169e0 100644 --- a/source/blender/editors/curve/editcurve_undo.c +++ b/source/blender/editors/curve/editcurve_undo.c @@ -162,7 +162,7 @@ static Object *editcurve_object_from_context(bContext *C) { ViewLayer *view_layer = CTX_data_view_layer(C); Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); - if (obedit && ELEM(obedit->type, OB_CURVE, OB_SURF)) { + if (obedit && ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { Curve *cu = obedit->data; if (BKE_curve_editNurbs_get(cu) != NULL) { return obedit; diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index b2af0643e2c..02c7f3856e8 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -1640,7 +1640,9 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event) EditFont *ef = cu->editfont; static int accentcode = 0; uintptr_t ascii = event->ascii; - int alt = event->alt, shift = event->shift, ctrl = event->ctrl; + const bool alt = event->modifier & KM_ALT; + const bool shift = event->modifier & KM_SHIFT; + const bool ctrl = event->modifier & KM_CTRL; int event_type = event->type, event_val = event->val; char32_t inserted_text[2] = {0}; diff --git a/source/blender/editors/curves/CMakeLists.txt b/source/blender/editors/curves/CMakeLists.txt index d2b7dacbc20..1731d224b3e 100644 --- a/source/blender/editors/curves/CMakeLists.txt +++ b/source/blender/editors/curves/CMakeLists.txt @@ -6,6 +6,7 @@ set(INC ../../blenlib ../../blentranslation ../../depsgraph + ../../functions ../../makesdna ../../makesrna ../../windowmanager @@ -13,6 +14,7 @@ set(INC ) set(SRC + intern/curves_add.cc intern/curves_ops.cc ) diff --git a/source/blender/editors/curves/intern/curves_add.cc b/source/blender/editors/curves/intern/curves_add.cc new file mode 100644 index 00000000000..9cde23451dc --- /dev/null +++ b/source/blender/editors/curves/intern/curves_add.cc @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup edcurves + */ + +#include "BLI_rand.hh" + +#include "BKE_curves.hh" + +#include "ED_curves.h" + +namespace blender::ed::curves { + +bke::CurvesGeometry primitive_random_sphere(const int curves_size, const int points_per_curve) +{ + bke::CurvesGeometry curves(points_per_curve * curves_size, curves_size); + + MutableSpan<int> offsets = curves.offsets(); + MutableSpan<float3> positions = curves.positions(); + + float *radius_data = (float *)CustomData_add_layer_named( + &curves.point_data, CD_PROP_FLOAT, CD_DEFAULT, nullptr, curves.point_size, "radius"); + MutableSpan<float> radii{radius_data, curves.points_size()}; + + for (const int i : offsets.index_range()) { + offsets[i] = points_per_curve * i; + } + + RandomNumberGenerator rng; + + for (const int i : curves.curves_range()) { + const IndexRange curve_range = curves.range_for_curve(i); + MutableSpan<float3> curve_positions = positions.slice(curve_range); + MutableSpan<float> curve_radii = radii.slice(curve_range); + + const float theta = 2.0f * M_PI * rng.get_float(); + const float phi = saacosf(2.0f * rng.get_float() - 1.0f); + + float3 no = {std::sin(theta) * std::sin(phi), std::cos(theta) * std::sin(phi), std::cos(phi)}; + no = math::normalize(no); + + float3 co = no; + for (int key = 0; key < points_per_curve; key++) { + float t = key / (float)(points_per_curve - 1); + curve_positions[key] = co; + curve_radii[key] = 0.02f * (1.0f - t); + + float3 offset = float3(rng.get_float(), rng.get_float(), rng.get_float()) * 2.0f - 1.0f; + co += (offset + no) / points_per_curve; + } + } + + return curves; +} + +} // namespace blender::ed::curves diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc index fdda8e636f7..52a55ae1760 100644 --- a/source/blender/editors/curves/intern/curves_ops.cc +++ b/source/blender/editors/curves/intern/curves_ops.cc @@ -4,67 +4,8 @@ * \ingroup edcurves */ -#include "BLI_utildefines.h" - #include "ED_curves.h" -#include "ED_object.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "BKE_context.h" - -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_types.h" - -static bool curves_sculptmode_toggle_poll(bContext *C) -{ - Object *ob = CTX_data_active_object(C); - if (ob == nullptr) { - return false; - } - if (ob->type != OB_CURVES) { - return false; - } - return true; -} - -static int curves_sculptmode_toggle_exec(bContext *C, wmOperator *op) -{ - Object *ob = CTX_data_active_object(C); - const bool is_mode_set = ob->mode == OB_MODE_SCULPT_CURVES; - - if (is_mode_set) { - if (!ED_object_mode_compat_set(C, ob, OB_MODE_SCULPT_CURVES, op->reports)) { - return OPERATOR_CANCELLED; - } - } - - if (is_mode_set) { - ob->mode = OB_MODE_OBJECT; - } - else { - ob->mode = OB_MODE_SCULPT_CURVES; - } - - WM_event_add_notifier(C, NC_SCENE | ND_MODE, nullptr); - return OPERATOR_CANCELLED; -} - -static void CURVES_OT_sculptmode_toggle(wmOperatorType *ot) -{ - ot->name = "Curve Sculpt Mode Toggle"; - ot->idname = "CURVES_OT_sculptmode_toggle"; - ot->description = "Enter/Exit sculpt mode for curves"; - - ot->exec = curves_sculptmode_toggle_exec; - ot->poll = curves_sculptmode_toggle_poll; - - ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER; -} void ED_operatortypes_curves() { - WM_operatortype_append(CURVES_OT_sculptmode_toggle); } diff --git a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c index aea6d41202e..447fe1005a1 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c @@ -147,7 +147,7 @@ static void move3d_get_translate(const wmGizmo *gz, float co_delta[3]) { MoveInteraction *inter = gz->interaction_data; - const float mval_delta[2] = { + const float xy_delta[2] = { event->mval[0] - inter->init.mval[0], event->mval[1] - inter->init.mval[1], }; @@ -155,9 +155,9 @@ static void move3d_get_translate(const wmGizmo *gz, RegionView3D *rv3d = region->regiondata; float co_ref[3]; mul_v3_mat3_m4v3(co_ref, gz->matrix_space, inter->init.prop_co); - const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL); + const float zfac = ED_view3d_calc_zfac(rv3d, co_ref); - ED_view3d_win_to_delta(region, mval_delta, co_delta, zfac); + ED_view3d_win_to_delta(region, xy_delta, zfac, co_delta); float matrix_space_inv[3][3]; copy_m3_m4(matrix_space_inv, gz->matrix_space); diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 163b5657326..5ab4a663efe 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -326,8 +326,7 @@ static void annotation_stroke_convertcoords(tGPsdata *p, } else { float mval_prj[2]; - float rvec[3], dvec[3]; - float zfac; + float rvec[3]; /* Current method just converts each point in screen-coordinates to * 3D-coordinates using the 3D-cursor as reference. In general, this @@ -339,13 +338,14 @@ static void annotation_stroke_convertcoords(tGPsdata *p, */ annotation_get_3d_reference(p, rvec); - zfac = ED_view3d_calc_zfac(p->region->regiondata, rvec, NULL); + const float zfac = ED_view3d_calc_zfac(p->region->regiondata, rvec); if (ED_view3d_project_float_global(p->region, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - float mval_f[2]; - sub_v2_v2v2(mval_f, mval_prj, mval); - ED_view3d_win_to_delta(p->region, mval_f, dvec, zfac); + float dvec[3]; + float xy_delta[2]; + sub_v2_v2v2(xy_delta, mval_prj, mval); + ED_view3d_win_to_delta(p->region, xy_delta, zfac, dvec); sub_v3_v3v3(out, rvec, dvec); } else { @@ -2060,7 +2060,7 @@ static void annotation_draw_apply_event( p->mval[1] = (float)event->mval[1] - y; /* Key to toggle stabilization. */ - if (event->shift && p->paintmode == GP_PAINTMODE_DRAW) { + if ((event->modifier & KM_SHIFT) && (p->paintmode == GP_PAINTMODE_DRAW)) { /* Using permanent stabilization, shift will deactivate the flag. */ if (p->flags & GP_PAINTFLAG_USE_STABILIZER) { if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { @@ -2075,7 +2075,7 @@ static void annotation_draw_apply_event( } } /* verify key status for straight lines */ - else if (event->ctrl || event->alt) { + else if (event->modifier & (KM_CTRL | KM_ALT)) { if (p->straight[0] == 0) { int dx = abs((int)(p->mval[0] - p->mvalo[0])); int dy = abs((int)(p->mval[1] - p->mvalo[1])); @@ -2299,7 +2299,7 @@ static int annotation_draw_invoke(bContext *C, wmOperator *op, const wmEvent *ev p->flags |= GP_PAINTFLAG_USE_STABILIZER | GP_PAINTFLAG_USE_STABILIZER_TEMP; annotation_draw_toggle_stabilizer_cursor(p, true); } - else if (event->shift) { + else if (event->modifier & KM_SHIFT) { p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; annotation_draw_toggle_stabilizer_cursor(p, true); } diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 63239fd6341..d4518f21586 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -1300,8 +1300,8 @@ static void gpencil_layer_to_curve(bContext *C, /* init the curve object (remove rotation and get curve data from it) * - must clear transforms set on object, as those skew our results */ - ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info); - cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE); + ob = BKE_object_add_only_object(bmain, OB_CURVES_LEGACY, gpl->info); + cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVES_LEGACY); BKE_collection_object_add(bmain, collection, ob); base_new = BKE_view_layer_base_find(view_layer, ob); DEG_relations_tag_update(bmain); /* added object */ diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 680b313c47b..d734fb2678e 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -4356,6 +4356,7 @@ static int gpencil_stroke_sample_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); const float length = RNA_float_get(op->ptr, "length"); + const float sharp_threshold = RNA_float_get(op->ptr, "sharp_threshold"); /* sanity checks */ if (ELEM(NULL, gpd)) { @@ -4365,7 +4366,7 @@ static int gpencil_stroke_sample_exec(bContext *C, wmOperator *op) /* Go through each editable + selected stroke */ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { if (gps->flag & GP_STROKE_SELECT) { - BKE_gpencil_stroke_sample(gpd, gps, length, true); + BKE_gpencil_stroke_sample(gpd, gps, length, true, sharp_threshold); } } GP_EDITABLE_STROKES_END(gpstroke_iter); diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 8be34a35ca9..069493025dc 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -1097,7 +1097,7 @@ static void gpencil_erase_processed_area(tGPDfill *tgpf) /** * Naive dilate * - * Expand green areas into enclosing red areas. + * Expand green areas into enclosing red or transparent areas. * Using stack prevents creep when replacing colors directly. * <pre> * ----------- @@ -1110,8 +1110,8 @@ static void gpencil_erase_processed_area(tGPDfill *tgpf) */ static bool dilate_shape(ImBuf *ibuf) { -#define IS_RED (color[0] == 1.0f) #define IS_GREEN (color[1] == 1.0f) +#define IS_NOT_GREEN (color[1] != 1.0f) bool done = false; @@ -1140,7 +1140,7 @@ static bool dilate_shape(ImBuf *ibuf) if (v - 1 >= 0) { index = v - 1; get_pixel(ibuf, index, color); - if (IS_RED) { + if (IS_NOT_GREEN) { BLI_stack_push(stack, &index); lt = index; } @@ -1149,7 +1149,7 @@ static bool dilate_shape(ImBuf *ibuf) if (v + 1 <= maxpixel) { index = v + 1; get_pixel(ibuf, index, color); - if (IS_RED) { + if (IS_NOT_GREEN) { BLI_stack_push(stack, &index); rt = index; } @@ -1158,7 +1158,7 @@ static bool dilate_shape(ImBuf *ibuf) if (v + ibuf->x <= max_size) { index = v + ibuf->x; get_pixel(ibuf, index, color); - if (IS_RED) { + if (IS_NOT_GREEN) { BLI_stack_push(stack, &index); tp = index; } @@ -1167,7 +1167,7 @@ static bool dilate_shape(ImBuf *ibuf) if (v - ibuf->x >= 0) { index = v - ibuf->x; get_pixel(ibuf, index, color); - if (IS_RED) { + if (IS_NOT_GREEN) { BLI_stack_push(stack, &index); bm = index; } @@ -1176,7 +1176,7 @@ static bool dilate_shape(ImBuf *ibuf) if (tp && lt) { index = tp - 1; get_pixel(ibuf, index, color); - if (IS_RED) { + if (IS_NOT_GREEN) { BLI_stack_push(stack, &index); } } @@ -1184,7 +1184,7 @@ static bool dilate_shape(ImBuf *ibuf) if (tp && rt) { index = tp + 1; get_pixel(ibuf, index, color); - if (IS_RED) { + if (IS_NOT_GREEN) { BLI_stack_push(stack, &index); } } @@ -1192,7 +1192,7 @@ static bool dilate_shape(ImBuf *ibuf) if (bm && lt) { index = bm - 1; get_pixel(ibuf, index, color); - if (IS_RED) { + if (IS_NOT_GREEN) { BLI_stack_push(stack, &index); } } @@ -1200,7 +1200,7 @@ static bool dilate_shape(ImBuf *ibuf) if (bm && rt) { index = bm + 1; get_pixel(ibuf, index, color); - if (IS_RED) { + if (IS_NOT_GREEN) { BLI_stack_push(stack, &index); } } @@ -1218,8 +1218,8 @@ static bool dilate_shape(ImBuf *ibuf) return done; -#undef IS_RED #undef IS_GREEN +#undef IS_NOT_GREEN } /** @@ -1239,7 +1239,7 @@ static bool contract_shape(ImBuf *ibuf) const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; const int max_size = (ibuf->x * ibuf->y) - 1; - /* Detect if pixel is near of no green pixels and mark green to be cleared. */ + /* Detect if pixel is near of no green pixels and mark green pixel to be cleared. */ for (int row = 0; row < ibuf->y; row++) { if (!is_row_filled(ibuf, row)) { continue; @@ -2172,7 +2172,8 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) tgpf->on_back = RNA_boolean_get(op->ptr, "on_back"); const bool is_brush_inv = brush_settings->fill_direction == BRUSH_DIR_IN; - const bool is_inverted = (is_brush_inv && !event->ctrl) || (!is_brush_inv && event->ctrl); + const bool is_inverted = (is_brush_inv && (event->modifier & KM_CTRL) == 0) || + (!is_brush_inv && (event->modifier & KM_CTRL) != 0); const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(tgpf->gpd); const bool do_extend = (tgpf->fill_extend_fac > 0.0f); const bool help_lines = ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) || @@ -2313,7 +2314,7 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) case EVT_PAGEUPKEY: case WHEELUPMOUSE: if (tgpf->oldkey == 1) { - tgpf->fill_extend_fac -= (event->shift) ? 0.01f : 0.1f; + tgpf->fill_extend_fac -= (event->modifier & KM_SHIFT) ? 0.01f : 0.1f; CLAMP_MIN(tgpf->fill_extend_fac, 0.0f); gpencil_update_extend(tgpf); } @@ -2321,7 +2322,7 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) case EVT_PAGEDOWNKEY: case WHEELDOWNMOUSE: if (tgpf->oldkey == 1) { - tgpf->fill_extend_fac += (event->shift) ? 0.01f : 0.1f; + tgpf->fill_extend_fac += (event->modifier & KM_SHIFT) ? 0.01f : 0.1f; CLAMP_MAX(tgpf->fill_extend_fac, 100.0f); gpencil_update_extend(tgpf); } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index a6691a12505..5409cea2a2a 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -235,7 +235,7 @@ typedef struct tGPsdata { /** key used for invoking the operator */ short keymodifier; /** shift modifier flag */ - short shift; + bool shift; /** size in pixels for uv calculation */ float totpixlen; /** Special mode for fill brush. */ @@ -447,21 +447,21 @@ static void gpencil_stroke_convertcoords(tGPsdata *p, } float mval_prj[2]; - float rvec[3], dvec[3]; - float mval_f[2]; - float zfac; + float rvec[3]; /* Current method just converts each point in screen-coordinates to * 3D-coordinates using the 3D-cursor as reference. In general, this * works OK, but it could of course be improved. */ gpencil_get_3d_reference(p, rvec); - zfac = ED_view3d_calc_zfac(p->region->regiondata, rvec, NULL); + const float zfac = ED_view3d_calc_zfac(p->region->regiondata, rvec); if (ED_view3d_project_float_global(p->region, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - sub_v2_v2v2(mval_f, mval_prj, mval); - ED_view3d_win_to_delta(p->region, mval_f, dvec, zfac); + float dvec[3]; + float xy_delta[2]; + sub_v2_v2v2(xy_delta, mval_prj, mval); + ED_view3d_win_to_delta(p->region, xy_delta, zfac, dvec); sub_v3_v3v3(out, rvec, dvec); } else { @@ -2841,11 +2841,11 @@ static void gpencil_draw_apply_event(bContext *C, * add any x,y override position */ copy_v2fl_v2i(p->mval, event->mval); - p->shift = event->shift; + p->shift = (event->modifier & KM_SHIFT) != 0; /* verify direction for straight lines and guides */ if ((is_speed_guide) || - (event->alt && (RNA_boolean_get(op->ptr, "disable_straight") == false))) { + ((event->modifier & KM_ALT) && (RNA_boolean_get(op->ptr, "disable_straight") == false))) { if (p->straight == 0) { int dx = (int)fabsf(p->mval[0] - p->mvali[0]); int dy = (int)fabsf(p->mval[1] - p->mvali[1]); @@ -2886,13 +2886,13 @@ static void gpencil_draw_apply_event(bContext *C, /* special eraser modes */ if (p->paintmode == GP_PAINTMODE_ERASER) { - if (event->shift) { + if (event->modifier & KM_SHIFT) { p->flags |= GP_PAINTFLAG_HARD_ERASER; } else { p->flags &= ~GP_PAINTFLAG_HARD_ERASER; } - if (event->alt) { + if (event->modifier & KM_ALT) { p->flags |= GP_PAINTFLAG_STROKE_ERASER; } else { @@ -3116,11 +3116,11 @@ static void gpencil_guide_event_handling(bContext *C, else if ((event->type == EVT_LKEY) && (event->val == KM_RELEASE)) { add_notifier = true; guide->use_guide = true; - if (event->ctrl) { + if (event->modifier & KM_CTRL) { guide->angle = 0.0f; guide->type = GP_GUIDE_PARALLEL; } - else if (event->alt) { + else if (event->modifier & KM_ALT) { guide->type = GP_GUIDE_PARALLEL; guide->angle = RNA_float_get(op->ptr, "guide_last_angle"); } @@ -3150,10 +3150,10 @@ static void gpencil_guide_event_handling(bContext *C, add_notifier = true; float angle = guide->angle; float adjust = (float)M_PI / 180.0f; - if (event->alt) { + if (event->modifier & KM_ALT) { adjust *= 45.0f; } - else if (!event->shift) { + else if ((event->modifier & KM_SHIFT) == 0) { adjust *= 15.0f; } angle += (event->type == EVT_JKEY) ? adjust : -adjust; @@ -3633,7 +3633,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) */ } else if (event->type == EVT_ZKEY) { - if (event->ctrl) { + if (event->modifier & KM_CTRL) { p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 2d761dd6c91..57a184b0e8d 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -1494,7 +1494,7 @@ static void gpencil_primitive_edit_event_handling( float dy = (tgpi->mval[1] - tgpi->mvalo[1]); tgpi->cp1[0] += dx; tgpi->cp1[1] += dy; - if (event->shift) { + if (event->modifier & KM_SHIFT) { copy_v2_v2(tgpi->cp2, tgpi->cp1); } } @@ -1503,7 +1503,7 @@ static void gpencil_primitive_edit_event_handling( float dy = (tgpi->mval[1] - tgpi->mvalo[1]); tgpi->cp2[0] += dx; tgpi->cp2[1] += dy; - if (event->shift) { + if (event->modifier & KM_SHIFT) { copy_v2_v2(tgpi->cp1, tgpi->cp2); } } @@ -1692,7 +1692,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e WM_cursor_modal_set(win, WM_CURSOR_NSEW_SCROLL); copy_v2_v2(tgpi->end, tgpi->mval); - if (event->shift) { + if (event->modifier & KM_SHIFT) { gpencil_primitive_constrain(tgpi, true); } @@ -1722,7 +1722,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e case EVT_FKEY: /* brush thickness/ brush strength */ { if ((event->val == KM_PRESS)) { - if (event->shift) { + if (event->modifier & KM_SHIFT) { tgpi->prev_flag = tgpi->flag; tgpi->flag = IN_BRUSH_STRENGTH; } @@ -1900,7 +1900,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e case EVT_FKEY: /* brush thickness/ brush strength */ { if ((event->val == KM_PRESS)) { - if (event->shift) { + if (event->modifier & KM_SHIFT) { tgpi->prev_flag = tgpi->flag; tgpi->flag = IN_BRUSH_STRENGTH; } @@ -1954,12 +1954,12 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e copy_v2_v2(tgpi->origin, tgpi->mval); } /* Keep square if shift key */ - if (event->shift) { + if (event->modifier & KM_SHIFT) { gpencil_primitive_constrain( tgpi, (ELEM(tgpi->type, GP_STROKE_LINE, GP_STROKE_POLYLINE) || tgpi->curve)); } /* Center primitive if alt key */ - if (event->alt && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) { + if ((event->modifier & KM_ALT) && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) { tgpi->start[0] = tgpi->origin[0] - (tgpi->end[0] - tgpi->origin[0]); tgpi->start[1] = tgpi->origin[1] - (tgpi->end[1] - tgpi->origin[1]); } diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index e8f097d0018..67325e8a3d1 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -507,7 +507,7 @@ static void gpencil_brush_grab_calc_dvec(tGP_BrushEditData *gso) /* Convert mouse-movements to movement vector */ RegionView3D *rv3d = gso->region->regiondata; float *rvec = gso->object->loc; - float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL); + const float zfac = ED_view3d_calc_zfac(rv3d, rvec); float mval_f[2]; @@ -525,7 +525,7 @@ static void gpencil_brush_grab_calc_dvec(tGP_BrushEditData *gso) copy_v2_v2(mval_f, r); } - ED_view3d_win_to_delta(gso->region, mval_f, gso->dvec, zfac); + ED_view3d_win_to_delta(gso->region, mval_f, zfac, gso->dvec); } /* Apply grab transform to all relevant points of the affected strokes */ @@ -624,17 +624,16 @@ static void gpencil_brush_calc_midpoint(tGP_BrushEditData *gso) */ RegionView3D *rv3d = gso->region->regiondata; const float *rvec = gso->object->loc; - float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL); + const float zfac = ED_view3d_calc_zfac(rv3d, rvec); - float mval_f[2]; - copy_v2_v2(mval_f, gso->mval); float mval_prj[2]; - float dvec[3]; if (ED_view3d_project_float_global(gso->region, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - sub_v2_v2v2(mval_f, mval_prj, mval_f); - ED_view3d_win_to_delta(gso->region, mval_f, dvec, zfac); + float dvec[3]; + float xy_delta[2]; + sub_v2_v2v2(xy_delta, mval_prj, gso->mval); + ED_view3d_win_to_delta(gso->region, xy_delta, zfac, dvec); sub_v3_v3v3(gso->dvec, rvec, dvec); } else { @@ -830,10 +829,10 @@ static bool gpencil_brush_randomize_apply(tGP_BrushEditData *gso, /* 3D: Project to 3D space */ bool flip; RegionView3D *rv3d = gso->region->regiondata; - float zfac = ED_view3d_calc_zfac(rv3d, &pt->x, &flip); + const float zfac = ED_view3d_calc_zfac_ex(rv3d, &pt->x, &flip); if (flip == false) { float dvec[3]; - ED_view3d_win_to_delta(gso->gsc.region, svec, dvec, zfac); + ED_view3d_win_to_delta(gso->gsc.region, svec, zfac, dvec); add_v3_v3(&pt->x, dvec); /* compute lock axis */ gpencil_sculpt_compute_lock_axis(gso, pt, save_pt); @@ -1883,7 +1882,7 @@ static void gpencil_sculpt_brush_apply_event(bContext *C, wmOperator *op, const RNA_collection_add(op->ptr, "stroke", &itemptr); RNA_float_set_array(&itemptr, "mouse", mouse); - RNA_boolean_set(&itemptr, "pen_flip", event->ctrl != false); + RNA_boolean_set(&itemptr, "pen_flip", (event->modifier & KM_CTRL) != 0); RNA_boolean_set(&itemptr, "is_start", gso->first); /* handle pressure sensitivity (which is supplied by tablets and otherwise 1.0) */ @@ -1895,7 +1894,7 @@ static void gpencil_sculpt_brush_apply_event(bContext *C, wmOperator *op, const } RNA_float_set(&itemptr, "pressure", pressure); - if (event->shift) { + if (event->modifier & KM_SHIFT) { gso->brush_prev = gso->brush; gso->brush = gpencil_sculpt_get_smooth_brush(gso); diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index da263d44fc6..fca4ff84dc5 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -2659,7 +2659,7 @@ static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *eve RNA_int_set_array(op->ptr, "location", event->mval); if (!RNA_struct_property_is_set(op->ptr, "use_shift_extend")) { - RNA_boolean_set(op->ptr, "use_shift_extend", event->shift); + RNA_boolean_set(op->ptr, "use_shift_extend", event->modifier & KM_SHIFT); } return gpencil_select_exec(C, op); diff --git a/source/blender/editors/gpencil/gpencil_trace_utils.c b/source/blender/editors/gpencil/gpencil_trace_utils.c index 10be8c3e91e..735759d40ec 100644 --- a/source/blender/editors/gpencil/gpencil_trace_utils.c +++ b/source/blender/editors/gpencil/gpencil_trace_utils.c @@ -314,7 +314,7 @@ void ED_gpencil_trace_data_to_strokes(Main *bmain, if (sample > 0.0f) { /* Resample stroke. Don't need to call to BKE_gpencil_stroke_geometry_update() because * the sample function already call that. */ - BKE_gpencil_stroke_sample(gpd, gps, sample, false); + BKE_gpencil_stroke_sample(gpd, gps, sample, false, 0); } else { BKE_gpencil_stroke_geometry_update(gpd, gps); diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index c0777ac3105..9a658b68f21 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -822,17 +822,16 @@ bool gpencil_point_xy_to_3d(const GP_SpaceConversion *gsc, ED_gpencil_drawing_reference_get(scene, gsc->ob, scene->toolsettings->gpencil_v3d_align, rvec); - float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL); + float zfac = ED_view3d_calc_zfac(rv3d, rvec); - float mval_f[2], mval_prj[2]; - float dvec[3]; - - copy_v2_v2(mval_f, screen_co); + float mval_prj[2]; if (ED_view3d_project_float_global(gsc->region, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - sub_v2_v2v2(mval_f, mval_prj, mval_f); - ED_view3d_win_to_delta(gsc->region, mval_f, dvec, zfac); + float dvec[3]; + float xy_delta[2]; + sub_v2_v2v2(xy_delta, mval_prj, screen_co); + ED_view3d_win_to_delta(gsc->region, xy_delta, zfac, dvec); sub_v3_v3v3(r_out, rvec, dvec); return true; @@ -863,21 +862,21 @@ void gpencil_stroke_convertcoords_tpoint(Scene *scene, */ } else { - float mval_f[2] = {UNPACK2(point2D->m_xy)}; float mval_prj[2]; - float rvec[3], dvec[3]; - float zfac; + float rvec[3]; /* Current method just converts each point in screen-coordinates to * 3D-coordinates using the 3D-cursor as reference. */ ED_gpencil_drawing_reference_get(scene, ob, ts->gpencil_v3d_align, rvec); - zfac = ED_view3d_calc_zfac(region->regiondata, rvec, NULL); + const float zfac = ED_view3d_calc_zfac(region->regiondata, rvec); if (ED_view3d_project_float_global(region, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - sub_v2_v2v2(mval_f, mval_prj, mval_f); - ED_view3d_win_to_delta(region, mval_f, dvec, zfac); + float dvec[3]; + float xy_delta[2]; + sub_v2_v2v2(xy_delta, mval_prj, point2D->m_xy); + ED_view3d_win_to_delta(region, xy_delta, zfac, dvec); sub_v3_v3v3(r_out, rvec, dvec); } else { @@ -2005,19 +2004,19 @@ static void gpencil_stroke_convertcoords(ARegion *region, const float origin[3], float out[3]) { - float mval_f[2] = {UNPACK2(point2D->m_xy)}; float mval_prj[2]; - float rvec[3], dvec[3]; - float zfac; + float rvec[3]; copy_v3_v3(rvec, origin); - zfac = ED_view3d_calc_zfac(region->regiondata, rvec, NULL); + const float zfac = ED_view3d_calc_zfac(region->regiondata, rvec); if (ED_view3d_project_float_global(region, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - sub_v2_v2v2(mval_f, mval_prj, mval_f); - ED_view3d_win_to_delta(region, mval_f, dvec, zfac); + float dvec[3]; + float xy_delta[2]; + sub_v2_v2v2(xy_delta, mval_prj, point2D->m_xy); + ED_view3d_win_to_delta(region, xy_delta, zfac, dvec); sub_v3_v3v3(out, rvec, dvec); } else { diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index 1d1b00e3f08..244942a87ba 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -1241,7 +1241,7 @@ static void gpencil_vertexpaint_brush_apply_event(bContext *C, RNA_collection_add(op->ptr, "stroke", &itemptr); RNA_float_set_array(&itemptr, "mouse", mouse); - RNA_boolean_set(&itemptr, "pen_flip", event->ctrl != false); + RNA_boolean_set(&itemptr, "pen_flip", event->modifier & KM_CTRL); RNA_boolean_set(&itemptr, "is_start", gso->first); /* Handle pressure sensitivity (which is supplied by tablets). */ diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c index 8fe4cba7021..01e73cd2abd 100644 --- a/source/blender/editors/gpencil/gpencil_weight_paint.c +++ b/source/blender/editors/gpencil/gpencil_weight_paint.c @@ -698,7 +698,7 @@ static void gpencil_weightpaint_brush_apply_event(bContext *C, RNA_collection_add(op->ptr, "stroke", &itemptr); RNA_float_set_array(&itemptr, "mouse", mouse); - RNA_boolean_set(&itemptr, "pen_flip", event->ctrl != false); + RNA_boolean_set(&itemptr, "pen_flip", event->modifier & KM_CTRL); RNA_boolean_set(&itemptr, "is_start", gso->first); /* Handle pressure sensitivity (which is supplied by tablets). */ diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index e6a68f7fab7..4b6f5e4cac6 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -1090,6 +1090,15 @@ void animviz_calc_motionpaths(struct Depsgraph *depsgraph, bool restore); /** + * Update motion path computation range (in `ob.avs` or `armature.avs`) from user choice in + * `ob.avs.path_range` or `arm.avs.path_range`, depending on active user mode. + * + * \param ob: Object to compute range for (must be provided). + * \param scene: Used when scene range is chosen. + */ +void animviz_motionpath_compute_range(struct Object *ob, struct Scene *scene); + +/** * Get list of motion paths to be baked for the given object. * - assumes the given list is ready to be used. */ diff --git a/source/blender/editors/include/ED_curves.h b/source/blender/editors/include/ED_curves.h index 7316b045646..9233b65b2ce 100644 --- a/source/blender/editors/include/ED_curves.h +++ b/source/blender/editors/include/ED_curves.h @@ -15,3 +15,14 @@ void ED_operatortypes_curves(void); #ifdef __cplusplus } #endif + +#ifdef __cplusplus + +# include "BKE_curves.hh" + +namespace blender::ed::curves { + +bke::CurvesGeometry primitive_random_sphere(int curves_size, int points_per_curve); + +} +#endif diff --git a/source/blender/editors/include/ED_curves_sculpt.h b/source/blender/editors/include/ED_curves_sculpt.h new file mode 100644 index 00000000000..8aab1533e25 --- /dev/null +++ b/source/blender/editors/include/ED_curves_sculpt.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup editors + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void ED_operatortypes_sculpt_curves(void); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/editors/include/ED_keyframes_keylist.h b/source/blender/editors/include/ED_keyframes_keylist.h index 6a8820d0083..fd3d35e1df7 100644 --- a/source/blender/editors/include/ED_keyframes_keylist.h +++ b/source/blender/editors/include/ED_keyframes_keylist.h @@ -131,7 +131,13 @@ const struct ActKeyColumn *ED_keylist_find_any_between(const struct AnimKeylist const Range2f frame_range); bool ED_keylist_is_empty(const struct AnimKeylist *keylist); const struct ListBase /* ActKeyColumn */ *ED_keylist_listbase(const struct AnimKeylist *keylist); -bool ED_keylist_frame_range(const struct AnimKeylist *keylist, Range2f *r_frame_range); +bool ED_keylist_all_keys_frame_range(const struct AnimKeylist *keylist, Range2f *r_frame_range); +/** + * Return the selected key-frame's range. + * \return False If none are selected and does not affect the frame range. + */ +bool ED_keylist_selected_keys_frame_range(const struct AnimKeylist *keylist, + Range2f *r_frame_range); const ActKeyColumn *ED_keylist_array(const struct AnimKeylist *keylist); int64_t ED_keylist_array_len(const struct AnimKeylist *keylist); @@ -183,10 +189,10 @@ void mask_to_keylist(struct bDopeSheet *ads, /* ActKeyColumn API ---------------- */ -/* Checks if ActKeyColumn has any block data */ +/** Checks if #ActKeyColumn has any block data. */ bool actkeyblock_is_valid(const ActKeyColumn *ac); -/* Checks if ActKeyColumn can be used as a block (i.e. drawn/used to detect "holds") */ +/** Checks if #ActKeyColumn can be used as a block (i.e. drawn/used to detect "holds"). */ int actkeyblock_get_valid_hold(const ActKeyColumn *ac); #ifdef __cplusplus diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h index e1b6a935d6d..ee40cc75e1e 100644 --- a/source/blender/editors/include/ED_render.h +++ b/source/blender/editors/include/ED_render.h @@ -24,6 +24,7 @@ struct Scene; struct ScrArea; struct bContext; struct bScreen; +struct PreviewImage; struct wmWindow; struct wmWindowManager; @@ -87,16 +88,13 @@ void ED_preview_shader_job(const struct bContext *C, ePreviewRenderMethod method); void ED_preview_icon_render(const struct bContext *C, struct Scene *scene, + struct PreviewImage *prv_img, struct ID *id, - unsigned int *rect, - int sizex, - int sizey); + enum eIconSizes icon_size); void ED_preview_icon_job(const struct bContext *C, - void *owner, + struct PreviewImage *prv_img, struct ID *id, - unsigned int *rect, - int sizex, - int sizey, + enum eIconSizes icon_size, bool delay); void ED_preview_restart_queue_free(void); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 5b439cb0978..c89df9c3789 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -250,6 +250,12 @@ void ED_area_offscreen_free(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *area); +/** + * Search all screens, even non-active or overlapping (multiple windows), return the most-likely + * area of interest. xy is relative to active window, like all similar functions. + */ +ScrArea *ED_area_find_under_cursor(const struct bContext *C, int spacetype, const int xy[2]); + ScrArea *ED_screen_areas_iter_first(const struct wmWindow *win, const bScreen *screen); ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area); /** diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index bd3a6bce8e8..f235f696ccc 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -106,7 +106,7 @@ void ED_slider_allow_overshoot_set(struct tSlider *slider, bool value); * \note Shift/Control are not configurable key-bindings. */ void apply_keyb_grid( - int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert); + bool shift, bool ctrl, float *val, float fac1, float fac2, float fac3, int invert); /* where else to go ? */ void unpack_menu(struct bContext *C, diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 46c9a1973eb..b1435e76eb2 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -507,9 +507,18 @@ float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3]); float ED_view3d_pixel_size_no_ui_scale(const struct RegionView3D *rv3d, const float co[3]); /** - * Calculate a depth value from \a co, use with #ED_view3d_win_to_delta + * Calculate a depth value from \a co, use with #ED_view3d_win_to_delta. + * + * \param r_flip: Set to `zfac < 0.0` before the value is made signed. + * Since it's important in some cases to know if the value was flipped. + * + * \return The unsigned depth component of `co` multiplied by `rv3d->persmat` matrix, + * with additional sanitation to ensure the result is never negative + * as this isn't useful for tool-code. */ -float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip); +float ED_view3d_calc_zfac_ex(const struct RegionView3D *rv3d, const float co[3], bool *r_flip); +/** See #ED_view3d_calc_zfac_ex doc-string. */ +float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3]); /** * Calculate a depth value from `co` (result should only be used for comparison). */ @@ -627,16 +636,24 @@ bool ED_view3d_win_to_3d_on_plane_int(const struct ARegion *region, float r_out[3]); /** * Calculate a 3d difference vector from 2d window offset. - * note that #ED_view3d_calc_zfac() must be called first to determine + * + * \note that #ED_view3d_calc_zfac() must be called first to determine * the depth used to calculate the delta. + * + * When the `zfac` is calculated based on a world-space location directly under the cursor, + * the value of `r_out` can be subtracted from #RegionView3D.ofs to pan the view + * with the contents following the cursor perfectly (without sliding). + * * \param region: The region (used for the window width and height). - * \param mval: The area relative 2d difference (such as `event->mval[0] - other_x`). - * \param out: The resulting world-space delta. + * \param xy_delta: 2D difference (in pixels) such as `event->mval[0] - other_x`. + * \param zfac: The depth result typically calculated by by #ED_view3d_calc_zfac + * (see it's doc-string for details). + * \param r_out: The resulting world-space delta. */ void ED_view3d_win_to_delta(const struct ARegion *region, - const float mval[2], - float out[3], - float zfac); + const float xy_delta[2], + float zfac, + float r_out[3]); /** * Calculate a 3d origin from 2d window coordinates. * \note Orthographic views have a less obvious origin, @@ -645,23 +662,23 @@ void ED_view3d_win_to_delta(const struct ARegion *region, * * \param region: The region (used for the window width and height). * \param mval: The area relative 2d location (such as event->mval converted to floats). - * \param out: The resulting normalized world-space direction vector. + * \param r_out: The resulting normalized world-space direction vector. */ -void ED_view3d_win_to_origin(const struct ARegion *region, const float mval[2], float out[3]); +void ED_view3d_win_to_origin(const struct ARegion *region, const float mval[2], float r_out[3]); /** * Calculate a 3d direction vector from 2d window coordinates. * This direction vector starts and the view in the direction of the 2d window coordinates. * In orthographic view all window coordinates yield the same vector. * - * \note doesn't rely on ED_view3d_calc_zfac + * \note doesn't rely on #ED_view3d_calc_zfac * for perspective view, get the vector direction to * the mouse cursor as a normalized vector. * * \param region: The region (used for the window width and height). * \param mval: The area relative 2d location (such as event->mval converted to floats). - * \param out: The resulting normalized world-space direction vector. + * \param r_out: The resulting normalized world-space direction vector. */ -void ED_view3d_win_to_vector(const struct ARegion *region, const float mval[2], float out[3]); +void ED_view3d_win_to_vector(const struct ARegion *region, const float mval[2], float r_out[3]); /** * Calculate a 3d segment from 2d window coordinates. * This ray_start is located at the viewpoint, ray_end is a far point. @@ -1078,6 +1095,20 @@ bool ED_view3d_persp_ensure(const struct Depsgraph *depsgraph, struct View3D *v3d, struct ARegion *region); +/* Camera view functions. */ + +/** + * Utility to scale zoom level when in camera-view #RegionView3D.camzoom and apply limits. + * \return true a change was made. + */ +bool ED_view3d_camera_view_zoom_scale(struct RegionView3D *rv3d, const float scale); +/** + * Utility to pan when in camera view. + * \param event_ofs: The offset the pan in screen (pixel) coordinates. + * \return true when a change was made. + */ +bool ED_view3d_camera_view_pan(struct ARegion *region, const float event_ofs[2]); + /* Camera lock functions */ /** diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 7bbc8249a97..060c9dc33d6 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -2902,7 +2902,7 @@ uiBut *UI_context_active_but_prop_get(const struct bContext *C, struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, int *r_index); -void UI_context_active_but_prop_handle(struct bContext *C); +void UI_context_active_but_prop_handle(struct bContext *C, bool handle_undo); void UI_context_active_but_clear(struct bContext *C, struct wmWindow *win, struct ARegion *region); struct wmOperator *UI_context_active_operator_get(const struct bContext *C); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 4819e8ed82c..3619a7ce317 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1418,7 +1418,7 @@ static bool ui_but_event_property_operator_string(const bContext *C, } /* This version is only for finding hotkeys for properties. - * These are set set via a data-path which is appended to the context, + * These are set via a data-path which is appended to the context, * manipulated using operators (see #ctx_toggle_opnames). */ if (ptr->owner_id) { @@ -3087,11 +3087,11 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) PointerRNA rptr; /* This is kind of hackish, in theory think we could only ever use the second member of - * this if/else, since ui_searchbox_apply() is supposed to always set that pointer when + * this if/else, since #ui_searchbox_apply() is supposed to always set that pointer when * we are storing pointers... But keeping str search first for now, * to try to break as little as possible existing code. All this is band-aids anyway. - * Fact remains, using editstr as main 'reference' over whole search button thingy - * is utterly weak and should be redesigned imho, but that's not a simple task. */ + * Fact remains, using `editstr` as main 'reference' over whole search button thingy + * is utterly weak and should be redesigned IMHO, but that's not a simple task. */ if (search_but && search_but->rnasearchprop && RNA_property_collection_lookup_string( &search_but->rnasearchpoin, search_but->rnasearchprop, str, &rptr)) { @@ -6529,7 +6529,7 @@ void UI_but_focus_on_enter_event(wmWindow *win, uiBut *but) event.type = EVT_BUT_OPEN; event.val = KM_PRESS; - event.is_repeat = false; + event.flag = 0; event.customdata = but; event.customdata_free = false; diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 34a20b91172..07efcdcbe38 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -201,7 +201,7 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *region, void *arg) /* XXX this guess_opname can potentially return a different keymap * than being found on adding later... */ wmKeyMap *km = WM_keymap_guess_opname(C, idname); - wmKeyMapItem *kmi = WM_keymap_add_item(km, idname, EVT_AKEY, KM_PRESS, 0, 0); + wmKeyMapItem *kmi = WM_keymap_add_item(km, idname, EVT_AKEY, KM_PRESS, 0, 0, KM_ANY); const int kmi_id = kmi->id; /* This takes ownership of prop, or prop can be NULL for reset. */ diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index e72381821e8..eaec1e249b7 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -147,8 +147,7 @@ void datadropper_win_area_find( *r_win = CTX_wm_window(C); *r_area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mval); if (*r_area == NULL) { - wmWindowManager *wm = CTX_wm_manager(C); - *r_win = WM_window_find_under_cursor(wm, NULL, *r_win, mval, r_mval); + *r_win = WM_window_find_under_cursor(*r_win, mval, r_mval); if (*r_win) { screen = WM_window_get_active_screen(*r_win); *r_area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, r_mval); diff --git a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c index d6f529f9f94..f3c70e6a96a 100644 --- a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c +++ b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c @@ -222,9 +222,9 @@ static void eyedropper_add_palette_color(bContext *C, const float col_conv[4]) static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, EyedropperGPencil *eye) { - const bool only_stroke = ((!event->ctrl) && (!event->shift)); - const bool only_fill = ((!event->ctrl) && (event->shift)); - const bool both = ((event->ctrl) && (event->shift)); + const bool only_stroke = (event->modifier & (KM_CTRL | KM_SHIFT)) == 0; + const bool only_fill = ((event->modifier & KM_CTRL) == 0 && (event->modifier & KM_SHIFT)); + const bool both = ((event->modifier & KM_CTRL) && (event->modifier & KM_SHIFT)); float col_conv[4]; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index bbb6bfabdd1..e0b64dcd4d6 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -275,7 +275,7 @@ static void ui_selectcontext_apply(bContext *C, const double value, const double value_orig); -# define IS_ALLSELECT_EVENT(event) ((event)->alt != 0) +# define IS_ALLSELECT_EVENT(event) (((event)->modifier & KM_ALT) != 0) /** just show a tinted color so users know its activated */ # define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE @@ -708,7 +708,8 @@ enum eSnapType { static enum eSnapType ui_event_to_snap(const wmEvent *event) { - return (event->ctrl) ? (event->shift) ? SNAP_ON_SMALL : SNAP_ON : SNAP_OFF; + return (event->modifier & KM_CTRL) ? (event->modifier & KM_SHIFT) ? SNAP_ON_SMALL : SNAP_ON : + SNAP_OFF; } static bool ui_event_is_snap(const wmEvent *event) @@ -1937,7 +1938,7 @@ static void ui_selectcontext_apply(bContext *C, /* could check for 'handle_layer_buttons' */ but->func) { wmWindow *win = CTX_wm_window(C); - if (!win->eventstate->shift) { + if ((win->eventstate->modifier & KM_SHIFT) == 0) { const int len = RNA_property_array_length(&but->rnapoin, prop); bool *tmparray = MEM_callocN(sizeof(bool) * len, __func__); @@ -3747,11 +3748,11 @@ static void ui_do_but_textedit( case EVT_XKEY: case EVT_CKEY: #if defined(__APPLE__) - if ((event->oskey && !IS_EVENT_MOD(event, shift, alt, ctrl)) || - (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey))) { + if (ELEM(event->modifier, KM_OSKEY, KM_CTRL)) #else - if (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey)) { + if (event->modifier == KM_CTRL) #endif + { if (event->type == EVT_VKEY) { changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_PASTE); } @@ -3769,16 +3770,16 @@ static void ui_do_but_textedit( ui_textedit_move(but, data, STRCUR_DIR_NEXT, - event->shift != 0, - event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); + event->modifier & KM_SHIFT, + (event->modifier & KM_CTRL) ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); retval = WM_UI_HANDLER_BREAK; break; case EVT_LEFTARROWKEY: ui_textedit_move(but, data, STRCUR_DIR_PREV, - event->shift != 0, - event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); + event->modifier & KM_SHIFT, + (event->modifier & KM_CTRL) ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); retval = WM_UI_HANDLER_BREAK; break; case WHEELDOWNMOUSE: @@ -3795,7 +3796,7 @@ static void ui_do_but_textedit( } ATTR_FALLTHROUGH; case EVT_ENDKEY: - ui_textedit_move(but, data, STRCUR_DIR_NEXT, event->shift != 0, STRCUR_JUMP_ALL); + ui_textedit_move(but, data, STRCUR_DIR_NEXT, event->modifier & KM_SHIFT, STRCUR_JUMP_ALL); retval = WM_UI_HANDLER_BREAK; break; case WHEELUPMOUSE: @@ -3812,7 +3813,7 @@ static void ui_do_but_textedit( } ATTR_FALLTHROUGH; case EVT_HOMEKEY: - ui_textedit_move(but, data, STRCUR_DIR_PREV, event->shift != 0, STRCUR_JUMP_ALL); + ui_textedit_move(but, data, STRCUR_DIR_PREV, event->modifier & KM_SHIFT, STRCUR_JUMP_ALL); retval = WM_UI_HANDLER_BREAK; break; case EVT_PADENTER: @@ -3822,13 +3823,13 @@ static void ui_do_but_textedit( break; case EVT_DELKEY: changed = ui_textedit_delete( - but, data, 1, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); + but, data, 1, (event->modifier & KM_CTRL) ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); retval = WM_UI_HANDLER_BREAK; break; case EVT_BACKSPACEKEY: changed = ui_textedit_delete( - but, data, 0, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); + but, data, 0, (event->modifier & KM_CTRL) ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); retval = WM_UI_HANDLER_BREAK; break; @@ -3837,10 +3838,9 @@ static void ui_do_but_textedit( /* Ctrl-A: Select all. */ #if defined(__APPLE__) /* OSX uses Command-A system-wide, so add it. */ - if ((event->oskey && !IS_EVENT_MOD(event, shift, alt, ctrl)) || - (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey))) + if (ELEM(event->modifier, KM_OSKEY, KM_CTRL)) #else - if (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey)) + if (event->modifier == KM_CTRL) #endif { ui_textedit_move(but, data, STRCUR_DIR_PREV, false, STRCUR_JUMP_ALL); @@ -3859,9 +3859,9 @@ static void ui_do_but_textedit( button_activate_state(C, but, BUTTON_STATE_EXIT); } } - else if (!IS_EVENT_MOD(event, ctrl, alt, oskey)) { + else if ((event->modifier & (KM_CTRL | KM_ALT | KM_OSKEY)) == 0) { /* Use standard keys for cycling through buttons Tab, Shift-Tab to reverse. */ - if (event->shift) { + if (event->modifier & KM_SHIFT) { ui_textedit_prev_but(block, but, data); } else { @@ -3874,12 +3874,12 @@ static void ui_do_but_textedit( case EVT_ZKEY: { /* Ctrl-Z or Ctrl-Shift-Z: Undo/Redo (allowing for OS-Key on Apple). */ - const bool is_redo = (event->shift != 0); + const bool is_redo = (event->modifier & KM_SHIFT); if ( #if defined(__APPLE__) - (event->oskey && !IS_EVENT_MOD(event, alt, ctrl)) || + ((event->modifier & KM_OSKEY) && ((event->modifier & (KM_ALT | KM_CTRL)) == 0)) || #endif - (event->ctrl && !IS_EVENT_MOD(event, alt, oskey))) { + ((event->modifier & KM_CTRL) && ((event->modifier & (KM_ALT | KM_OSKEY)) == 0))) { int undo_pos; const char *undo_str = ui_textedit_undo( data->undo_stack_text, is_redo ? 1 : -1, &undo_pos); @@ -4542,19 +4542,7 @@ static int ui_do_but_HOTKEYEVT(bContext *C, } /* always set */ - but->modifier_key = 0; - if (event->shift) { - but->modifier_key |= KM_SHIFT; - } - if (event->alt) { - but->modifier_key |= KM_ALT; - } - if (event->ctrl) { - but->modifier_key |= KM_CTRL; - } - if (event->oskey) { - but->modifier_key |= KM_OSKEY; - } + but->modifier_key = event->modifier; ui_but_update(but); ED_region_tag_redraw(data->region); @@ -4633,7 +4621,8 @@ static int ui_do_but_TAB( const int rna_type = but->rnaprop ? RNA_property_type(but->rnaprop) : 0; if (is_property && ELEM(rna_type, PROP_POINTER, PROP_STRING) && (but->custom_data != NULL) && - (event->type == LEFTMOUSE) && ((event->val == KM_DBL_CLICK) || event->ctrl)) { + (event->type == LEFTMOUSE) && + ((event->val == KM_DBL_CLICK) || (event->modifier & KM_CTRL))) { button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); return WM_UI_HANDLER_BREAK; } @@ -4666,7 +4655,8 @@ static int ui_do_but_TEX( if (ELEM(event->type, EVT_PADENTER, EVT_RETKEY) && (!UI_but_is_utf8(but))) { /* pass - allow filesel, enter to execute */ } - else if (ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS) && !event->ctrl) { + else if (ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS) && + ((event->modifier & KM_CTRL) == 0)) { /* pass */ } else { @@ -4735,7 +4725,7 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } - if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { + if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && (event->modifier & KM_CTRL)) { /* Support Ctrl-Wheel to cycle values on expanded enum rows. */ if (but->type == UI_BTYPE_ROW) { int type = event->type; @@ -5325,24 +5315,24 @@ static int ui_do_but_NUM( } /* XXX hardcoded keymap check.... */ - if (type == MOUSEPAN && event->ctrl) { + if (type == MOUSEPAN && (event->modifier & KM_CTRL)) { /* allow accumulating values, otherwise scrolling gets preference */ retval = WM_UI_HANDLER_BREAK; } - else if (type == WHEELDOWNMOUSE && event->ctrl) { + else if (type == WHEELDOWNMOUSE && (event->modifier & KM_CTRL)) { mx = but->rect.xmin; but->drawflag &= ~UI_BUT_ACTIVE_RIGHT; but->drawflag |= UI_BUT_ACTIVE_LEFT; click = 1; } - else if (type == WHEELUPMOUSE && event->ctrl) { + else if ((type == WHEELUPMOUSE) && (event->modifier & KM_CTRL)) { mx = but->rect.xmax; but->drawflag &= ~UI_BUT_ACTIVE_LEFT; but->drawflag |= UI_BUT_ACTIVE_RIGHT; click = 1; } else if (event->val == KM_PRESS) { - if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->ctrl) { + if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && (event->modifier & KM_CTRL)) { button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); retval = WM_UI_HANDLER_BREAK; } @@ -5402,7 +5392,7 @@ static int ui_do_but_NUM( #endif fac = 1.0f; - if (event->shift) { + if (event->modifier & KM_SHIFT) { fac /= 10.0f; } @@ -5668,27 +5658,27 @@ static int ui_do_but_SLI( } /* XXX hardcoded keymap check.... */ - if (type == MOUSEPAN && event->ctrl) { + if ((type == MOUSEPAN) && (event->modifier & KM_CTRL)) { /* allow accumulating values, otherwise scrolling gets preference */ retval = WM_UI_HANDLER_BREAK; } - else if (type == WHEELDOWNMOUSE && event->ctrl) { + else if ((type == WHEELDOWNMOUSE) && (event->modifier & KM_CTRL)) { mx = but->rect.xmin; click = 2; } - else if (type == WHEELUPMOUSE && event->ctrl) { + else if ((type == WHEELUPMOUSE) && (event->modifier & KM_CTRL)) { mx = but->rect.xmax; click = 2; } else if (event->val == KM_PRESS) { - if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->ctrl) { + if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && (event->modifier & KM_CTRL)) { button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); retval = WM_UI_HANDLER_BREAK; } #ifndef USE_ALLSELECT /* alt-click on sides to get "arrows" like in UI_BTYPE_NUM buttons, * and match wheel usage above */ - else if (event->type == LEFTMOUSE && event->alt) { + else if ((event->type == LEFTMOUSE) && (event->modifier & KM_ALT)) { int halfpos = BLI_rctf_cent_x(&but->rect); click = 2; if (mx < halfpos) { @@ -5754,8 +5744,13 @@ static int ui_do_but_SLI( data->multi_data.drag_dir[0] += abs(data->draglastx - mx); data->multi_data.drag_dir[1] += abs(data->draglasty - my); #endif - if (ui_numedit_but_SLI( - but, data, mx, true, is_motion, event->ctrl != 0, event->shift != 0)) { + if (ui_numedit_but_SLI(but, + data, + mx, + true, + is_motion, + event->modifier & KM_CTRL, + event->modifier & KM_SHIFT)) { ui_numedit_apply(C, block, but, data); } @@ -5981,8 +5976,8 @@ static int ui_do_but_LISTROW(bContext *C, /* hack to pass on ctrl+click and double click to overlapping text * editing field for editing list item names */ - if ((ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS && - event->ctrl) || + if ((ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && (event->val == KM_PRESS) && + (event->modifier & KM_CTRL)) || (event->type == LEFTMOUSE && event->val == KM_DBL_CLICK)) { uiBut *labelbut = ui_but_list_row_text_activate( C, but, data, event, BUTTON_ACTIVATE_TEXT_EDITING); @@ -6023,7 +6018,8 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co return WM_UI_HANDLER_BREAK; } if (ui_but_supports_cycling(but)) { - if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { + if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && + (event->modifier & KM_CTRL)) { int type = event->type; int val = event->val; @@ -6210,7 +6206,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co button_activate_state(C, but, BUTTON_STATE_MENU_OPEN); return WM_UI_HANDLER_BREAK; } - if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { + if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && (event->modifier & KM_CTRL)) { ColorPicker *cpicker = but->custom_data; float hsv_static[3] = {0.0f}; float *hsv = cpicker ? cpicker->hsv_perceptual : hsv_static; @@ -6269,7 +6265,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { if (color_but->is_pallete_color) { - if (!event->ctrl) { + if ((event->modifier & KM_CTRL) == 0) { float color[3]; Paint *paint = BKE_paint_get_active_from_context(C); Brush *brush = BKE_paint_brush(paint); @@ -6639,7 +6635,7 @@ static int ui_do_but_HSVCUBE( button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); /* also do drag the first time */ - if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->shift != 0)) { + if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->modifier & KM_SHIFT)) { ui_numedit_apply(C, block, but, data); } @@ -6650,7 +6646,7 @@ static int ui_do_but_HSVCUBE( const wmNDOFMotionData *ndof = event->customdata; const enum eSnapType snap = ui_event_to_snap(event); - ui_ndofedit_but_HSVCUBE(hsv_but, data, ndof, snap, event->shift != 0); + ui_ndofedit_but_HSVCUBE(hsv_but, data, ndof, snap, event->modifier & KM_SHIFT); button_activate_state(C, but, BUTTON_STATE_EXIT); ui_apply_but(C, but->block, but, data, true); @@ -6702,7 +6698,7 @@ static int ui_do_but_HSVCUBE( if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) { const enum eSnapType snap = ui_event_to_snap(event); - if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->shift != 0)) { + if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->modifier & KM_SHIFT)) { ui_numedit_apply(C, block, but, data); } } @@ -6914,7 +6910,7 @@ static int ui_do_but_HSVCIRCLE( button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); /* also do drag the first time */ - if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->shift != 0)) { + if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->modifier & KM_SHIFT)) { ui_numedit_apply(C, block, but, data); } @@ -6925,7 +6921,7 @@ static int ui_do_but_HSVCIRCLE( const enum eSnapType snap = ui_event_to_snap(event); const wmNDOFMotionData *ndof = event->customdata; - ui_ndofedit_but_HSVCIRCLE(but, data, ndof, snap, event->shift != 0); + ui_ndofedit_but_HSVCIRCLE(but, data, ndof, snap, event->modifier & KM_SHIFT); button_activate_state(C, but, BUTTON_STATE_EXIT); ui_apply_but(C, but->block, but, data, true); @@ -6987,7 +6983,7 @@ static int ui_do_but_HSVCIRCLE( if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) { const enum eSnapType snap = ui_event_to_snap(event); - if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->shift != 0)) { + if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->modifier & KM_SHIFT)) { ui_numedit_apply(C, block, but, data); } } @@ -7037,7 +7033,7 @@ static int ui_do_but_COLORBAND( if (event->type == LEFTMOUSE && event->val == KM_PRESS) { ColorBand *coba = (ColorBand *)but->poin; - if (event->ctrl) { + if (event->modifier & KM_CTRL) { /* insert new key on mouse location */ const float pos = ((float)(mx - but->rect.xmin)) / BLI_rctf_size_x(&but->rect); BKE_colorband_element_add(coba, pos); @@ -7237,7 +7233,7 @@ static int ui_do_but_CURVE( float dist_min_sq = square_f(U.dpi_fac * 14.0f); /* 14 pixels radius */ int sel = -1; - if (event->ctrl) { + if (event->modifier & KM_CTRL) { float f_xy[2]; BLI_rctf_transform_pt_v(&cumap->curr, &but->rect, f_xy, m_xy); @@ -7301,7 +7297,7 @@ static int ui_do_but_CURVE( if (sel != -1) { /* ok, we move a point */ /* deselect all if this one is deselect. except if we hold shift */ - if (!event->shift) { + if ((event->modifier & KM_SHIFT) == 0) { for (int a = 0; a < cuma->totpoint; a++) { cmp[a].flag &= ~CUMA_SELECT; } @@ -7336,8 +7332,8 @@ static int ui_do_but_CURVE( data, event->xy[0], event->xy[1], - event->ctrl != 0, - event->shift != 0)) { + event->modifier & KM_CTRL, + event->modifier & KM_SHIFT)) { ui_numedit_apply(C, block, but, data); } } @@ -7350,7 +7346,7 @@ static int ui_do_but_CURVE( if (data->dragchange == false) { /* deselect all, select one */ - if (!event->shift) { + if ((event->modifier & KM_SHIFT) == 0) { for (int a = 0; a < cuma->totpoint; a++) { cmp[a].flag &= ~CUMA_SELECT; } @@ -7539,7 +7535,7 @@ static int ui_do_but_CURVEPROFILE( if (event->type == LEFTMOUSE && event->val == KM_PRESS) { const float m_xy[2] = {mx, my}; - if (event->ctrl) { + if (event->modifier & KM_CTRL) { float f_xy[2]; BLI_rctf_transform_pt_v(&profile->view_rect, &but->rect, f_xy, m_xy); @@ -7616,7 +7612,7 @@ static int ui_do_but_CURVEPROFILE( /* Change the flag for the point(s) if one was selected or added. */ if (i_selected != -1) { /* Deselect all if this one is deselected, except if we hold shift. */ - if (event->shift) { + if (event->modifier & KM_SHIFT) { pts[i_selected].flag ^= selection_type; } else { @@ -7647,7 +7643,7 @@ static int ui_do_but_CURVEPROFILE( if (event->type == MOUSEMOVE) { if (mx != data->draglastx || my != data->draglasty) { if (ui_numedit_but_CURVEPROFILE( - block, but, data, mx, my, event->ctrl != 0, event->shift != 0)) { + block, but, data, mx, my, event->modifier & KM_CTRL, event->modifier & KM_SHIFT)) { ui_numedit_apply(C, block, but, data); } } @@ -7871,7 +7867,7 @@ static int ui_do_but_TRACKPREVIEW( button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); /* also do drag the first time */ - if (ui_numedit_but_TRACKPREVIEW(C, but, data, mx, my, event->shift != 0)) { + if (ui_numedit_but_TRACKPREVIEW(C, but, data, mx, my, event->modifier & KM_SHIFT)) { ui_numedit_apply(C, block, but, data); } @@ -7888,7 +7884,7 @@ static int ui_do_but_TRACKPREVIEW( } else if (event->type == MOUSEMOVE) { if (mx != data->draglastx || my != data->draglasty) { - if (ui_numedit_but_TRACKPREVIEW(C, but, data, mx, my, event->shift != 0)) { + if (ui_numedit_but_TRACKPREVIEW(C, but, data, mx, my, event->modifier & KM_SHIFT)) { ui_numedit_apply(C, block, but, data); } } @@ -7918,8 +7914,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * if (data->state == BUTTON_STATE_HIGHLIGHT) { /* handle copy and paste */ - bool is_press_ctrl_but_no_shift = event->val == KM_PRESS && IS_EVENT_MOD(event, ctrl, oskey) && - !event->shift; + bool is_press_ctrl_but_no_shift = (event->val == KM_PRESS) && + (event->modifier & (KM_CTRL | KM_OSKEY)) && + (event->modifier & KM_SHIFT) == 0; const bool do_copy = event->type == EVT_CKEY && is_press_ctrl_but_no_shift; const bool do_paste = event->type == EVT_VKEY && is_press_ctrl_but_no_shift; @@ -7934,12 +7931,14 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * /* do copy first, because it is the only allowed operator when disabled */ if (do_copy) { - ui_but_copy(C, but, event->alt); + ui_but_copy(C, but, event->modifier & KM_ALT); return WM_UI_HANDLER_BREAK; } /* handle menu */ - if ((event->type == RIGHTMOUSE) && !IS_EVENT_MOD(event, shift, ctrl, alt, oskey) && + + if ((event->type == RIGHTMOUSE) && + (event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) == 0 && (event->val == KM_PRESS)) { /* For some button types that are typically representing entire sets of data, right-clicking * to spawn the context menu should also activate the item. This makes it clear which item @@ -7960,7 +7959,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * } if (do_paste) { - ui_but_paste(C, but, data, event->alt); + ui_but_paste(C, but, data, event->modifier & KM_ALT); return WM_UI_HANDLER_BREAK; } @@ -8793,7 +8792,7 @@ uiBut *UI_context_active_but_prop_get(const bContext *C, return activebut; } -void UI_context_active_but_prop_handle(bContext *C) +void UI_context_active_but_prop_handle(bContext *C, const bool handle_undo) { uiBut *activebut = ui_context_rna_button_active(C); if (activebut) { @@ -8804,6 +8803,11 @@ void UI_context_active_but_prop_handle(bContext *C) if (block->handle_func) { block->handle_func(C, block->handle_func_arg, activebut->retval); } + if (handle_undo) { + /* Update the button so the undo text uses the correct value. */ + ui_but_update(activebut); + ui_apply_but_undo(activebut); + } } } @@ -8942,7 +8946,7 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *reg if (but) { button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER); - if (event->alt && but->active) { + if ((event->modifier & KM_ALT) && but->active) { /* Display tool-tips if holding Alt on mouse-over when tool-tips are disabled in the * preferences. */ but->active->tooltip_force = true; @@ -8970,7 +8974,7 @@ void ui_but_activate_event(bContext *C, ARegion *region, uiBut *but) wm_event_init_from_window(win, &event); event.type = EVT_BUT_OPEN; event.val = KM_PRESS; - event.is_repeat = false; + event.flag = 0; event.customdata = but; event.customdata_free = false; @@ -9394,7 +9398,7 @@ static int ui_list_activate_hovered_row(bContext *C, } } - const int *mouse_xy = ISTWEAK(event->type) ? event->prev_click_xy : event->xy; + const int *mouse_xy = (event->val == KM_CLICK_DRAG) ? event->prev_click_xy : event->xy; uiBut *listrow = ui_list_row_find_mouse_over(region, mouse_xy); if (listrow) { wmOperatorType *custom_activate_optype = ui_list->dyn_data->custom_activate_optype; @@ -9421,7 +9425,7 @@ static bool ui_list_is_hovering_draggable_but(bContext *C, const wmEvent *event) { /* On a tweak event, uses the coordinates from where tweaking was started. */ - const int *mouse_xy = ISTWEAK(event->type) ? event->prev_click_xy : event->xy; + const int *mouse_xy = (event->val == KM_CLICK_DRAG) ? event->prev_click_xy : event->xy; const uiBut *hovered_but = ui_but_find_mouse_over_ex(region, mouse_xy, false, NULL, NULL); if (list->dyn_data->custom_drag_optype) { @@ -9438,7 +9442,7 @@ static int ui_list_handle_click_drag(bContext *C, ARegion *region, const wmEvent *event) { - if (!ELEM(event->type, LEFTMOUSE, EVT_TWEAK_L)) { + if (event->type != LEFTMOUSE) { return WM_HANDLER_CONTINUE; } @@ -9448,7 +9452,7 @@ static int ui_list_handle_click_drag(bContext *C, bool activate = false; bool activate_dragging = false; - if (event->type == EVT_TWEAK_L) { + if (event->val == KM_CLICK_DRAG) { if (is_draggable) { activate_dragging = true; activate = true; @@ -9458,7 +9462,7 @@ static int ui_list_handle_click_drag(bContext *C, * regular events (including mouse presses to start dragging) and this part only kicks in if it * hasn't handled the release event. Note that if there's no overlaid button, the row selects * on the press event already via regular #UI_BTYPE_LISTROW handling. */ - else if ((event->type == LEFTMOUSE) && (event->val == KM_CLICK)) { + else if (event->val == KM_CLICK) { activate = true; } @@ -9534,7 +9538,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *regi ui_pan_to_scroll(event, &type, &val); /* 'ui_pan_to_scroll' gives the absolute direction. */ - if (event->is_direction_inverted) { + if (event->flag & WM_EVENT_SCROLL_INVERT) { scroll_dir = -1; } @@ -9545,14 +9549,14 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *regi } } - if (ELEM(event->type, LEFTMOUSE, EVT_TWEAK_L)) { + if (event->type == LEFTMOUSE) { retval = ui_list_handle_click_drag(C, ui_list, region, event); } else if (val == KM_PRESS) { if ((ELEM(type, EVT_UPARROWKEY, EVT_DOWNARROWKEY, EVT_LEFTARROWKEY, EVT_RIGHTARROWKEY) && - !IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) || - ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->ctrl && - !IS_EVENT_MOD(event, shift, alt, oskey)))) { + (event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) == 0) || + ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && (event->modifier & KM_CTRL) && + (event->modifier & (KM_SHIFT | KM_ALT | KM_OSKEY)) == 0))) { const int value_orig = RNA_property_int_get(&listbox->rnapoin, listbox->rnaprop); int value, min, max; @@ -9609,7 +9613,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *regi } retval = WM_UI_HANDLER_BREAK; } - else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) { + else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && (event->modifier & KM_SHIFT)) { /* We now have proper grip, but keep this anyway! */ if (ui_list->list_grip < (dyn_data->visual_height_min - UI_LIST_AUTO_SIZE_THRESHOLD)) { ui_list->list_grip = dyn_data->visual_height; @@ -10263,7 +10267,7 @@ static int ui_handle_menu_event(bContext *C, /* Smooth scrolling for popovers. */ case MOUSEPAN: { - if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) { + if (event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) { /* pass */ } else if (!ui_block_is_menu(block)) { @@ -10285,7 +10289,7 @@ static int ui_handle_menu_event(bContext *C, } case WHEELUPMOUSE: case WHEELDOWNMOUSE: { - if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) { + if (event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) { /* pass */ } else if (!ui_block_is_menu(block)) { @@ -10308,7 +10312,7 @@ static int ui_handle_menu_event(bContext *C, case EVT_HOMEKEY: case EVT_ENDKEY: /* Arrow-keys: only handle for block_loop blocks. */ - if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) { + if (event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) { /* pass */ } else if (inside || (block->flag & UI_BLOCK_LOOP)) { @@ -10455,11 +10459,11 @@ static int ui_handle_menu_event(bContext *C, /* Only respond to explicit press to avoid the event that opened the menu * activating an item when the key is held. */ - if (event->is_repeat) { + if (event->flag & WM_EVENT_IS_REPEAT) { break; } - if (event->alt) { + if (event->modifier & KM_ALT) { act += 10; } @@ -10539,10 +10543,10 @@ static int ui_handle_menu_event(bContext *C, case EVT_YKEY: case EVT_ZKEY: { if (ELEM(event->val, KM_PRESS, KM_DBL_CLICK) && - !IS_EVENT_MOD(event, shift, ctrl, oskey) && + ((event->modifier & (KM_SHIFT | KM_CTRL | KM_OSKEY)) == 0) && /* Only respond to explicit press to avoid the event that opened the menu * activating an item when the key is held. */ - !event->is_repeat) { + (event->flag & WM_EVENT_IS_REPEAT) == 0) { if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval)) { break; } @@ -11066,7 +11070,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle case EVT_YKEY: case EVT_ZKEY: { if ((ELEM(event->val, KM_PRESS, KM_DBL_CLICK)) && - !IS_EVENT_MOD(event, shift, ctrl, oskey)) { + ((event->modifier & (KM_SHIFT | KM_CTRL | KM_OSKEY)) == 0)) { LISTBASE_FOREACH (uiBut *, but, &block->buttons) { if (but->menu_key == event->type) { ui_but_pie_button_activate(C, but, menu); diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index e277aa2e629..9dfc9be2a30 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -573,18 +573,6 @@ int UI_icon_from_event_type(short event_type, short event_value) else if (event_type == EVT_RIGHTALTKEY) { event_type = EVT_LEFTALTKEY; } - else if (event_type == EVT_TWEAK_L) { - event_type = LEFTMOUSE; - event_value = KM_CLICK_DRAG; - } - else if (event_type == EVT_TWEAK_M) { - event_type = MIDDLEMOUSE; - event_value = KM_CLICK_DRAG; - } - else if (event_type == EVT_TWEAK_R) { - event_type = RIGHTMOUSE; - event_value = KM_CLICK_DRAG; - } DrawInfo *di = g_di_event_list; do { @@ -1399,19 +1387,17 @@ static void icon_set_image(const bContext *C, const bool delay = prv_img->rect[size] != NULL; icon_create_rect(prv_img, size); - prv_img->flag[size] |= PRV_RENDERING; if (use_job && (!id || BKE_previewimg_id_supports_jobs(id))) { /* Job (background) version */ - ED_preview_icon_job( - C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size], delay); + ED_preview_icon_job(C, prv_img, id, size, delay); } else { if (!scene) { scene = CTX_data_scene(C); } /* Immediate version */ - ED_preview_icon_render(C, scene, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]); + ED_preview_icon_render(C, scene, prv_img, id, size); } } @@ -2271,7 +2257,7 @@ int UI_icon_from_idcode(const int idcode) return ICON_CAMERA_DATA; case ID_CF: return ICON_FILE; - case ID_CU: + case ID_CU_LEGACY: return ICON_CURVE_DATA; case ID_GD: return ICON_OUTLINER_DATA_GREASEPENCIL; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 54a5b496048..bd55d2d9d81 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -492,7 +492,7 @@ static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index) PointerRNA *ptr = &but->rnapoin; PropertyRNA *prop = but->rnaprop; const int index = POINTER_AS_INT(arg_index); - const int shift = win->eventstate->shift; + const bool shift = win->eventstate->modifier & KM_SHIFT; const int len = RNA_property_array_length(ptr, prop); if (!shift) { @@ -752,7 +752,7 @@ static void ui_item_enum_expand_handle(bContext *C, void *arg1, void *arg2) { wmWindow *win = CTX_wm_window(C); - if (!win->eventstate->shift) { + if ((win->eventstate->modifier & KM_SHIFT) == 0) { uiBut *but = (uiBut *)arg1; const int enum_value = POINTER_AS_INT(arg2); diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index a96f14d7435..498c22748ce 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -314,7 +314,7 @@ static int operator_button_property_finish(bContext *C, PointerRNA *ptr, Propert RNA_property_update(C, ptr, prop); /* as if we pressed the button */ - UI_context_active_but_prop_handle(C); + UI_context_active_but_prop_handle(C, false); /* Since we don't want to undo _all_ edits to settings, eg window * edits on the screen or on operator settings. @@ -326,6 +326,19 @@ static int operator_button_property_finish(bContext *C, PointerRNA *ptr, Propert return OPERATOR_CANCELLED; } +static int operator_button_property_finish_with_undo(bContext *C, + PointerRNA *ptr, + PropertyRNA *prop) +{ + /* Perform updates required for this property. */ + RNA_property_update(C, ptr, prop); + + /* As if we pressed the button. */ + UI_context_active_but_prop_handle(C, true); + + return OPERATOR_FINISHED; +} + static bool reset_default_button_poll(bContext *C) { PointerRNA ptr; @@ -350,7 +363,7 @@ static int reset_default_button_exec(bContext *C, wmOperator *op) /* if there is a valid property that is editable... */ if (ptr.data && prop && RNA_property_editable(&ptr, prop)) { if (RNA_property_reset(&ptr, prop, (all) ? -1 : index)) { - return operator_button_property_finish(C, &ptr, prop); + return operator_button_property_finish_with_undo(C, &ptr, prop); } } @@ -369,7 +382,9 @@ static void UI_OT_reset_default_button(wmOperatorType *ot) ot->exec = reset_default_button_exec; /* flags */ - ot->flag = OPTYPE_UNDO; + /* Don't set #OPTYPE_UNDO because #operator_button_property_finish_with_undo + * is responsible for the undo push. */ + ot->flag = 0; /* properties */ RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array"); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 2cb0f256b71..c7f2eb230cb 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -2061,8 +2061,8 @@ static void ui_handle_panel_header(const bContext *C, const uiBlock *block, const int mx, const int event_type, - const short ctrl, - const short shift) + const bool ctrl, + const bool shift) { Panel *panel = block->panel; ARegion *region = CTX_wm_region(C); @@ -2274,7 +2274,7 @@ static int ui_handle_panel_category_cycling(const wmEvent *event, (event->mval[0] > ((PanelCategoryDyn *)region->panels_category.first)->rect.xmin)); /* If mouse is inside non-tab region, ctrl key is required. */ - if (is_mousewheel && !event->ctrl && !inside_tabregion) { + if (is_mousewheel && (event->modifier & KM_CTRL) == 0 && !inside_tabregion) { return WM_UI_HANDLER_CONTINUE; } @@ -2291,7 +2291,7 @@ static int ui_handle_panel_category_cycling(const wmEvent *event, pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev; } else { - const bool backwards = event->shift; + const bool backwards = event->modifier & KM_SHIFT; pc_dyn = backwards ? pc_dyn->prev : pc_dyn->next; if (!pc_dyn) { /* Proper cyclic behavior, back to first/last category (only used for ctrl+tab). */ @@ -2349,7 +2349,7 @@ int ui_handler_panel_region(bContext *C, retval = WM_UI_HANDLER_BREAK; } } - else if ((event->type == EVT_TABKEY && event->ctrl) || + else if (((event->type == EVT_TABKEY) && (event->modifier & KM_CTRL)) || ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) { /* Cycle tabs. */ retval = ui_handle_panel_category_cycling(event, region, active_but); @@ -2386,9 +2386,11 @@ int ui_handler_panel_region(bContext *C, /* The panel collapse / expand key "A" is special as it takes priority over * active button handling. */ - if (event->type == EVT_AKEY && !IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) { + if (event->type == EVT_AKEY && + ((event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) == 0)) { retval = WM_UI_HANDLER_BREAK; - ui_handle_panel_header(C, block, mx, event->type, event->ctrl, event->shift); + ui_handle_panel_header( + C, block, mx, event->type, event->modifier & KM_CTRL, event->modifier & KM_SHIFT); break; } } @@ -2402,7 +2404,8 @@ int ui_handler_panel_region(bContext *C, /* All mouse clicks inside panel headers should return in break. */ if (ELEM(event->type, EVT_RETKEY, EVT_PADENTER, LEFTMOUSE)) { retval = WM_UI_HANDLER_BREAK; - ui_handle_panel_header(C, block, mx, event->type, event->ctrl, event->shift); + ui_handle_panel_header( + C, block, mx, event->type, event->modifier & KM_CTRL, event->modifier & KM_SHIFT); } else if (event->type == RIGHTMOUSE) { retval = WM_UI_HANDLER_BREAK; diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c index 8a945c8c913..4703367671d 100644 --- a/source/blender/editors/interface/interface_query.c +++ b/source/blender/editors/interface/interface_query.c @@ -310,7 +310,7 @@ uiBut *ui_but_find_mouse_over_ex(const ARegion *region, uiBut *ui_but_find_mouse_over(const ARegion *region, const wmEvent *event) { - return ui_but_find_mouse_over_ex(region, event->xy, event->ctrl != 0, NULL, NULL); + return ui_but_find_mouse_over_ex(region, event->xy, event->modifier & KM_CTRL, NULL, NULL); } uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px) diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index 09faf493ce7..29553ff65d1 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -701,7 +701,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is /* Keymap */ /* This is too handy not to expose somehow, let's be sneaky for now. */ - if ((is_label == false) && CTX_wm_window(C)->eventstate->shift) { + if ((is_label == false) && CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) { const char *expr_imports[] = {"bpy", "bl_ui", NULL}; char expr[256]; SNPRINTF(expr, diff --git a/source/blender/editors/interface/interface_template_list.cc b/source/blender/editors/interface/interface_template_list.cc index 40675da71a9..6139ac8e702 100644 --- a/source/blender/editors/interface/interface_template_list.cc +++ b/source/blender/editors/interface/interface_template_list.cc @@ -598,7 +598,7 @@ static char *uilist_item_tooltip_func(bContext *UNUSED(C), void *argN, const cha } /** - * \note Note that \a layout_type may be null. + * \note that \a layout_type may be null. */ static uiList *ui_list_ensure(bContext *C, uiListType *ui_list_type, diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 2b7ca1f8b71..32b3bb5e926 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -609,7 +609,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); - if (id && CTX_wm_window(C)->eventstate->shift) { + if (id && CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) { /* only way to force-remove data (on save) */ id_us_clear_real(id); id_fake_user_clear(id); @@ -635,7 +635,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) case UI_ID_LOCAL: if (id) { Main *bmain = CTX_data_main(C); - if (CTX_wm_window(C)->eventstate->shift) { + if (CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) { if (ID_IS_OVERRIDABLE_LIBRARY(id)) { /* Only remap that specific ID usage to overriding local data-block. */ ID *override_id = BKE_lib_override_library_create_from_id(bmain, id, false); @@ -731,7 +731,7 @@ static const char *template_id_browse_tip(const StructRNA *type) return N_("Browse Object to be linked"); case ID_ME: return N_("Browse Mesh Data to be linked"); - case ID_CU: + case ID_CU_LEGACY: return N_("Browse Curve Data to be linked"); case ID_MB: return N_("Browse Metaball Data to be linked"); @@ -844,7 +844,7 @@ static uiBut *template_id_def_new_but(uiBlock *block, BLT_I18NCONTEXT_ID_SCENE, BLT_I18NCONTEXT_ID_OBJECT, BLT_I18NCONTEXT_ID_MESH, - BLT_I18NCONTEXT_ID_CURVE, + BLT_I18NCONTEXT_ID_CURVE_LEGACY, BLT_I18NCONTEXT_ID_METABALL, BLT_I18NCONTEXT_ID_MATERIAL, BLT_I18NCONTEXT_ID_TEXTURE, @@ -5539,7 +5539,7 @@ static void handle_layer_buttons(bContext *C, void *arg1, void *arg2) uiBut *but = arg1; const int cur = POINTER_AS_INT(arg2); wmWindow *win = CTX_wm_window(C); - const int shift = win->eventstate->shift; + const bool shift = win->eventstate->modifier & KM_SHIFT; if (!shift) { const int tot = RNA_property_array_length(&but->rnapoin, but->rnaprop); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index fbbf3c6fdf1..d1f3843c643 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2579,7 +2579,7 @@ static void widget_state(uiWidgetType *wt, int state, int drawflag, eUIEmbossTyp * * A lot of places of the UI like the Node Editor or panels are zoomable. In most cases we can * get the zoom factor from the aspect, but in some cases like popups we need to fall back to - * using the the size of the element. The latter method relies on the element always being the same + * using the size of the element. The latter method relies on the element always being the same * size. * \{ */ @@ -4293,7 +4293,7 @@ static void widget_tab( const bool is_active = (state & UI_SELECT); /* Draw shaded outline - Disabled for now, - * seems incorrect and also looks nicer without it imho ;) */ + * seems incorrect and also looks nicer without it IMHO ;). */ // #define USE_TAB_SHADED_HIGHLIGHT uchar theme_col_tab_highlight[3]; diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 09d57d3ea99..28a025ee581 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1449,7 +1449,7 @@ static int view2d_ndof_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* tune these until it feels right */ const float zoom_sensitivity = 0.5f; const float speed = 10.0f; /* match view3d ortho */ - const bool has_translate = (ndof->tvec[0] && ndof->tvec[1]) && view_pan_poll(C); + const bool has_translate = !is_zero_v2(ndof->tvec) && view_pan_poll(C); const bool has_zoom = (ndof->tvec[2] != 0.0f) && view_zoom_poll(C); if (has_translate) { diff --git a/source/blender/editors/io/io_obj.c b/source/blender/editors/io/io_obj.c index 28e14a14f5f..1c821eebdee 100644 --- a/source/blender/editors/io/io_obj.c +++ b/source/blender/editors/io/io_obj.c @@ -38,12 +38,12 @@ static const EnumPropertyItem io_obj_transform_axis_forward[] = { {OBJ_AXIS_Z_FORWARD, "Z_FORWARD", 0, "Z", "Positive Z axis"}, {OBJ_AXIS_NEGATIVE_X_FORWARD, "NEGATIVE_X_FORWARD", 0, "-X", "Negative X axis"}, {OBJ_AXIS_NEGATIVE_Y_FORWARD, "NEGATIVE_Y_FORWARD", 0, "-Y", "Negative Y axis"}, - {OBJ_AXIS_NEGATIVE_Z_FORWARD, "NEGATIVE_Z_FORWARD", 0, "-Z (Default)", "Negative Z axis"}, + {OBJ_AXIS_NEGATIVE_Z_FORWARD, "NEGATIVE_Z_FORWARD", 0, "-Z", "Negative Z axis"}, {0, NULL, 0, NULL, NULL}}; static const EnumPropertyItem io_obj_transform_axis_up[] = { {OBJ_AXIS_X_UP, "X_UP", 0, "X", "Positive X axis"}, - {OBJ_AXIS_Y_UP, "Y_UP", 0, "Y (Default)", "Positive Y axis"}, + {OBJ_AXIS_Y_UP, "Y_UP", 0, "Y", "Positive Y axis"}, {OBJ_AXIS_Z_UP, "Z_UP", 0, "Z", "Positive Z axis"}, {OBJ_AXIS_NEGATIVE_X_UP, "NEGATIVE_X_UP", 0, "-X", "Negative X axis"}, {OBJ_AXIS_NEGATIVE_Y_UP, "NEGATIVE_Y_UP", 0, "-Y", "Negative Y axis"}, @@ -55,7 +55,7 @@ static const EnumPropertyItem io_obj_export_evaluation_mode[] = { {DAG_EVAL_VIEWPORT, "DAG_EVAL_VIEWPORT", 0, - "Viewport (Default)", + "Viewport", "Export objects as they appear in the viewport"}, {0, NULL, 0, NULL, NULL}}; diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 429db50f321..e53dda1760e 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -546,7 +546,7 @@ static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event) value = value_start[vmode] + value * opdata->scale[vmode]; /* Fake shift-transform... */ - if (event->shift) { + if (event->modifier & KM_SHIFT) { if (opdata->shift_value[vmode] < 0.0f) { opdata->shift_value[vmode] = (vmode == SEGMENTS_VALUE) ? opdata->segments : diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index 58bd906101c..7b251b77750 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -77,14 +77,14 @@ static void mesh_bisect_interactive_calc(bContext *C, const float *co_ref = rv3d->ofs; float co_a_ss[2] = {x_start, y_start}, co_b_ss[2] = {x_end, y_end}, co_delta_ss[2]; float co_a[3], co_b[3]; - const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL); + const float zfac = ED_view3d_calc_zfac(rv3d, co_ref); /* view vector */ ED_view3d_win_to_vector(region, co_a_ss, co_a); /* view delta */ sub_v2_v2v2(co_delta_ss, co_a_ss, co_b_ss); - ED_view3d_win_to_delta(region, co_delta_ss, co_b, zfac); + ED_view3d_win_to_delta(region, co_delta_ss, zfac, co_b); /* cross both to get a normal */ cross_v3_v3v3(plane_no, co_a, co_b); diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index 84bda411d4a..bce46dd7cf7 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -58,7 +58,7 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C, } me_eval_needs_free = false; } - else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { + else if (ELEM(ob->type, OB_FONT, OB_CURVES_LEGACY, OB_SURF)) { Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); me_eval = BKE_mesh_new_nomain_from_curve(ob_eval); me_eval_needs_free = true; diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 72844908685..c9fc48c3568 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -581,7 +581,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) handled = true; break; case MOUSEPAN: - if (event->alt == 0) { + if ((event->modifier & KM_ALT) == 0) { cuts += 0.02f * (event->xy[1] - event->prev_xy[1]); if (cuts < 1 && lcd->cuts >= 1) { cuts = 1; @@ -598,7 +598,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) if (event->val == KM_RELEASE) { break; } - if (event->alt == 0) { + if ((event->modifier & KM_ALT) == 0) { cuts += 1; } else { @@ -612,7 +612,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) if (event->val == KM_RELEASE) { break; } - if (event->alt == 0) { + if ((event->modifier & KM_ALT) == 0) { cuts = max_ff(cuts - 1, 1); } else { @@ -755,7 +755,8 @@ void MESH_OT_loopcut(wmOperatorType *ot) RNA_def_property_enum_items(prop, rna_enum_proportional_falloff_curve_only_items); RNA_def_property_enum_default(prop, PROP_INVSQUARE); RNA_def_property_ui_text(prop, "Falloff", "Falloff type the feather"); - RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ + RNA_def_property_translation_context(prop, + BLT_I18NCONTEXT_ID_CURVE_LEGACY); /* Abusing id_curve :/ */ /* For redo only. */ prop = RNA_def_int(ot->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", 0, INT_MAX); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index fc1d60fc768..d8fc7a4f9d4 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1367,10 +1367,10 @@ static int edbm_select_mode_invoke(bContext *C, wmOperator *op, const wmEvent *e /* detecting these options based on shift/ctrl here is weak, but it's done * to make this work when clicking buttons or menus */ if (!RNA_struct_property_is_set(op->ptr, "use_extend")) { - RNA_boolean_set(op->ptr, "use_extend", event->shift); + RNA_boolean_set(op->ptr, "use_extend", event->modifier & KM_SHIFT); } if (!RNA_struct_property_is_set(op->ptr, "use_expand")) { - RNA_boolean_set(op->ptr, "use_expand", event->ctrl); + RNA_boolean_set(op->ptr, "use_expand", event->modifier & KM_CTRL); } return edbm_select_mode_exec(C, op); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index a1e661cf2ac..2577218d6a9 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -269,7 +269,8 @@ static void mesh_operator_edgering_props(wmOperatorType *ot, RNA_def_property_enum_items(prop, rna_enum_proportional_falloff_curve_only_items); RNA_def_property_enum_default(prop, PROP_SMOOTH); RNA_def_property_ui_text(prop, "Profile Shape", "Shape of the profile"); - RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ + RNA_def_property_translation_context(prop, + BLT_I18NCONTEXT_ID_CURVE_LEGACY); /* Abusing id_curve :/ */ } static void mesh_operator_edgering_props_get(wmOperator *op, struct EdgeRingOpSubdProps *op_props) @@ -9640,13 +9641,13 @@ static int edbm_smooth_normals_exec(bContext *C, wmOperator *op) float(*smooth_normal)[3] = MEM_callocN(sizeof(*smooth_normal) * lnors_ed_arr->totloop, __func__); - /* This is weird choice of operation, taking all loops of faces of current vertex. - * Could lead to some rather far away loops weighting as much as very close ones + /* NOTE(@mont29): This is weird choice of operation, taking all loops of faces of current + * vertex. Could lead to some rather far away loops weighting as much as very close ones * (topologically speaking), with complex polygons. * Using topological distance here (rather than geometrical one) - * makes sense imho, but would rather go with a more consistent and flexible code, - * we could even add max topological distance to take into account, * and a weighting curve. - * Would do that later though, think for now we can live with that choice. --mont29. */ + * makes sense IMHO, but would rather go with a more consistent and flexible code, + * we could even add max topological distance to take into account, and a weighting curve. + * Would do that later though, think for now we can live with that choice. */ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { l = lnor_ed->loop; diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 92f2f859965..417fdca4988 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -632,7 +632,7 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, Undo return um; } -static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key *key) +static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em) { BMEditMesh *em_tmp; BMesh *bm; @@ -688,29 +688,6 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key * bm->spacearr_dirty = BM_SPACEARR_DIRTY_ALL; - /* T35170: Restore the active key on the RealMesh. Otherwise 'fake' offset propagation happens - * if the active is a basis for any other. */ - if (key && (key->type == KEY_RELATIVE)) { - /* Since we can't add, remove or reorder keyblocks in editmode, it's safe to assume - * shapenr from restored bmesh and keyblock indices are in sync. */ - const int kb_act_idx = ob->shapenr - 1; - - /* If it is, let's patch the current mesh key block to its restored value. - * Else, the offsets won't be computed and it won't matter. */ - if (BKE_keyblock_is_basis(key, kb_act_idx)) { - KeyBlock *kb_act = BLI_findlink(&key->block, kb_act_idx); - - if (kb_act->totelem != um->me.totvert) { - /* The current mesh has some extra/missing verts compared to the undo, adjust. */ - MEM_SAFE_FREE(kb_act->data); - kb_act->data = MEM_mallocN((size_t)(key->elemsize) * bm->totvert, __func__); - kb_act->totelem = um->me.totvert; - } - - BKE_keyblock_update_from_mesh(&um->me, kb_act); - } - } - ob->shapenr = um->shapenr; MEM_freeN(em_tmp); @@ -858,7 +835,7 @@ static void mesh_undosys_step_decode(struct bContext *C, continue; } BMEditMesh *em = me->edit_mesh; - undomesh_to_editmesh(&elem->data, obedit, em, me->key); + undomesh_to_editmesh(&elem->data, obedit, em); em->needs_flush_to_id = 1; DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY); } diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 49a5345d048..b3f90880388 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -21,6 +21,7 @@ #include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" #include "BKE_report.h" #include "DEG_depsgraph.h" @@ -1110,6 +1111,8 @@ static void mesh_add_verts(Mesh *mesh, int len) mesh->vdata = vdata; BKE_mesh_update_customdata_pointers(mesh, false); + BKE_mesh_runtime_clear_cache(mesh); + /* scan the input list and insert the new vertices */ /* set default flags */ @@ -1146,6 +1149,8 @@ static void mesh_add_edges(Mesh *mesh, int len) mesh->edata = edata; BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */ + BKE_mesh_runtime_clear_cache(mesh); + /* set default flags */ medge = &mesh->medge[mesh->totedge]; for (i = 0; i < len; i++, medge++) { @@ -1174,6 +1179,8 @@ static void mesh_add_loops(Mesh *mesh, int len) CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop); } + BKE_mesh_runtime_clear_cache(mesh); + CustomData_free(&mesh->ldata, mesh->totloop); mesh->ldata = ldata; BKE_mesh_update_customdata_pointers(mesh, true); @@ -1205,6 +1212,8 @@ static void mesh_add_polys(Mesh *mesh, int len) mesh->pdata = pdata; BKE_mesh_update_customdata_pointers(mesh, true); + BKE_mesh_runtime_clear_cache(mesh); + /* set default flags */ mpoly = &mesh->mpoly[mesh->totpoly]; for (i = 0; i < len; i++, mpoly++) { diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 5a8708c84b6..f3782c17845 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -412,6 +412,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) * Even though this mesh wont typically have run-time data, the Python API can for e.g. * create loop-triangle cache here, which is confusing when left in the mesh, see: T90798. */ BKE_mesh_runtime_clear_geometry(me); + BKE_mesh_clear_derived_normals(me); /* new material indices and material array */ if (totmat) { diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index 54db59dc2fa..39ccadd1445 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -8,6 +8,7 @@ set(INC ../../blentranslation ../../bmesh ../../depsgraph + ../../functions ../../gpencil_modifiers ../../gpu ../../ikplugin @@ -28,7 +29,7 @@ set(INC ) set(SRC - object_add.c + object_add.cc object_bake.c object_bake_api.c object_collection.c diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.cc index c2d811f56dc..7befad3b8d7 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.cc @@ -5,9 +5,9 @@ * \ingroup edobj */ -#include <ctype.h> -#include <stdlib.h> -#include <string.h> +#include <cctype> +#include <cstdlib> +#include <cstring> #include "MEM_guardedalloc.h" @@ -93,6 +93,7 @@ #include "ED_armature.h" #include "ED_curve.h" +#include "ED_curves.h" #include "ED_gpencil.h" #include "ED_mball.h" #include "ED_mesh.h" @@ -122,7 +123,7 @@ const EnumPropertyItem rna_enum_light_type_items[] = { {LA_SUN, "SUN", ICON_LIGHT_SUN, "Sun", "Constant direction parallel ray light source"}, {LA_SPOT, "SPOT", ICON_LIGHT_SPOT, "Spot", "Directional cone light source"}, {LA_AREA, "AREA", ICON_LIGHT_AREA, "Area", "Directional area light source"}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; /* copy from rna_object_force.c */ @@ -140,7 +141,7 @@ static const EnumPropertyItem field_type_items[] = { {PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", ""}, {PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", ""}, {PFIELD_FLUIDFLOW, "FLUID", ICON_FORCE_FLUIDFLOW, "Fluid Flow", ""}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; static EnumPropertyItem lightprobe_type_items[] = { @@ -159,7 +160,7 @@ static EnumPropertyItem lightprobe_type_items[] = { ICON_LIGHTPROBE_GRID, "Irradiance Volume", "Irradiance probe to capture diffuse indirect lighting"}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; enum { @@ -172,7 +173,7 @@ static const EnumPropertyItem align_options[] = { {ALIGN_WORLD, "WORLD", 0, "World", "Align the new object to the world"}, {ALIGN_VIEW, "VIEW", 0, "View", "Align the new object to the view"}, {ALIGN_CURSOR, "CURSOR", 0, "3D Cursor", "Use the 3D cursor orientation for the new object"}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; /** \} */ @@ -198,7 +199,7 @@ static void object_add_drop_xy_props(wmOperatorType *ot) "X-coordinate (screen space) to place the new object under", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); prop = RNA_def_int(ot->srna, "drop_y", 0, @@ -208,7 +209,7 @@ static void object_add_drop_xy_props(wmOperatorType *ot) "Y-coordinate (screen space) to place the new object under", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); } static bool object_add_drop_xy_is_set(const wmOperator *op) @@ -343,13 +344,13 @@ float ED_object_new_primitive_matrix(bContext *C, invert_m3_m3(imat, mat); mul_m3_v3(imat, r_primmat[3]); - if (scale != NULL) { + if (scale != nullptr) { rescale_m4(r_primmat, scale); } { - const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : - ED_scene_grid_scale(scene, NULL); + const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, nullptr) : + ED_scene_grid_scale(scene, nullptr); return dia; } @@ -393,20 +394,20 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode) if (do_editmode) { prop = RNA_def_boolean(ot->srna, "enter_editmode", - 0, + false, "Enter Edit Mode", "Enter edit mode when adding this object"); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); } /* NOTE: this property gets hidden for add-camera operator. */ prop = RNA_def_enum( ot->srna, "align", align_options, ALIGN_WORLD, "Align", "The alignment of the new object"); - RNA_def_property_update_runtime(prop, view_align_update); + RNA_def_property_update_runtime(prop, (void *)view_align_update); prop = RNA_def_float_vector_xyz(ot->srna, "location", 3, - NULL, + nullptr, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF, "Location", @@ -417,7 +418,7 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode) prop = RNA_def_float_rotation(ot->srna, "rotation", 3, - NULL, + nullptr, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF, "Rotation", @@ -429,14 +430,14 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode) prop = RNA_def_float_vector_xyz(ot->srna, "scale", 3, - NULL, + nullptr, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF, "Scale", "Scale for the newly added object", -1000.0f, 1000.0f); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); } void ED_object_add_mesh_props(wmOperatorType *ot) @@ -461,11 +462,11 @@ bool ED_object_add_generic_get_opts(bContext *C, r_enter_editmode = &_enter_editmode; } /* Only to ensure the value is _always_ set. - * Typically the property will exist when the argument is non-NULL. */ + * Typically the property will exist when the argument is non-nullptr. */ *r_enter_editmode = false; PropertyRNA *prop = RNA_struct_find_property(op->ptr, "enter_editmode"); - if (prop != NULL) { + if (prop != nullptr) { if (RNA_property_is_set(op->ptr, prop) && r_enter_editmode) { *r_enter_editmode = RNA_property_boolean_get(op->ptr, prop); } @@ -571,7 +572,7 @@ bool ED_object_add_generic_get_opts(bContext *C, copy_v3_fl(r_scale, 1.0f); PropertyRNA *prop = RNA_struct_find_property(op->ptr, "scale"); - if (prop != NULL) { + if (prop != nullptr) { if (RNA_property_is_set(op->ptr, prop)) { RNA_property_float_get_array(op->ptr, prop, r_scale); } @@ -600,19 +601,19 @@ Object *ED_object_add_type_with_obdata(bContext *C, { Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); - if (obedit != NULL) { + if (obedit != nullptr) { ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); } } /* deselects all, sets active object */ Object *ob; - if (obdata != NULL) { + if (obdata != nullptr) { BLI_assert(type == BKE_object_obdata_to_type(obdata)); ob = BKE_object_add_for_data(bmain, view_layer, type, name, obdata, true); const short *materials_len_p = BKE_id_material_len_p(obdata); if (materials_len_p && *materials_len_p > 0) { - BKE_object_materials_test(bmain, ob, ob->data); + BKE_object_materials_test(bmain, ob, static_cast<ID *>(ob->data)); } } else { @@ -630,7 +631,7 @@ Object *ED_object_add_type_with_obdata(bContext *C, */ DEG_id_type_tag(bmain, ID_OB); DEG_relations_tag_update(bmain); - if (ob->data != NULL) { + if (ob->data != nullptr) { DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS); } @@ -657,7 +658,7 @@ Object *ED_object_add_type(bContext *C, const ushort local_view_bits) { return ED_object_add_type_with_obdata( - C, type, name, loc, rot, enter_editmode, local_view_bits, NULL); + C, type, name, loc, rot, enter_editmode, local_view_bits, nullptr); } /* for object add operator */ @@ -668,12 +669,12 @@ static int object_add_exec(bContext *C, wmOperator *op) float loc[3], rot[3], radius; WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts( - C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) { + C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } radius = RNA_float_get(op->ptr, "radius"); Object *ob = ED_object_add_type( - C, RNA_enum_get(op->ptr, "type"), NULL, loc, rot, enter_editmode, local_view_bits); + C, RNA_enum_get(op->ptr, "type"), nullptr, loc, rot, enter_editmode, local_view_bits); if (ob->type == OB_LATTICE) { /* lattice is a special case! @@ -737,7 +738,7 @@ static int lightprobe_add_exec(bContext *C, wmOperator *op) float loc[3], rot[3]; WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts( - C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) { + C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } int type = RNA_enum_get(op->ptr, "type"); @@ -829,26 +830,25 @@ static int effector_add_exec(bContext *C, wmOperator *op) float loc[3], rot[3]; WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts( - C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) { + C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } - int type = RNA_enum_get(op->ptr, "type"); + const ePFieldType type = static_cast<ePFieldType>(RNA_enum_get(op->ptr, "type")); float dia = RNA_float_get(op->ptr, "radius"); Object *ob; if (type == PFIELD_GUIDE) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Curve *cu; ob = ED_object_add_type( - C, OB_CURVE, get_effector_defname(type), loc, rot, false, local_view_bits); + C, OB_CURVES_LEGACY, get_effector_defname(type), loc, rot, false, local_view_bits); - cu = ob->data; + Curve *cu = static_cast<Curve *>(ob->data); cu->flag |= CU_PATH | CU_3D; ED_object_editmode_enter_ex(bmain, scene, ob, 0); float mat[4][4]; - ED_object_new_primitive_matrix(C, ob, loc, rot, NULL, mat); + ED_object_new_primitive_matrix(C, ob, loc, rot, nullptr, mat); mul_mat3_m4_fl(mat, dia); BLI_addtail(&cu->editnurb->nurbs, ED_curve_add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, 1)); @@ -909,22 +909,23 @@ static int object_camera_add_exec(bContext *C, wmOperator *op) bool enter_editmode; float loc[3], rot[3]; if (!ED_object_add_generic_get_opts( - C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) { + C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } - Object *ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, local_view_bits); + Object *ob = ED_object_add_type(C, OB_CAMERA, nullptr, loc, rot, false, local_view_bits); if (v3d) { - if (v3d->camera == NULL) { + if (v3d->camera == nullptr) { v3d->camera = ob; } - if (v3d->scenelock && scene->camera == NULL) { + if (v3d->scenelock && scene->camera == nullptr) { scene->camera = ob; } } - Camera *cam = ob->data; - cam->drawsize = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL); + Camera *cam = static_cast<Camera *>(ob->data); + cam->drawsize = v3d ? ED_view3d_grid_scale(scene, v3d, nullptr) : + ED_scene_grid_scale(scene, nullptr); return OPERATOR_FINISHED; } @@ -969,14 +970,14 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) float loc[3], rot[3]; WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts( - C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) { + C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } bool newob = false; Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); - if (obedit == NULL || obedit->type != OB_MBALL) { - obedit = ED_object_add_type(C, OB_MBALL, NULL, loc, rot, true, local_view_bits); + if (obedit == nullptr || obedit->type != OB_MBALL) { + obedit = ED_object_add_type(C, OB_MBALL, nullptr, loc, rot, true, local_view_bits); newob = true; } else { @@ -984,7 +985,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) } float mat[4][4]; - ED_object_new_primitive_matrix(C, obedit, loc, rot, NULL, mat); + ED_object_new_primitive_matrix(C, obedit, loc, rot, nullptr, mat); /* Halving here is done to account for constant values from #BKE_mball_element_add. * While the default radius of the resulting meta element is 2, * we want to pass in 1 so other values such as resolution are scaled by 1.0. */ @@ -1040,14 +1041,14 @@ static int object_add_text_exec(bContext *C, wmOperator *op) WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts( - C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) { + C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } if (obedit && obedit->type == OB_FONT) { return OPERATOR_CANCELLED; } - obedit = ED_object_add_type(C, OB_FONT, NULL, loc, rot, enter_editmode, local_view_bits); + obedit = ED_object_add_type(C, OB_FONT, nullptr, loc, rot, enter_editmode, local_view_bits); BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius")); return OPERATOR_FINISHED; @@ -1094,11 +1095,11 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts( - C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) { + C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } - if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) { - obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, local_view_bits); + if ((obedit == nullptr) || (obedit->type != OB_ARMATURE)) { + obedit = ED_object_add_type(C, OB_ARMATURE, nullptr, loc, rot, true, local_view_bits); ED_object_editmode_enter_ex(bmain, scene, obedit, 0); newob = true; } @@ -1106,7 +1107,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } - if (obedit == NULL) { + if (obedit == nullptr) { BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature"); return OPERATOR_CANCELLED; } @@ -1155,10 +1156,11 @@ static int object_empty_add_exec(bContext *C, wmOperator *op) float loc[3], rot[3]; WM_operator_view3d_unit_defaults(C, op); - if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) { + if (!ED_object_add_generic_get_opts( + C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } - ob = ED_object_add_type(C, OB_EMPTY, NULL, loc, rot, false, local_view_bits); + ob = ED_object_add_type(C, OB_EMPTY, nullptr, loc, rot, false, local_view_bits); BKE_object_empty_draw_type_set(ob, type); BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius")); @@ -1192,7 +1194,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv { Scene *scene = CTX_data_scene(C); - Image *ima = NULL; + Image *ima = nullptr; ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM); if (!ima) { @@ -1201,7 +1203,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv /* handled below */ id_us_min(&ima->id); - Object *ob = NULL; + Object *ob = nullptr; Object *ob_cursor = ED_view3d_give_object_under_cursor(C, event->mval); /* either change empty under cursor or create a new empty */ @@ -1216,10 +1218,10 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv float rot[3]; if (!ED_object_add_generic_get_opts( - C, op, 'Z', NULL, rot, NULL, NULL, &local_view_bits, NULL)) { + C, op, 'Z', nullptr, rot, nullptr, nullptr, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } - ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false, local_view_bits); + ob = ED_object_add_type(C, OB_EMPTY, nullptr, nullptr, rot, false, local_view_bits); ED_object_location_from_view(C, ob->loc); ED_view3d_cursor3d_position(C, event->mval, false, ob->loc); @@ -1229,9 +1231,9 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv BKE_object_empty_draw_type_set(ob, OB_EMPTY_IMAGE); - id_us_min(ob->data); + id_us_min(static_cast<ID *>(ob->data)); ob->data = ima; - id_us_plus(ob->data); + id_us_plus(static_cast<ID *>(ob->data)); return OPERATOR_FINISHED; } @@ -1253,16 +1255,17 @@ void OBJECT_OT_drop_named_image(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - prop = RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "Filepath", "Path to image file"); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_string(ot->srna, "filepath", nullptr, FILE_MAX, "Filepath", "Path to image file"); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); RNA_def_boolean(ot->srna, "relative_path", true, "Relative Path", "Select the file relative to the blend file"); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Image name to assign"); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); + prop = RNA_def_string( + ot->srna, "name", nullptr, MAX_ID_NAME - 2, "Name", "Image name to assign"); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); ED_object_add_generic_props(ot, false); } @@ -1277,7 +1280,7 @@ static bool object_gpencil_add_poll(bContext *C) Scene *scene = CTX_data_scene(C); Object *obact = CTX_data_active_object(C); - if ((scene == NULL) || (ID_IS_LINKED(scene))) { + if ((scene == nullptr) || (ID_IS_LINKED(scene))) { return false; } @@ -1293,7 +1296,7 @@ static bool object_gpencil_add_poll(bContext *C) static int object_gpencil_add_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C), *ob_orig = ob; - bGPdata *gpd = (ob && (ob->type == OB_GPENCIL)) ? ob->data : NULL; + bGPdata *gpd = (ob && (ob->type == OB_GPENCIL)) ? static_cast<bGPdata *>(ob->data) : nullptr; const int type = RNA_enum_get(op->ptr, "type"); const bool use_in_front = RNA_boolean_get(op->ptr, "use_in_front"); @@ -1307,12 +1310,13 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op) /* NOTE: We use 'Y' here (not 'Z'), as. */ WM_operator_view3d_unit_defaults(C, op); - if (!ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, NULL, NULL, &local_view_bits, NULL)) { + if (!ED_object_add_generic_get_opts( + C, op, 'Y', loc, rot, nullptr, nullptr, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } /* Add new object if not currently editing a GP object. */ - if ((gpd == NULL) || (GPENCIL_ANY_MODE(gpd) == false)) { - const char *ob_name = NULL; + if ((gpd == nullptr) || (GPENCIL_ANY_MODE(gpd) == false)) { + const char *ob_name = nullptr; switch (type) { case GP_EMPTY: { ob_name = "GPencil"; @@ -1338,12 +1342,12 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op) } ob = ED_object_add_type(C, OB_GPENCIL, ob_name, loc, rot, true, local_view_bits); - gpd = ob->data; + gpd = static_cast<bGPdata *>(ob->data); newob = true; } else { DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_ADDED, NULL); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_ADDED, nullptr); } /* create relevant geometry */ @@ -1351,7 +1355,7 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op) case GP_EMPTY: { float mat[4][4]; - ED_object_new_primitive_matrix(C, ob, loc, rot, NULL, mat); + ED_object_new_primitive_matrix(C, ob, loc, rot, nullptr, mat); ED_gpencil_create_blank(C, ob, mat); break; } @@ -1389,7 +1393,7 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op) ED_gpencil_create_lineart(C, ob); - gpd = ob->data; + gpd = static_cast<bGPdata *>(ob->data); /* Add Line Art modifier */ LineartGpencilModifierData *md = (LineartGpencilModifierData *)BKE_gpencil_modifier_new( @@ -1458,21 +1462,21 @@ static void object_add_ui(bContext *UNUSED(C), wmOperator *op) uiLayoutSetPropSep(layout, true); - uiItemR(layout, op->ptr, "radius", 0, NULL, ICON_NONE); - uiItemR(layout, op->ptr, "align", 0, NULL, ICON_NONE); - uiItemR(layout, op->ptr, "location", 0, NULL, ICON_NONE); - uiItemR(layout, op->ptr, "rotation", 0, NULL, ICON_NONE); - uiItemR(layout, op->ptr, "type", 0, NULL, ICON_NONE); + uiItemR(layout, op->ptr, "radius", 0, nullptr, ICON_NONE); + uiItemR(layout, op->ptr, "align", 0, nullptr, ICON_NONE); + uiItemR(layout, op->ptr, "location", 0, nullptr, ICON_NONE); + uiItemR(layout, op->ptr, "rotation", 0, nullptr, ICON_NONE); + uiItemR(layout, op->ptr, "type", 0, nullptr, ICON_NONE); int type = RNA_enum_get(op->ptr, "type"); if (ELEM(type, GP_LRT_COLLECTION, GP_LRT_OBJECT, GP_LRT_SCENE)) { - uiItemR(layout, op->ptr, "use_lights", 0, NULL, ICON_NONE); - uiItemR(layout, op->ptr, "use_in_front", 0, NULL, ICON_NONE); + uiItemR(layout, op->ptr, "use_lights", 0, nullptr, ICON_NONE); + uiItemR(layout, op->ptr, "use_in_front", 0, nullptr, ICON_NONE); bool in_front = RNA_boolean_get(op->ptr, "use_in_front"); uiLayout *col = uiLayoutColumn(layout, false); uiLayoutSetActive(col, !in_front); - uiItemR(col, op->ptr, "stroke_depth_offset", 0, NULL, ICON_NONE); - uiItemR(col, op->ptr, "stroke_depth_order", 0, NULL, ICON_NONE); + uiItemR(col, op->ptr, "stroke_depth_offset", 0, nullptr, ICON_NONE); + uiItemR(col, op->ptr, "stroke_depth_order", 0, nullptr, ICON_NONE); } } @@ -1483,7 +1487,7 @@ static EnumPropertyItem rna_enum_gpencil_add_stroke_depth_order_items[] = { "2D Layers", "Display strokes using grease pencil layers to define order"}, {GP_DRAWMODE_3D, "3D", 0, "3D Location", "Display strokes using real 3D position in 3D space"}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; void OBJECT_OT_gpencil_add(wmOperatorType *ot) @@ -1565,7 +1569,8 @@ static int object_light_add_exec(bContext *C, wmOperator *op) float loc[3], rot[3]; WM_operator_view3d_unit_defaults(C, op); - if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) { + if (!ED_object_add_generic_get_opts( + C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } ob = ED_object_add_type(C, OB_LAMP, get_light_defname(type), loc, rot, false, local_view_bits); @@ -1648,7 +1653,8 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) update_location_if_necessary = true; } else { - collection = BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection")); + collection = static_cast<Collection *>( + BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection"))); } if (update_location_if_necessary) { @@ -1660,11 +1666,12 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) } } - if (collection == NULL) { + if (collection == nullptr) { return OPERATOR_CANCELLED; } - if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) { + if (!ED_object_add_generic_get_opts( + C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } @@ -1735,7 +1742,7 @@ void OBJECT_OT_collection_instance_add(wmOperatorType *ot) "Session UUID of the collection to add", INT32_MIN, INT32_MAX); - RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN)); object_add_drop_xy_props(ot); } @@ -1751,7 +1758,7 @@ void OBJECT_OT_collection_instance_add(wmOperatorType *ot) static int object_data_instance_add_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - ID *id = NULL; + ID *id = nullptr; ushort local_view_bits; float loc[3], rot[3]; @@ -1767,7 +1774,7 @@ static int object_data_instance_add_exec(bContext *C, wmOperator *op) char name[MAX_ID_NAME - 2]; RNA_property_string_get(op->ptr, prop_name, name); id = BKE_libblock_find_name(bmain, id_type, name); - if (id == NULL) { + if (id == nullptr) { return OPERATOR_CANCELLED; } const int object_type = BKE_object_obdata_to_type(id); @@ -1782,7 +1789,8 @@ static int object_data_instance_add_exec(bContext *C, wmOperator *op) RNA_property_float_set_array(op->ptr, prop_location, loc); } - if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) { + if (!ED_object_add_generic_get_opts( + C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } @@ -1829,10 +1837,11 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) ushort local_view_bits; float loc[3], rot[3]; - if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) { + if (!ED_object_add_generic_get_opts( + C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } - Object *ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits); + Object *ob = ED_object_add_type(C, OB_SPEAKER, nullptr, loc, rot, false, local_view_bits); const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ob); /* To make it easier to start using this immediately in NLA, a default sound clip is created @@ -1840,8 +1849,8 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) { /* create new data for NLA hierarchy */ 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); + NlaTrack *nlt = BKE_nlatrack_add(adt, nullptr, is_liboverride); + NlaStrip *strip = BKE_nla_add_soundstrip(bmain, scene, static_cast<Speaker *>(ob->data)); strip->start = CFRA; strip->end += strip->start; @@ -1852,7 +1861,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) BLI_strncpy(nlt->name, DATA_("SoundTrack"), sizeof(nlt->name)); BKE_nlastrip_validate_name(adt, strip); - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, nullptr); } return OPERATOR_FINISHED; @@ -1891,15 +1900,21 @@ static bool object_hair_curves_add_poll(bContext *C) static int object_hair_curves_add_exec(bContext *C, wmOperator *op) { + using namespace blender; + ushort local_view_bits; float loc[3], rot[3]; - if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) { + if (!ED_object_add_generic_get_opts( + C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } - Object *object = ED_object_add_type(C, OB_CURVES, NULL, loc, rot, false, local_view_bits); + Object *object = ED_object_add_type(C, OB_CURVES, nullptr, loc, rot, false, local_view_bits); object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */ + Curves *curves_id = static_cast<Curves *>(object->data); + bke::CurvesGeometry::wrap(curves_id->geometry) = ed::curves::primitive_random_sphere(500, 8); + return OPERATOR_FINISHED; } @@ -1938,11 +1953,12 @@ static int object_pointcloud_add_exec(bContext *C, wmOperator *op) { ushort local_view_bits; float loc[3], rot[3]; - if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) { + if (!ED_object_add_generic_get_opts( + C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } - Object *object = ED_object_add_type(C, OB_POINTCLOUD, NULL, loc, rot, false, local_view_bits); + Object *object = ED_object_add_type(C, OB_POINTCLOUD, nullptr, loc, rot, false, local_view_bits); object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */ return OPERATOR_FINISHED; @@ -2062,11 +2078,11 @@ static int object_delete_exec(bContext *C, wmOperator *op) /* FIXME: this will also remove parent from grease pencil from other scenes. */ /* Remove from Grease Pencil parent */ - for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) { + LISTBASE_FOREACH (bGPdata *, gpd, &bmain->gpencils) { LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - if (gpl->parent != NULL) { + if (gpl->parent != nullptr) { if (gpl->parent == ob) { - gpl->parent = NULL; + gpl->parent = nullptr; } } } @@ -2123,8 +2139,8 @@ void OBJECT_OT_delete(wmOperatorType *ot) PropertyRNA *prop; prop = RNA_def_boolean( - ot->srna, "use_global", 0, "Delete Globally", "Remove object from all scenes"); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + ot->srna, "use_global", false, "Delete Globally", "Remove object from all scenes"); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); WM_operator_properties_confirm_or_exec(ot); } @@ -2188,7 +2204,7 @@ static void copy_object_set_idnew(bContext *C) */ static uint dupliobject_hash(const void *ptr) { - const DupliObject *dob = ptr; + const DupliObject *dob = static_cast<const DupliObject *>(ptr); uint hash = BLI_ghashutil_ptrhash(dob->ob); if (dob->type == OB_DUPLICOLLECTION) { @@ -2210,7 +2226,7 @@ static uint dupliobject_hash(const void *ptr) */ static uint dupliobject_instancer_hash(const void *ptr) { - const DupliObject *dob = ptr; + const DupliObject *dob = static_cast<const DupliObject *>(ptr); uint hash = BLI_ghashutil_inthash(dob->persistent_id[0]); for (int i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) { hash ^= (dob->persistent_id[i] ^ i); @@ -2221,8 +2237,8 @@ static uint dupliobject_instancer_hash(const void *ptr) /* Compare function that matches dupliobject_hash */ static bool dupliobject_cmp(const void *a_, const void *b_) { - const DupliObject *a = a_; - const DupliObject *b = b_; + const DupliObject *a = static_cast<const DupliObject *>(a_); + const DupliObject *b = static_cast<const DupliObject *>(b_); if (a->ob != b->ob) { return true; @@ -2255,8 +2271,8 @@ static bool dupliobject_cmp(const void *a_, const void *b_) /* Compare function that matches dupliobject_instancer_hash. */ static bool dupliobject_instancer_cmp(const void *a_, const void *b_) { - const DupliObject *a = a_; - const DupliObject *b = b_; + const DupliObject *a = static_cast<const DupliObject *>(a_); + const DupliObject *b = static_cast<const DupliObject *>(b_); for (int i = 0; (i < MAX_DUPLI_RECUR); i++) { if (a->persistent_id[i] != b->persistent_id[i]) { @@ -2280,7 +2296,7 @@ static void make_object_duplilist_real(bContext *C, { Main *bmain = CTX_data_main(C); ViewLayer *view_layer = CTX_data_view_layer(C); - GHash *parent_gh = NULL, *instancer_gh = NULL; + GHash *parent_gh = nullptr, *instancer_gh = nullptr; Object *object_eval = DEG_get_evaluated_object(depsgraph, base->object); @@ -2308,19 +2324,19 @@ static void make_object_duplilist_real(bContext *C, LISTBASE_FOREACH (DupliObject *, dob, lb_duplis) { Object *ob_src = DEG_get_original_object(dob->ob); - Object *ob_dst = ID_NEW_SET(ob_src, BKE_id_copy(bmain, &ob_src->id)); + Object *ob_dst = static_cast<Object *>(ID_NEW_SET(ob_src, BKE_id_copy(bmain, &ob_src->id))); id_us_min(&ob_dst->id); /* font duplis can have a totcol without material, we get them from parent * should be implemented better... */ - if (ob_dst->mat == NULL) { + if (ob_dst->mat == nullptr) { ob_dst->totcol = 0; } BKE_collection_object_add_from(bmain, scene, base->object, ob_dst); Base *base_dst = BKE_view_layer_base_find(view_layer, ob_dst); - BLI_assert(base_dst != NULL); + BLI_assert(base_dst != nullptr); ED_object_base_select(base_dst, BA_SELECT); DEG_id_tag_update(&ob_dst->id, ID_RECALC_SELECT); @@ -2329,17 +2345,17 @@ static void make_object_duplilist_real(bContext *C, /* make sure apply works */ BKE_animdata_free(&ob_dst->id, true); - ob_dst->adt = NULL; + ob_dst->adt = nullptr; - ob_dst->parent = NULL; + ob_dst->parent = nullptr; BKE_constraints_free(&ob_dst->constraints); - ob_dst->runtime.curve_cache = NULL; + ob_dst->runtime.curve_cache = nullptr; const bool is_dupli_instancer = (ob_dst->transflag & OB_DUPLI) != 0; ob_dst->transflag &= ~OB_DUPLI; /* Remove instantiated collection, it's annoying to keep it here * (and get potentially a lot of usages of it then...). */ id_us_min((ID *)ob_dst->instance_collection); - ob_dst->instance_collection = NULL; + ob_dst->instance_collection = nullptr; copy_m4_m4(ob_dst->obmat, dob->mat); BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false); @@ -2365,7 +2381,7 @@ static void make_object_duplilist_real(bContext *C, LISTBASE_FOREACH (DupliObject *, dob, lb_duplis) { Object *ob_src = dob->ob; - Object *ob_dst = BLI_ghash_lookup(dupli_gh, dob); + Object *ob_dst = static_cast<Object *>(BLI_ghash_lookup(dupli_gh, dob)); /* Remap new object to itself, and clear again newid pointer of orig object. */ BKE_libblock_relink_to_newid(bmain, &ob_dst->id, 0); @@ -2375,7 +2391,7 @@ static void make_object_duplilist_real(bContext *C, if (use_hierarchy) { /* original parents */ Object *ob_src_par = ob_src->parent; - Object *ob_dst_par = NULL; + Object *ob_dst_par = nullptr; /* find parent that was also made real */ if (ob_src_par) { @@ -2392,7 +2408,7 @@ static void make_object_duplilist_real(bContext *C, else { dob_key.persistent_id[0] = dob->persistent_id[0]; } - ob_dst_par = BLI_ghash_lookup(parent_gh, &dob_key); + ob_dst_par = static_cast<Object *>(BLI_ghash_lookup(parent_gh, &dob_key)); } if (ob_dst_par) { @@ -2408,10 +2424,10 @@ static void make_object_duplilist_real(bContext *C, ob_dst->parent = ob_dst_par; } } - if (use_base_parent && ob_dst->parent == NULL) { - Object *ob_dst_par = NULL; + if (use_base_parent && ob_dst->parent == nullptr) { + Object *ob_dst_par = nullptr; - if (instancer_gh != NULL) { + if (instancer_gh != nullptr) { /* OK to keep most of the members uninitialized, * they won't be read, this is simply for a hash lookup. */ DupliObject dob_key; @@ -2421,10 +2437,10 @@ static void make_object_duplilist_real(bContext *C, memcpy(&dob_key.persistent_id[0], &dob->persistent_id[1], sizeof(dob_key.persistent_id[0]) * (MAX_DUPLI_RECUR - 1)); - ob_dst_par = BLI_ghash_lookup(instancer_gh, &dob_key); + ob_dst_par = static_cast<Object *>(BLI_ghash_lookup(instancer_gh, &dob_key)); } - if (ob_dst_par == NULL) { + if (ob_dst_par == nullptr) { /* Default to parenting to root object... * Always the case when use_hierarchy is false. */ ob_dst_par = base->object; @@ -2445,18 +2461,18 @@ static void make_object_duplilist_real(bContext *C, } if (base->object->transflag & OB_DUPLICOLLECTION && base->object->instance_collection) { - base->object->instance_collection = NULL; + base->object->instance_collection = nullptr; } ED_object_base_select(base, BA_DESELECT); DEG_id_tag_update(&base->object->id, ID_RECALC_SELECT); - BLI_ghash_free(dupli_gh, NULL, NULL); + BLI_ghash_free(dupli_gh, nullptr, nullptr); if (parent_gh) { - BLI_ghash_free(parent_gh, NULL, NULL); + BLI_ghash_free(parent_gh, nullptr, nullptr); } if (instancer_gh) { - BLI_ghash_free(instancer_gh, NULL, NULL); + BLI_ghash_free(instancer_gh, nullptr, nullptr); } free_object_duplilist(lb_duplis); @@ -2488,7 +2504,7 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_SCENE, scene); - WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); + WM_main_add_notifier(NC_OBJECT | ND_DRAW, nullptr); ED_outliner_select_sync_from_object_tag(C); return OPERATOR_FINISHED; @@ -2511,11 +2527,11 @@ void OBJECT_OT_duplicates_make_real(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_base_parent", - 0, + false, "Parent", "Parent newly created objects to the original instancer"); RNA_def_boolean( - ot->srna, "use_hierarchy", 0, "Keep Hierarchy", "Maintain parent child relationships"); + ot->srna, "use_hierarchy", false, "Keep Hierarchy", "Maintain parent child relationships"); } /** \} */ @@ -2525,7 +2541,11 @@ void OBJECT_OT_duplicates_make_real(wmOperatorType *ot) * \{ */ static const EnumPropertyItem convert_target_items[] = { - {OB_CURVE, "CURVE", ICON_OUTLINER_OB_CURVE, "Curve", "Curve from Mesh or Text objects"}, + {OB_CURVES_LEGACY, + "CURVE", + ICON_OUTLINER_OB_CURVE, + "Curve", + "Curve from Mesh or Text objects"}, {OB_MESH, "MESH", ICON_OUTLINER_OB_MESH, @@ -2547,19 +2567,19 @@ static const EnumPropertyItem convert_target_items[] = { "Point Cloud", "Point Cloud from Mesh objects"}, #endif - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; static void object_data_convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob) { - if (ob->runtime.curve_cache == NULL) { + if (ob->runtime.curve_cache == nullptr) { /* Force creation. This is normally not needed but on operator * redo we might end up with an object which isn't evaluated yet. * Also happens in case we are working on a copy of the object * (all its caches have been nuked then). */ - if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { - /* We need 'for render' ON here, to enable computing bevel dipslist if needed. + if (ELEM(ob->type, OB_SURF, OB_CURVES_LEGACY, OB_FONT)) { + /* We need 'for render' ON here, to enable computing bevel #DispList if needed. * Also makes sense anyway, we would not want e.g. to lose hidden parts etc. */ BKE_displist_make_curveTypes(depsgraph, scene, ob, true); } @@ -2572,10 +2592,10 @@ static void object_data_convert_ensure_curve_cache(Depsgraph *depsgraph, Scene * static void object_data_convert_curve_to_mesh(Main *bmain, Depsgraph *depsgraph, Object *ob) { Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); - Curve *curve = ob->data; + Curve *curve = static_cast<Curve *>(ob->data); Mesh *mesh = BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object_eval, true); - if (mesh == NULL) { + if (mesh == nullptr) { /* Unable to convert the curve to a mesh. */ return; } @@ -2606,9 +2626,9 @@ static bool object_convert_poll(bContext *C) { Scene *scene = CTX_data_scene(C); Base *base_act = CTX_data_active_base(C); - Object *obact = base_act ? base_act->object : NULL; + Object *obact = base_act ? base_act->object : nullptr; - if (obact == NULL || obact->data == NULL || ID_IS_LINKED(obact) || + if (obact == nullptr || obact->data == nullptr || ID_IS_LINKED(obact) || ID_IS_OVERRIDE_LIBRARY(obact) || ID_IS_OVERRIDE_LIBRARY(obact->data)) { return false; } @@ -2621,7 +2641,7 @@ static bool object_convert_poll(bContext *C) static Base *duplibase_for_convert( Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob) { - if (ob == NULL) { + if (ob == nullptr) { ob = base->object; } @@ -2636,14 +2656,14 @@ static Base *duplibase_for_convert( /* XXX: An ugly hack needed because if we re-run depsgraph with some new meta-ball objects * having same 'family name' as orig ones, they will affect end result of meta-ball computation. - * For until we get rid of that name-based thingy in MBalls, that should do the trick - * (this is weak, but other solution (to change name of `obn`) is even worse imho). + * For until we get rid of that name-based thingy in meta-balls, that should do the trick + * (this is weak, but other solution (to change name of `obn`) is even worse IMHO). * See T65996. */ const bool is_meta_ball = (obn->type == OB_MBALL); void *obdata = obn->data; if (is_meta_ball) { obn->type = OB_EMPTY; - obn->data = NULL; + obn->data = nullptr; } /* XXX Doing that here is stupid, it means we update and re-evaluate the whole depsgraph every @@ -2675,7 +2695,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); - Base *basen = NULL, *basact = NULL; + Base *basen = nullptr, *basact = nullptr; Object *ob1, *obact = CTX_data_active_object(C); const short target = RNA_enum_get(op->ptr, "target"); bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); @@ -2723,7 +2743,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) * on other objects data masks too, see: T50950. */ { LISTBASE_FOREACH (CollectionPointerLink *, link, &selected_editable_bases) { - Base *base = link->ptr.data; + Base *base = static_cast<Base *>(link->ptr.data); Object *ob = base->object; /* The way object type conversion works currently (enforcing conversion of *all* objects @@ -2750,8 +2770,8 @@ static int object_convert_exec(bContext *C, wmOperator *op) } LISTBASE_FOREACH (CollectionPointerLink *, link, &selected_editable_bases) { - Object *newob = NULL; - Base *base = link->ptr.data; + Object *newob = nullptr; + Base *base = static_cast<Base *>(link->ptr.data); Object *ob = base->object; if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) { @@ -2773,15 +2793,15 @@ static int object_convert_exec(bContext *C, wmOperator *op) } } } - else if (ob->type == OB_MESH && target == OB_CURVE) { + else if (ob->type == OB_MESH && target == OB_CURVES_LEGACY) { ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr); newob = basen->object; /* Decrement original mesh's usage count. */ - Mesh *me = newob->data; + Mesh *me = static_cast<Mesh *>(newob->data); id_us_min(&me->id); /* Make a new copy of the mesh. */ @@ -2793,9 +2813,9 @@ static int object_convert_exec(bContext *C, wmOperator *op) BKE_mesh_to_curve(bmain, depsgraph, scene, newob); - if (newob->type == OB_CURVE) { + if (newob->type == OB_CURVES_LEGACY) { BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */ - if (newob->rigidbody_object != NULL) { + if (newob->rigidbody_object != nullptr) { ED_rigidbody_object_remove(bmain, scene, newob); } } @@ -2851,11 +2871,11 @@ static int object_convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr); newob = basen->object; /* Decrement original mesh's usage count. */ - Mesh *me = newob->data; + Mesh *me = static_cast<Mesh *>(newob->data); id_us_min(&me->id); /* Make a new copy of the mesh. */ @@ -2876,11 +2896,11 @@ static int object_convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr); newob = basen->object; /* Decrement original mesh's usage count. */ - Mesh *me = newob->data; + Mesh *me = static_cast<Mesh *>(newob->data); id_us_min(&me->id); /* Make a new copy of the mesh. */ @@ -2912,50 +2932,58 @@ static int object_convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr); newob = basen->object; /* Decrement original curve's usage count. */ id_us_min(&((Curve *)newob->data)->id); /* Make a new copy of the curve. */ - newob->data = BKE_id_copy(bmain, ob->data); + newob->data = BKE_id_copy(bmain, static_cast<ID *>(ob->data)); } else { newob = ob; } - Curve *cu = newob->data; + Curve *cu = static_cast<Curve *>(newob->data); Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - BKE_vfont_to_curve_ex(ob_eval, ob_eval->data, FO_EDIT, &cu->nurb, NULL, NULL, NULL, NULL); - - newob->type = OB_CURVE; - cu->type = OB_CURVE; + BKE_vfont_to_curve_ex(ob_eval, + static_cast<Curve *>(ob_eval->data), + FO_EDIT, + &cu->nurb, + nullptr, + nullptr, + nullptr, + nullptr); + + newob->type = OB_CURVES_LEGACY; + cu->type = OB_CURVES_LEGACY; if (cu->vfont) { id_us_min(&cu->vfont->id); - cu->vfont = NULL; + cu->vfont = nullptr; } if (cu->vfontb) { id_us_min(&cu->vfontb->id); - cu->vfontb = NULL; + cu->vfontb = nullptr; } if (cu->vfonti) { id_us_min(&cu->vfonti->id); - cu->vfonti = NULL; + cu->vfonti = nullptr; } if (cu->vfontbi) { id_us_min(&cu->vfontbi->id); - cu->vfontbi = NULL; + cu->vfontbi = nullptr; } if (!keep_original) { /* other users */ if (ID_REAL_USERS(&cu->id) > 1) { - for (ob1 = bmain->objects.first; ob1; ob1 = ob1->id.next) { + for (ob1 = static_cast<Object *>(bmain->objects.first); ob1; + ob1 = static_cast<Object *>(ob1->id.next)) { if (ob1->data == ob->data) { - ob1->type = OB_CURVE; + ob1->type = OB_CURVES_LEGACY; DEG_id_tag_update(&ob1->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); } @@ -2985,22 +3013,22 @@ static int object_convert_exec(bContext *C, wmOperator *op) BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, newob, false, 1.0f, 0.0f); gpencilConverted = true; gpencilCurveConverted = true; - basen = NULL; + basen = nullptr; } } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) { ob->flag |= OB_DONE; if (target == OB_MESH) { if (keep_original) { - basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr); newob = basen->object; /* Decrement original curve's usage count. */ id_us_min(&((Curve *)newob->data)->id); /* make a new copy of the curve */ - newob->data = BKE_id_copy(bmain, ob->data); + newob->data = BKE_id_copy(bmain, static_cast<ID *>(ob->data)); } else { newob = ob; @@ -3013,7 +3041,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) BKE_object_free_curve_cache(newob); } else if (target == OB_GPENCIL) { - if (ob->type != OB_CURVE) { + if (ob->type != OB_CURVES_LEGACY) { ob->flag &= ~OB_DONE; BKE_report(op->reports, RPT_ERROR, "Convert Surfaces to Grease Pencil is not supported"); } @@ -3047,23 +3075,24 @@ static int object_convert_exec(bContext *C, wmOperator *op) basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, baseob); newob = basen->object; - MetaBall *mb = newob->data; + MetaBall *mb = static_cast<MetaBall *>(newob->data); id_us_min(&mb->id); newob->data = BKE_mesh_add(bmain, "Mesh"); newob->type = OB_MESH; - Mesh *me = newob->data; + Mesh *me = static_cast<Mesh *>(newob->data); me->totcol = mb->totcol; if (newob->totcol) { - me->mat = MEM_dupallocN(mb->mat); + me->mat = static_cast<Material **>(MEM_dupallocN(mb->mat)); for (a = 0; a < newob->totcol; a++) { id_us_plus((ID *)me->mat[a]); } } object_data_convert_ensure_curve_cache(depsgraph, scene, baseob); - BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, newob->data); + BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, + static_cast<Mesh *>(newob->data)); if (obact->type == OB_MBALL) { basact = basen; @@ -3077,11 +3106,11 @@ static int object_convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr); newob = basen->object; /* Decrement original point cloud's usage count. */ - PointCloud *pointcloud = newob->data; + PointCloud *pointcloud = static_cast<PointCloud *>(newob->data); id_us_min(&pointcloud->id); /* Make a new copy of the point cloud. */ @@ -3104,7 +3133,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* Ensure new object has consistent material data with its new obdata. */ if (newob) { - BKE_object_materials_test(bmain, newob, newob->data); + BKE_object_materials_test(bmain, newob, static_cast<ID *>(newob->data)); } /* tag obdata if it was been changed */ @@ -3116,7 +3145,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) basact = basen; } - basen = NULL; + basen = nullptr; } if (!keep_original && (ob->flag & OB_DONE)) { @@ -3137,7 +3166,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) * their basis happens to be removed first. */ FOREACH_SCENE_OBJECT_BEGIN (scene, ob_mball) { if (ob_mball->type == OB_MBALL) { - Object *ob_basis = NULL; + Object *ob_basis = nullptr; if (!BKE_mball_is_basis(ob_mball) && ((ob_basis = BKE_mball_basis_find(scene, ob_mball)) && (ob_basis->flag & OB_DONE))) { ED_object_base_free_and_unlink(bmain, scene, ob_mball); @@ -3159,7 +3188,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* Remove curves and meshes converted to Grease Pencil object. */ if (gpencilConverted) { FOREACH_SCENE_OBJECT_BEGIN (scene, ob_delete) { - if (ELEM(ob_delete->type, OB_CURVE, OB_MESH)) { + if (ELEM(ob_delete->type, OB_CURVES_LEGACY, OB_MESH)) { if (ob_delete->flag & OB_DONE) { ED_object_base_free_and_unlink(bmain, scene, ob_delete); } @@ -3172,7 +3201,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* Remove Text curves converted to Grease Pencil object to avoid duplicated curves. */ if (gpencilCurveConverted) { FOREACH_SCENE_OBJECT_BEGIN (scene, ob_delete) { - if (ELEM(ob_delete->type, OB_CURVE) && (ob_delete->flag & OB_DONE)) { + if (ELEM(ob_delete->type, OB_CURVES_LEGACY) && (ob_delete->flag & OB_DONE)) { ED_object_base_free_and_unlink(bmain, scene, ob_delete); } } @@ -3181,7 +3210,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) } // XXX ED_object_editmode_enter(C, 0); - // XXX exit_editmode(C, EM_FREEDATA|); /* freedata, but no undo */ + // XXX exit_editmode(C, EM_FREEDATA|); /* free data, but no undo */ if (basact) { /* active base was changed */ @@ -3208,15 +3237,15 @@ static void object_convert_ui(bContext *UNUSED(C), wmOperator *op) uiLayoutSetPropSep(layout, true); - uiItemR(layout, op->ptr, "target", 0, NULL, ICON_NONE); - uiItemR(layout, op->ptr, "keep_original", 0, NULL, ICON_NONE); + uiItemR(layout, op->ptr, "target", 0, nullptr, ICON_NONE); + uiItemR(layout, op->ptr, "keep_original", 0, nullptr, ICON_NONE); if (RNA_enum_get(op->ptr, "target") == OB_GPENCIL) { - uiItemR(layout, op->ptr, "thickness", 0, NULL, ICON_NONE); - uiItemR(layout, op->ptr, "angle", 0, NULL, ICON_NONE); - uiItemR(layout, op->ptr, "offset", 0, NULL, ICON_NONE); - uiItemR(layout, op->ptr, "seams", 0, NULL, ICON_NONE); - uiItemR(layout, op->ptr, "faces", 0, NULL, ICON_NONE); + uiItemR(layout, op->ptr, "thickness", 0, nullptr, ICON_NONE); + uiItemR(layout, op->ptr, "angle", 0, nullptr, ICON_NONE); + uiItemR(layout, op->ptr, "offset", 0, nullptr, ICON_NONE); + uiItemR(layout, op->ptr, "seams", 0, nullptr, ICON_NONE); + uiItemR(layout, op->ptr, "faces", 0, nullptr, ICON_NONE); } } @@ -3243,14 +3272,14 @@ void OBJECT_OT_convert(wmOperatorType *ot) ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to"); RNA_def_boolean(ot->srna, "keep_original", - 0, + false, "Keep Original", "Keep original objects instead of replacing them"); prop = RNA_def_float_rotation(ot->srna, "angle", 0, - NULL, + nullptr, DEG2RADF(0.0f), DEG2RADF(180.0f), "Threshold Angle", @@ -3260,8 +3289,8 @@ void OBJECT_OT_convert(wmOperatorType *ot) RNA_def_property_float_default(prop, DEG2RADF(70.0f)); RNA_def_int(ot->srna, "thickness", 5, 1, 100, "Thickness", "", 1, 100); - RNA_def_boolean(ot->srna, "seams", 0, "Only Seam Edges", "Convert only seam edges"); - RNA_def_boolean(ot->srna, "faces", 1, "Export Faces", "Export faces as filled strokes"); + RNA_def_boolean(ot->srna, "seams", false, "Only Seam Edges", "Convert only seam edges"); + RNA_def_boolean(ot->srna, "faces", true, "Export Faces", "Export faces as filled strokes"); RNA_def_float_distance(ot->srna, "offset", 0.01f, @@ -3279,16 +3308,11 @@ void OBJECT_OT_convert(wmOperatorType *ot) /** \name Duplicate Object Operator * \{ */ -/* - * dupflag: a flag made from constants declared in DNA_userdef_types.h - * The flag tells adduplicate() whether to copy data linked to the object, - * or to reference the existing data. - * U.dupflag for default operations or you can construct a flag as python does - * if the dupflag is 0 then no data will be copied (linked duplicate). */ - -/* used below, assumes id.new is correct */ -/* leaves selection of base/object unaltered */ -/* Does set ID->newid pointers. */ +/** + * - Assumes `id.new` is correct. + * - Leaves selection of base/object unaltered. + * - Sets #ID.newid pointers. + */ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer *view_layer, @@ -3296,18 +3320,19 @@ static Base *object_add_duplicate_internal(Main *bmain, const eDupli_ID_Flags dupflag, const eLibIDDuplicateFlags duplicate_options) { - Base *base, *basen = NULL; + Base *base, *basen = nullptr; Object *obn; if (ob->mode & OB_MODE_POSE) { /* nothing? */ } else { - obn = ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options)); + obn = static_cast<Object *>( + ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options))); DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); base = BKE_view_layer_base_find(view_layer, ob); - if ((base != NULL) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) { + if ((base != nullptr) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) { BKE_collection_object_add_from(bmain, scene, ob, obn); } else { @@ -3316,7 +3341,7 @@ static Base *object_add_duplicate_internal(Main *bmain, } basen = BKE_view_layer_base_find(view_layer, obn); - if (base != NULL) { + if (base != nullptr) { basen->local_view_bits = base->local_view_bits; } @@ -3325,8 +3350,7 @@ static Base *object_add_duplicate_internal(Main *bmain, */ /* XXX: is 2) really a good measure here? */ if (ob->rigidbody_object || ob->rigidbody_constraint) { - Collection *collection; - for (collection = bmain->collections.first; collection; collection = collection->id.next) { + LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { if (BKE_collection_has_object(collection, ob)) { BKE_collection_object_add(bmain, collection, obn); } @@ -3349,8 +3373,8 @@ Base *ED_object_add_duplicate( dupflag, LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID); - if (basen == NULL) { - return NULL; + if (basen == nullptr) { + return nullptr; } ob = basen->object; @@ -3363,7 +3387,7 @@ Base *ED_object_add_duplicate( /* DAG_relations_tag_update(bmain); */ /* caller must do */ - if (ob->data != NULL) { + if (ob->data != nullptr) { DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS); } @@ -3379,7 +3403,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const bool linked = RNA_boolean_get(op->ptr, "linked"); - const eDupli_ID_Flags dupflag = (linked) ? 0 : (eDupli_ID_Flags)U.dupflag; + const eDupli_ID_Flags dupflag = (linked) ? (eDupli_ID_Flags)0 : (eDupli_ID_Flags)U.dupflag; /* We need to handle that here ourselves, because we may duplicate several objects, in which case * we also want to remap pointers between those... */ @@ -3399,7 +3423,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) ED_object_base_select(base, BA_DESELECT); ED_object_base_select(basen, BA_SELECT); - if (basen == NULL) { + if (basen == nullptr) { continue; } @@ -3409,7 +3433,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) } if (basen->object->data) { - DEG_id_tag_update(basen->object->data, 0); + DEG_id_tag_update(static_cast<ID *>(basen->object->data), 0); } } CTX_DATA_END; @@ -3447,7 +3471,7 @@ void OBJECT_OT_duplicate(wmOperatorType *ot) /* to give to transform */ prop = RNA_def_boolean(ot->srna, "linked", - 0, + false, "Linked", "Duplicate object but not object data, linking to the original data"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); @@ -3473,14 +3497,14 @@ static int object_add_named_exec(bContext *C, wmOperator *op) Base *basen; Object *ob; const bool linked = RNA_boolean_get(op->ptr, "linked"); - const eDupli_ID_Flags dupflag = (linked) ? 0 : (eDupli_ID_Flags)U.dupflag; + const eDupli_ID_Flags dupflag = (linked) ? (eDupli_ID_Flags)0 : (eDupli_ID_Flags)U.dupflag; char name[MAX_ID_NAME - 2]; /* find object, create fake base */ RNA_string_get(op->ptr, "name", name); ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name); - if (ob == NULL) { + if (ob == nullptr) { BKE_report(op->reports, RPT_ERROR, "Object not found"); return OPERATOR_CANCELLED; } @@ -3499,7 +3523,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op) */ LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID); - if (basen == NULL) { + if (basen == nullptr) { BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated"); return OPERATOR_CANCELLED; } @@ -3510,7 +3534,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op) /* object_add_duplicate_internal() doesn't deselect other objects, unlike object_add_common() or * BKE_view_layer_base_deselect_all(). */ - ED_object_base_deselect_all(view_layer, NULL, SEL_DESELECT); + ED_object_base_deselect_all(view_layer, nullptr, SEL_DESELECT); ED_object_base_select(basen, BA_SELECT); ED_object_base_activate(C, basen); @@ -3566,11 +3590,11 @@ void OBJECT_OT_add_named(wmOperatorType *ot) "Linked", "Duplicate object but not object data, linking to the original data"); - RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Object name to add"); + RNA_def_string(ot->srna, "name", nullptr, MAX_ID_NAME - 2, "Name", "Object name to add"); prop = RNA_def_float_matrix( - ot->srna, "matrix", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + ot->srna, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); object_add_drop_xy_props(ot); } @@ -3599,7 +3623,7 @@ static int object_transform_to_mouse_exec(bContext *C, wmOperator *op) ob = OBACT(view_layer); } - if (ob == NULL) { + if (ob == nullptr) { BKE_report(op->reports, RPT_ERROR, "Object not found"); return OPERATOR_CANCELLED; } @@ -3615,8 +3639,10 @@ static int object_transform_to_mouse_exec(bContext *C, wmOperator *op) PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix"); if (RNA_property_is_set(op->ptr, prop_matrix)) { + ObjectsInViewLayerParams params = {0}; uint objects_len; - Object **objects = BKE_view_layer_array_selected_objects(view_layer, NULL, &objects_len, {0}); + Object **objects = BKE_view_layer_array_selected_objects_params( + view_layer, nullptr, &objects_len, ¶ms); float matrix[4][4]; RNA_property_float_get_array(op->ptr, prop_matrix, &matrix[0][0]); @@ -3674,14 +3700,14 @@ void OBJECT_OT_transform_to_mouse(wmOperatorType *ot) PropertyRNA *prop; RNA_def_string(ot->srna, "name", - NULL, + nullptr, MAX_ID_NAME - 2, "Name", "Object name to place (when unset use the active object)"); prop = RNA_def_float_matrix( - ot->srna, "matrix", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + ot->srna, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); object_add_drop_xy_props(ot); } @@ -3696,12 +3722,12 @@ static bool object_join_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - if (ob == NULL || ob->data == NULL || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) || + if (ob == nullptr || ob->data == nullptr || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { return false; } - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE, OB_GPENCIL)) { + if (ELEM(ob->type, OB_MESH, OB_CURVES_LEGACY, OB_SURF, OB_ARMATURE, OB_GPENCIL)) { return ED_operator_screenactive(C); } return false; @@ -3740,7 +3766,7 @@ static int object_join_exec(bContext *C, wmOperator *op) if (ob->type == OB_MESH) { ret = ED_mesh_join_objects_exec(C, op); } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) { ret = ED_curve_join_objects_exec(C, op); } else if (ob->type == OB_ARMATURE) { @@ -3802,7 +3828,7 @@ static bool join_shapes_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - if (ob == NULL || ob->data == NULL || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) || + if (ob == nullptr || ob->data == nullptr || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { return false; } diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 30e3f2b0c69..3b40a10eb2a 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -301,6 +301,7 @@ static void bake_targets_refresh(BakeTargets *targets) Image *ima = targets->images[i].image; if (ima) { + BKE_image_partial_update_mark_full_update(ima); LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { BKE_image_free_gputextures(ima); DEG_id_tag_update(&ima->id, 0); @@ -605,7 +606,7 @@ static bool bake_objects_check(Main *bmain, continue; } - if (ELEM(ob_iter->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL) == false) { + if (ELEM(ob_iter->type, OB_MESH, OB_FONT, OB_CURVES_LEGACY, OB_SURF, OB_MBALL) == false) { BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh or can't be converted to a mesh (Curve, Text, " @@ -1038,19 +1039,18 @@ static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets, * materials and UVs. */ pixel->seed = v; - /* Barycentric coordinates, nudged a bit to avoid precision issues that - * may happen when exactly at the vertex coordinate. */ + /* Barycentric coordinates. */ if (j == 0) { - pixel->uv[0] = 1.0f - FLT_EPSILON; - pixel->uv[1] = FLT_EPSILON / 2.0f; + pixel->uv[0] = 1.0f; + pixel->uv[1] = 0.0f; } else if (j == 1) { - pixel->uv[0] = FLT_EPSILON / 2.0f; - pixel->uv[1] = 1.0f - FLT_EPSILON; + pixel->uv[0] = 0.0f; + pixel->uv[1] = 1.0f; } else if (j == 2) { - pixel->uv[0] = FLT_EPSILON / 2.0f; - pixel->uv[1] = FLT_EPSILON / 2.0f; + pixel->uv[0] = 0.0f; + pixel->uv[1] = 0.0f; } } } diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 4ccd35b512b..3f4ed27a175 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -511,7 +511,7 @@ static void test_constraint( * * In other cases it should be impossible to have a type mismatch. */ - if (ct->tar->type != OB_CURVE) { + if (ct->tar->type != OB_CURVES_LEGACY) { con->flag |= CONSTRAINT_DISABLE; } else { @@ -1443,6 +1443,11 @@ static int constraint_delete_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Object *ob = ED_object_active_context(C); bConstraint *con = edit_constraint_property_get(C, op, ob, 0); + + if (con == NULL) { + return OPERATOR_CANCELLED; + } + ListBase *lb = ED_object_constraint_list_from_constraint(ob, con, NULL); /* Store name temporarily for report. */ @@ -1510,6 +1515,11 @@ static int constraint_apply_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Object *ob = ED_object_active_context(C); bConstraint *con = edit_constraint_property_get(C, op, ob, 0); + + if (con == NULL) { + return OPERATOR_CANCELLED; + } + bPoseChannel *pchan; ListBase *constraints = ED_object_constraint_list_from_constraint(ob, con, &pchan); @@ -1602,6 +1612,11 @@ static int constraint_copy_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Object *ob = ED_object_active_context(C); bConstraint *con = edit_constraint_property_get(C, op, ob, 0); + + if (con == NULL) { + return OPERATOR_CANCELLED; + } + bPoseChannel *pchan; ListBase *constraints = ED_object_constraint_list_from_constraint(ob, con, &pchan); @@ -1682,6 +1697,11 @@ static int constraint_copy_to_selected_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Object *obact = ED_object_active_context(C); bConstraint *con = edit_constraint_property_get(C, op, obact, 0); + + if (con == NULL) { + return OPERATOR_CANCELLED; + } + bPoseChannel *pchan; ED_object_constraint_list_from_constraint(obact, con, &pchan); @@ -2275,7 +2295,8 @@ static bool get_new_constraint_target( break; } - if (((!only_curve) || (ob->type == OB_CURVE)) && ((!only_mesh) || (ob->type == OB_MESH))) { + if (((!only_curve) || (ob->type == OB_CURVES_LEGACY)) && + ((!only_mesh) || (ob->type == OB_MESH))) { /* set target */ *tar_ob = ob; found = true; diff --git a/source/blender/editors/object/object_data_transform.c b/source/blender/editors/object/object_data_transform.c index f74556e3639..63513eac965 100644 --- a/source/blender/editors/object/object_data_transform.c +++ b/source/blender/editors/object/object_data_transform.c @@ -382,7 +382,7 @@ struct XFormObjectData *ED_object_data_xform_create_ex(ID *id, bool is_edit_mode break; } - case ID_CU: { + case ID_CU_LEGACY: { Curve *cu = (Curve *)id; struct Key *key = cu->key; @@ -505,7 +505,7 @@ void ED_object_data_xform_destroy(struct XFormObjectData *xod_base) } break; } - case ID_CU: { + case ID_CU_LEGACY: { struct XFormObjectData_Curve *xod = (struct XFormObjectData_Curve *)xod_base; if (xod->key_data != NULL) { MEM_freeN(xod->key_data); @@ -565,7 +565,7 @@ void ED_object_data_xform_by_mat4(struct XFormObjectData *xod_base, const float break; } - case ID_CU: { + case ID_CU_LEGACY: { BLI_assert(xod_base->is_edit_mode == false); /* Not used currently. */ Curve *cu = (Curve *)xod_base->id; @@ -670,7 +670,7 @@ void ED_object_data_xform_restore(struct XFormObjectData *xod_base) break; } - case ID_CU: { + case ID_CU_LEGACY: { Curve *cu = (Curve *)xod_base->id; struct Key *key = cu->key; @@ -745,7 +745,7 @@ void ED_object_data_xform_tag_update(struct XFormObjectData *xod_base) DEG_id_tag_update(<->id, ID_RECALC_GEOMETRY); break; } - case ID_CU: { + case ID_CU_LEGACY: { /* Generic update. */ Curve *cu = (Curve *)xod_base->id; DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index fd40ac7bc7c..82b14787d9b 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -21,6 +21,7 @@ #include "BLT_translation.h" +#include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_collection_types.h" #include "DNA_curve_types.h" @@ -73,6 +74,7 @@ #include "ED_curve.h" #include "ED_gpencil.h" #include "ED_image.h" +#include "ED_keyframes_keylist.h" #include "ED_lattice.h" #include "ED_mball.h" #include "ED_mesh.h" @@ -89,7 +91,7 @@ #include "CLG_log.h" -/* For menu/popup icons etc etc. */ +/* For menu/popup icons etc. */ #include "UI_interface.h" #include "UI_resources.h" @@ -340,10 +342,10 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); int index = RNA_int_get(op->ptr, "collection_index"); - const bool extend = (win->eventstate->shift != 0); + const bool extend = (win->eventstate->modifier & KM_SHIFT) != 0; const bool toggle = RNA_boolean_get(op->ptr, "toggle"); - if (win->eventstate->alt != 0) { + if (win->eventstate->modifier & KM_ALT) { index += 10; } @@ -568,7 +570,7 @@ static bool ED_object_editmode_load_free_ex(Main *bmain, */ DEG_relations_tag_update(bmain); } - else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { + else if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { const Curve *cu = obedit->data; if (cu->editnurb == NULL) { return false; @@ -799,12 +801,16 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene); } - else if (ELEM(ob->type, OB_SURF, OB_CURVE)) { + else if (ELEM(ob->type, OB_SURF, OB_CURVES_LEGACY)) { ok = true; ED_curve_editnurb_make(ob); WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene); } + else if (ob->type == OB_CURVES) { + ok = true; + WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_CURVES, scene); + } if (ok) { DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); @@ -1019,7 +1025,7 @@ void ED_object_check_force_modifiers(Main *bmain, Scene *scene, Object *object) if (!md) { if (pd && (pd->shape == PFIELD_SHAPE_SURFACE) && !ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) { - if (ELEM(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) { + if (ELEM(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVES_LEGACY)) { ED_object_modifier_add(NULL, bmain, scene, object, NULL, eModifierType_Surface); } } @@ -1205,30 +1211,32 @@ static int object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEv /* set default settings from existing/stored settings */ { bAnimVizSettings *avs = &ob->avs; - - RNA_int_set(op->ptr, "start_frame", avs->path_sf); - RNA_int_set(op->ptr, "end_frame", avs->path_ef); + RNA_enum_set(op->ptr, "display_type", avs->path_type); + RNA_enum_set(op->ptr, "range", avs->path_range); } /* show popup dialog to allow editing of range... */ /* FIXME: hard-coded dimensions here are just arbitrary. */ - return WM_operator_props_dialog_popup(C, op, 200); + return WM_operator_props_dialog_popup(C, op, 270); } /* Calculate/recalculate whole paths (avs.path_sf to avs.path_ef) */ static int object_calculate_paths_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - int start = RNA_int_get(op->ptr, "start_frame"); - int end = RNA_int_get(op->ptr, "end_frame"); + short path_type = RNA_enum_get(op->ptr, "display_type"); + short path_range = RNA_enum_get(op->ptr, "range"); - /* set up path data for bones being calculated */ + /* set up path data for objects being calculated */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { - bAnimVizSettings *avs = &ob->avs; - - /* grab baking settings from operator settings */ - avs->path_sf = start; - avs->path_ef = end; + /* When operator is not invoked, dismiss the operator settings */ + if (op->flag & OP_IS_INVOKE) { + bAnimVizSettings *avs = &ob->avs; + /* grab baking settings from operator settings */ + avs->path_type = path_type; + avs->path_range = path_range; + } + animviz_motionpath_compute_range(ob, scene); /* verify that the selected object has the appropriate settings */ animviz_verify_motionpaths(op->reports, scene, ob, NULL); @@ -1247,9 +1255,9 @@ static int object_calculate_paths_exec(bContext *C, wmOperator *op) void OBJECT_OT_paths_calculate(wmOperatorType *ot) { /* identifiers */ - ot->name = "Calculate Object Paths"; + ot->name = "Calculate Object Motion Paths"; ot->idname = "OBJECT_OT_paths_calculate"; - ot->description = "Calculate motion paths for the selected objects"; + ot->description = "Generate motion paths for the selected objects"; /* api callbacks */ ot->invoke = object_calculate_paths_invoke; @@ -1260,24 +1268,18 @@ void OBJECT_OT_paths_calculate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_int(ot->srna, - "start_frame", - 1, - MINAFRAME, - MAXFRAME, - "Start", - "First frame to calculate object paths on", - MINFRAME, - MAXFRAME / 2.0); - RNA_def_int(ot->srna, - "end_frame", - 250, - MINAFRAME, - MAXFRAME, - "End", - "Last frame to calculate object paths on", - MINFRAME, - MAXFRAME / 2.0); + RNA_def_enum(ot->srna, + "display_type", + rna_enum_motionpath_display_type_items, + MOTIONPATH_TYPE_RANGE, + "Display type", + ""); + RNA_def_enum(ot->srna, + "range", + rna_enum_motionpath_range_items, + MOTIONPATH_RANGE_SCENE, + "Computation Range", + ""); } /** \} */ @@ -1296,13 +1298,19 @@ static bool object_update_paths_poll(bContext *C) return false; } -static int object_update_paths_exec(bContext *C, wmOperator *UNUSED(op)) +static int object_update_paths_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); if (scene == NULL) { return OPERATOR_CANCELLED; } + CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { + animviz_motionpath_compute_range(ob, scene); + /* verify that the selected object has the appropriate settings */ + animviz_verify_motionpaths(op->reports, scene, ob, NULL); + } + CTX_DATA_END; /* calculate the paths for objects that have them (and are tagged to get refreshed) */ ED_objects_recalculate_paths_selected(C, scene, OBJECT_PATH_CALC_RANGE_FULL); @@ -1423,7 +1431,7 @@ static int object_clear_paths_exec(bContext *C, wmOperator *op) /* operator callback/wrapper */ static int object_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if ((event->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) { + if ((event->modifier & KM_SHIFT) && !RNA_struct_property_is_set(op->ptr, "only_selected")) { RNA_boolean_set(op->ptr, "only_selected", true); } return object_clear_paths_exec(C, op); @@ -1453,46 +1461,6 @@ void OBJECT_OT_paths_clear(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Update Motion Paths Range from Scene Operator - * \{ */ - -static int object_update_paths_range_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Scene *scene = CTX_data_scene(C); - - /* Loop over all editable objects in scene. */ - CTX_DATA_BEGIN (C, Object *, ob, editable_objects) { - /* use Preview Range or Full Frame Range - whichever is in use */ - ob->avs.path_sf = PSFRA; - ob->avs.path_ef = PEFRA; - - /* tag for updates */ - DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - } - CTX_DATA_END; - - return OPERATOR_FINISHED; -} - -void OBJECT_OT_paths_range_update(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Update Range from Scene"; - ot->idname = "OBJECT_OT_paths_range_update"; - ot->description = "Update frame range for motion paths from the Scene's current frame range"; - - /* callbacks */ - ot->exec = object_update_paths_range_exec; - ot->poll = ED_operator_object_active_editable; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Object Shade Smooth/Flat Operator * \{ */ @@ -1548,7 +1516,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); changed = true; } - else if (ELEM(ob->type, OB_SURF, OB_CURVE)) { + else if (ELEM(ob->type, OB_SURF, OB_CURVES_LEGACY)) { BKE_curve_smooth_flag_set(ob->data, use_smooth); changed = true; } diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 338307dc8ca..dffbb3bedd5 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -342,7 +342,7 @@ static bool object_hook_index_array(Main *bmain, } return true; } - case OB_CURVE: + case OB_CURVES_LEGACY: case OB_SURF: ED_curve_editnurb_load(bmain, obedit); ED_curve_editnurb_make(obedit); @@ -447,7 +447,7 @@ static void object_hook_select(Object *ob, HookModifierData *hmd) else if (ob->type == OB_LATTICE) { select_editlattice_hook(ob, hmd); } - else if (ob->type == OB_CURVE) { + else if (ob->type == OB_CURVES_LEGACY) { select_editcurve_hook(ob, hmd); } else if (ob->type == OB_SURF) { diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 0aac5957c9d..135c76140c1 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -76,7 +76,6 @@ void OBJECT_OT_shade_flat(struct wmOperatorType *ot); void OBJECT_OT_paths_calculate(struct wmOperatorType *ot); void OBJECT_OT_paths_update(struct wmOperatorType *ot); void OBJECT_OT_paths_clear(struct wmOperatorType *ot); -void OBJECT_OT_paths_range_update(struct wmOperatorType *ot); void OBJECT_OT_paths_update_visible(struct wmOperatorType *ot); void OBJECT_OT_forcefield_toggle(struct wmOperatorType *ot); @@ -97,7 +96,7 @@ void OBJECT_OT_select_more(struct wmOperatorType *ot); void OBJECT_OT_select_less(struct wmOperatorType *ot); void OBJECT_OT_select_same_collection(struct wmOperatorType *ot); -/* object_add.c */ +/* object_add.cc */ void OBJECT_OT_add(struct wmOperatorType *ot); void OBJECT_OT_add_named(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index 509e496c39a..8e9e8558016 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -118,7 +118,7 @@ bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode) } } break; - case OB_CURVE: + case OB_CURVES_LEGACY: case OB_SURF: case OB_FONT: case OB_MBALL: @@ -143,7 +143,7 @@ bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode) } break; case OB_CURVES: - if (mode & (OB_MODE_SCULPT_CURVES)) { + if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT_CURVES)) { return true; } break; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 38a955dca0a..e0d25baec16 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -110,7 +110,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object * else if (ob->type == OB_MBALL) { BKE_displist_make_mball(depsgraph, scene_eval, ob_eval); } - else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { + else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) { BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false); } else if (ob->type == OB_GPENCIL) { @@ -757,7 +757,7 @@ static bool modifier_apply_obdata( } } } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) { Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); Curve *curve = ob->data; Curve *curve_eval = (Curve *)object_eval->data; diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 35f5ede270d..45ee4daa441 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -45,7 +45,6 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_paths_calculate); WM_operatortype_append(OBJECT_OT_paths_update); WM_operatortype_append(OBJECT_OT_paths_clear); - WM_operatortype_append(OBJECT_OT_paths_range_update); WM_operatortype_append(OBJECT_OT_paths_update_visible); WM_operatortype_append(OBJECT_OT_forcefield_toggle); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 8834941d083..3ecf86d14ed 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -169,7 +169,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) } } } - else if (ELEM(obedit->type, OB_SURF, OB_CURVE)) { + else if (ELEM(obedit->type, OB_SURF, OB_CURVES_LEGACY)) { ListBase *editnurb = object_editcurve_get(obedit); for (Nurb *nu = editnurb->first; nu != NULL; nu = nu->next) { @@ -341,7 +341,7 @@ EnumPropertyItem prop_clear_parent_types[] = { /* Helper for ED_object_parent_clear() - Remove deform-modifiers associated with parent */ static void object_remove_parent_deform_modifiers(Object *ob, const Object *par) { - if (ELEM(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVE)) { + if (ELEM(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVES_LEGACY)) { ModifierData *md, *mdn; /* assume that we only need to remove the first instance of matching deform modifier here */ @@ -363,7 +363,7 @@ static void object_remove_parent_deform_modifiers(Object *ob, const Object *par) free = true; } } - else if ((md->type == eModifierType_Curve) && (par->type == OB_CURVE)) { + else if ((md->type == eModifierType_Curve) && (par->type == OB_CURVES_LEGACY)) { CurveModifierData *cmd = (CurveModifierData *)md; if (cmd->object == par) { free = true; @@ -531,7 +531,7 @@ bool ED_object_parent_set(ReportList *reports, switch (partype) { case PAR_FOLLOW: case PAR_PATH_CONST: { - if (par->type != OB_CURVE) { + if (par->type != OB_CURVES_LEGACY) { return false; } Curve *cu = par->data; @@ -626,7 +626,7 @@ bool ED_object_parent_set(ReportList *reports, */ /* XXX currently this should only happen for meshes, curves, surfaces, * and lattices - this stuff isn't available for meta-balls yet. */ - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { + if (ELEM(ob->type, OB_MESH, OB_CURVES_LEGACY, OB_SURF, OB_FONT, OB_LATTICE)) { ModifierData *md; switch (partype) { @@ -968,7 +968,7 @@ static int parent_set_invoke_menu(bContext *C, wmOperatorType *ot) uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE); uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE_RELATIVE); } - else if (parent->type == OB_CURVE) { + else if (parent->type == OB_CURVES_LEGACY) { uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_CURVE); uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_FOLLOW); uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_PATH_CONST); @@ -1820,7 +1820,7 @@ static void single_obdata_users( ob->data, BKE_id_copy_ex(bmain, ob->data, NULL, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS)); break; - case OB_CURVE: + case OB_CURVES_LEGACY: case OB_SURF: case OB_FONT: ob->data = cu = ID_NEW_SET( @@ -2318,7 +2318,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op) BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); const bool success = BKE_lib_override_library_create( - bmain, scene, view_layer, NULL, id_root, &obact->id, NULL); + bmain, scene, view_layer, NULL, id_root, id_root, &obact->id, NULL); /* Remove the instance empty from this scene, the items now have an overridden collection * instead. */ diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc index 44e6fb10528..2e495ac6147 100644 --- a/source/blender/editors/object/object_remesh.cc +++ b/source/blender/editors/object/object_remesh.cc @@ -406,7 +406,7 @@ static int voxel_size_edit_modal(bContext *C, wmOperator *op, const wmEvent *eve d = cd->slow_mval[0] - mval[0]; } - if (event->ctrl) { + if (event->modifier & KM_CTRL) { /* Linear mode, enables jumping to any voxel size. */ d = d * 0.0005f; } diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index f017fea7cdf..9e82abf4d07 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -613,7 +613,7 @@ static int apply_objects_internal(bContext *C, OB_ARMATURE, OB_LATTICE, OB_MBALL, - OB_CURVE, + OB_CURVES_LEGACY, OB_SURF, OB_FONT, OB_GPENCIL)) { @@ -639,13 +639,13 @@ static int apply_objects_internal(bContext *C, } } - if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) { ID *obdata = ob->data; Curve *cu; cu = ob->data; - if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) { + if (((ob->type == OB_CURVES_LEGACY) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) { BKE_reportf( reports, RPT_ERROR, @@ -811,7 +811,7 @@ static int apply_objects_internal(bContext *C, MetaBall *mb = ob->data; BKE_mball_transform(mb, mat, do_props); } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) { Curve *cu = ob->data; scale = mat3_to_scale(rsmat); BKE_curve_transform_ex(cu, mat, true, do_props, scale); @@ -1209,7 +1209,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) do_inverse_offset = true; } } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) { Curve *cu = ob->data; if (centermode == ORIGIN_TO_CURSOR) { @@ -1223,7 +1223,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) } /* don't allow Z change if curve is 2D */ - if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) { + if ((ob->type == OB_CURVES_LEGACY) && !(cu->flag & CU_3D)) { cent[2] = 0.0; } @@ -1861,7 +1861,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const view3d_operator_needs_opengl(C); - const bool is_translate = (event->ctrl != 0); + const bool is_translate = event->modifier & KM_CTRL; const bool is_translate_init = is_translate && (xfd->is_translate != is_translate); if (event->type == MOUSEMOVE || is_translate_init) { diff --git a/source/blender/editors/object/object_utils.c b/source/blender/editors/object/object_utils.c index 19940fbb0fc..cb9c8a92abe 100644 --- a/source/blender/editors/object/object_utils.c +++ b/source/blender/editors/object/object_utils.c @@ -64,7 +64,7 @@ bool ED_object_calc_active_center_for_editmode(Object *obedit, break; } - case OB_CURVE: + case OB_CURVES_LEGACY: case OB_SURF: { Curve *cu = obedit->data; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index af9496263e7..fc815ebe682 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -4684,7 +4684,7 @@ static int brush_edit_init(bContext *C, wmOperator *op) bedit->ob = ob; bedit->edit = edit; - bedit->zfac = ED_view3d_calc_zfac(region->regiondata, min, NULL); + bedit->zfac = ED_view3d_calc_zfac(region->regiondata, min); /* cache view depths and settings for re-use */ PE_set_view3d_data(C, &bedit->data); @@ -4757,7 +4757,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) switch (pset->brushtype) { case PE_BRUSH_COMB: { - const float mval_f[2] = {dx, dy}; + const float xy_delta[2] = {dx, dy}; data.mval = mval; data.rad = pe_brush_size_get(scene, brush); @@ -4771,7 +4771,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) invert_m4_m4(ob->imat, ob->obmat); - ED_view3d_win_to_delta(region, mval_f, vec, bedit->zfac); + ED_view3d_win_to_delta(region, xy_delta, bedit->zfac, vec); data.dvec = vec; foreach_mouse_hit_key(&data, brush_comb, selected); @@ -4963,7 +4963,7 @@ static void brush_edit_apply_event(bContext *C, wmOperator *op, const wmEvent *e RNA_collection_add(op->ptr, "stroke", &itemptr); RNA_float_set_array(&itemptr, "mouse", mouse); - RNA_boolean_set(&itemptr, "pen_flip", event->shift != false); /* XXX hardcoded */ + RNA_boolean_set(&itemptr, "pen_flip", event->modifier & KM_SHIFT); /* XXX hardcoded */ /* apply */ brush_edit_apply(C, op, &itemptr); diff --git a/source/blender/editors/render/render_internal.cc b/source/blender/editors/render/render_internal.cc index 5308d4611e7..03c0f3977b7 100644 --- a/source/blender/editors/render/render_internal.cc +++ b/source/blender/editors/render/render_internal.cc @@ -618,6 +618,12 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec static void current_scene_update(void *rjv, Scene *scene) { RenderJob *rj = static_cast<RenderJob *>(rjv); + + if (rj->current_scene != scene) { + /* Image must be updated when rendered scene changes. */ + BKE_image_partial_update_mark_full_update(rj->image); + } + rj->current_scene = scene; rj->iuser.scene = scene; } @@ -1188,5 +1194,6 @@ void RENDER_OT_shutter_curve_preset(wmOperatorType *ot) ot->exec = render_shutter_curve_preset_exec; prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", ""); - RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ + RNA_def_property_translation_context(prop, + BLT_I18NCONTEXT_ID_CURVE_LEGACY); /* Abusing id_curve :/ */ } diff --git a/source/blender/editors/render/render_opengl.cc b/source/blender/editors/render/render_opengl.cc index 1ca2b01a2cb..be66e87f2e5 100644 --- a/source/blender/editors/render/render_opengl.cc +++ b/source/blender/editors/render/render_opengl.cc @@ -599,30 +599,30 @@ static int gather_frames_to_render_for_id(LibraryIDLinkCallbackData *cb_data) const ID_Type id_type = GS(id->name); switch (id_type) { /* Whitelist: */ - case ID_ME: /* Mesh */ - case ID_CU: /* Curve */ - case ID_MB: /* MetaBall */ - case ID_MA: /* Material */ - case ID_TE: /* Tex (Texture) */ - case ID_IM: /* Image */ - case ID_LT: /* Lattice */ - case ID_LA: /* Light */ - case ID_CA: /* Camera */ - case ID_KE: /* Key (shape key) */ - case ID_VF: /* VFont (Vector Font) */ - case ID_TXT: /* Text */ - case ID_SPK: /* Speaker */ - case ID_SO: /* Sound */ - case ID_AR: /* bArmature */ - case ID_NT: /* bNodeTree */ - case ID_PA: /* ParticleSettings */ - case ID_MC: /* MovieClip */ - case ID_MSK: /* Mask */ - case ID_LP: /* LightProbe */ - case ID_CV: /* Curves */ - case ID_PT: /* PointCloud */ - case ID_VO: /* Volume */ - case ID_SIM: /* Simulation */ + case ID_ME: /* Mesh */ + case ID_CU_LEGACY: /* Curve */ + case ID_MB: /* MetaBall */ + case ID_MA: /* Material */ + case ID_TE: /* Tex (Texture) */ + case ID_IM: /* Image */ + case ID_LT: /* Lattice */ + case ID_LA: /* Light */ + case ID_CA: /* Camera */ + case ID_KE: /* Key (shape key) */ + case ID_VF: /* VFont (Vector Font) */ + case ID_TXT: /* Text */ + case ID_SPK: /* Speaker */ + case ID_SO: /* Sound */ + case ID_AR: /* bArmature */ + case ID_NT: /* bNodeTree */ + case ID_PA: /* ParticleSettings */ + case ID_MC: /* MovieClip */ + case ID_MSK: /* Mask */ + case ID_LP: /* LightProbe */ + case ID_CV: /* Curves */ + case ID_PT: /* PointCloud */ + case ID_VO: /* Volume */ + case ID_SIM: /* Simulation */ break; /* Blacklist: */ diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc index 6aaf551a88a..eca30a6ac25 100644 --- a/source/blender/editors/render/render_preview.cc +++ b/source/blender/editors/render/render_preview.cc @@ -10,6 +10,7 @@ #include <cmath> #include <cstdlib> #include <cstring> +#include <list> #ifndef WIN32 # include <unistd.h> @@ -1370,89 +1371,73 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat ShaderPreview *sp = static_cast<ShaderPreview *>(customdata); if (sp->pr_method == PR_ICON_DEFERRED) { - PreviewImage *prv = static_cast<PreviewImage *>(sp->owner); - ImBuf *thumb; - char *deferred_data = static_cast<char *>(PRV_DEFERRED_DATA(prv)); - ThumbSource source = static_cast<ThumbSource>(deferred_data[0]); - char *path = &deferred_data[1]; - - // printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path); - - thumb = IMB_thumb_manage(path, THB_LARGE, source); - - if (thumb) { - /* PreviewImage assumes premultiplied alhpa... */ - IMB_premultiply_alpha(thumb); - - icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect); - IMB_freeImBuf(thumb); - } + BLI_assert_unreachable(); + return; } - else { - ID *id = sp->id; - short idtype = GS(id->name); - BLI_assert(id != nullptr); - - if (idtype == ID_IM) { - Image *ima = (Image *)id; - ImBuf *ibuf = nullptr; - ImageUser iuser; - BKE_imageuser_default(&iuser); + ID *id = sp->id; + short idtype = GS(id->name); - if (ima == nullptr) { - return; - } + BLI_assert(id != nullptr); - /* setup dummy image user */ - iuser.framenr = 1; - iuser.scene = sp->scene; - - /* NOTE(@elubie): this needs to be changed: here image is always loaded if not - * already there. Very expensive for large images. Need to find a way to - * only get existing `ibuf`. */ - ibuf = BKE_image_acquire_ibuf(ima, &iuser, nullptr); - if (ibuf == nullptr || (ibuf->rect == nullptr && ibuf->rect_float == nullptr)) { - BKE_image_release_ibuf(ima, ibuf, nullptr); - return; - } + if (idtype == ID_IM) { + Image *ima = (Image *)id; + ImBuf *ibuf = nullptr; + ImageUser iuser; + BKE_imageuser_default(&iuser); - icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); + if (ima == nullptr) { + return; + } - *do_update = true; + /* setup dummy image user */ + iuser.framenr = 1; + iuser.scene = sp->scene; + /* NOTE(@elubie): this needs to be changed: here image is always loaded if not + * already there. Very expensive for large images. Need to find a way to + * only get existing `ibuf`. */ + ibuf = BKE_image_acquire_ibuf(ima, &iuser, nullptr); + if (ibuf == nullptr || (ibuf->rect == nullptr && ibuf->rect_float == nullptr)) { BKE_image_release_ibuf(ima, ibuf, nullptr); + return; } - else if (idtype == ID_BR) { - Brush *br = (Brush *)id; - br->icon_imbuf = icon_preview_imbuf_from_brush(br); + icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); - memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(uint)); + *do_update = true; - if (!(br->icon_imbuf) || !(br->icon_imbuf->rect)) { - return; - } + BKE_image_release_ibuf(ima, ibuf, nullptr); + } + else if (idtype == ID_BR) { + Brush *br = (Brush *)id; - icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect); + br->icon_imbuf = icon_preview_imbuf_from_brush(br); - *do_update = true; - } - else if (idtype == ID_SCR) { - bScreen *screen = (bScreen *)id; + memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(uint)); - ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect); - *do_update = true; + if (!(br->icon_imbuf) || !(br->icon_imbuf->rect)) { + return; } - else { - /* re-use shader job */ - shader_preview_startjob(customdata, stop, do_update); - /* world is rendered with alpha=0, so it wasn't displayed - * this could be render option for sky to, for later */ - if (idtype == ID_WO) { - set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); - } + icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect); + + *do_update = true; + } + else if (idtype == ID_SCR) { + bScreen *screen = (bScreen *)id; + + ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect); + *do_update = true; + } + else { + /* re-use shader job */ + shader_preview_startjob(customdata, stop, do_update); + + /* world is rendered with alpha=0, so it wasn't displayed + * this could be render option for sky to, for later */ + if (idtype == ID_WO) { + set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); } } } @@ -1670,6 +1655,197 @@ static void icon_preview_endjob(void *customdata) } } +/** + * Background job to manage requests for deferred loading of previews from the hard drive. + * + * Launches a single job to manage all incoming preview requests. The job is kept running until all + * preview requests are done loading (or it's otherwise aborted, e.g. by closing Blender). + * + * Note that this will use the OS thumbnail cache, i.e. load a preview from there or add it if not + * there yet. These two cases may lead to different performance. + */ +class PreviewLoadJob { + struct RequestedPreview { + PreviewImage *preview; + /** Requested size. */ + eIconSizes icon_size; + }; + + /** The previews that are still to be loaded. */ + ThreadQueue *todo_queue_; /* RequestedPreview * */ + /** All unfinished preview requests, #update_fn() calls #finish_preview_request() on loaded + * previews and removes them from this list. Only access from the main thread! */ + std::list<struct RequestedPreview> requested_previews_; + + public: + PreviewLoadJob(); + ~PreviewLoadJob(); + + static PreviewLoadJob &ensure_job(wmWindowManager *, wmWindow *); + static void load_jobless(PreviewImage *, eIconSizes); + + void push_load_request(PreviewImage *, eIconSizes); + + private: + static void run_fn(void *, short *, short *, float *); + static void update_fn(void *); + static void end_fn(void *); + static void free_fn(void *); + + /** Mark a single requested preview as being done, remove the request. */ + static void finish_request(RequestedPreview &); +}; + +PreviewLoadJob::PreviewLoadJob() : todo_queue_(BLI_thread_queue_init()) +{ +} + +PreviewLoadJob::~PreviewLoadJob() +{ + BLI_thread_queue_free(todo_queue_); +} + +PreviewLoadJob &PreviewLoadJob::ensure_job(wmWindowManager *wm, wmWindow *win) +{ + wmJob *wm_job = WM_jobs_get(wm, win, nullptr, "Load Previews", 0, WM_JOB_TYPE_LOAD_PREVIEW); + + if (!WM_jobs_is_running(wm_job)) { + PreviewLoadJob *job_data = MEM_new<PreviewLoadJob>("PreviewLoadJobData"); + + WM_jobs_customdata_set(wm_job, job_data, free_fn); + WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW); + WM_jobs_callbacks(wm_job, run_fn, nullptr, update_fn, end_fn); + + WM_jobs_start(wm, wm_job); + } + + return *reinterpret_cast<PreviewLoadJob *>(WM_jobs_customdata_get(wm_job)); +} + +void PreviewLoadJob::load_jobless(PreviewImage *preview, const eIconSizes icon_size) +{ + PreviewLoadJob job_data{}; + + job_data.push_load_request(preview, icon_size); + + short stop = 0, do_update = 0; + float progress = 0; + run_fn(&job_data, &stop, &do_update, &progress); + update_fn(&job_data); + end_fn(&job_data); +} + +void PreviewLoadJob::push_load_request(PreviewImage *preview, const eIconSizes icon_size) +{ + BLI_assert(preview->tag & PRV_TAG_DEFFERED); + RequestedPreview requested_preview{}; + requested_preview.preview = preview; + requested_preview.icon_size = icon_size; + + preview->flag[icon_size] |= PRV_RENDERING; + /* Warn main thread code that this preview is being rendered and cannot be freed. */ + preview->tag |= PRV_TAG_DEFFERED_RENDERING; + + requested_previews_.push_back(requested_preview); + BLI_thread_queue_push(todo_queue_, &requested_previews_.back()); +} + +void PreviewLoadJob::run_fn(void *customdata, + short *stop, + short *do_update, + float *UNUSED(progress)) +{ + PreviewLoadJob *job_data = reinterpret_cast<PreviewLoadJob *>(customdata); + + IMB_thumb_locks_acquire(); + + while (RequestedPreview *request = reinterpret_cast<RequestedPreview *>( + BLI_thread_queue_pop_timeout(job_data->todo_queue_, 100))) { + if (*stop) { + break; + } + + PreviewImage *preview = request->preview; + + const char *deferred_data = static_cast<char *>(PRV_DEFERRED_DATA(preview)); + const ThumbSource source = static_cast<ThumbSource>(deferred_data[0]); + const char *path = &deferred_data[1]; + + // printf("loading deferred %d×%d preview for %s\n", request->sizex, request->sizey, path); + + IMB_thumb_path_lock(path); + ImBuf *thumb = IMB_thumb_manage(path, THB_LARGE, source); + IMB_thumb_path_unlock(path); + + if (thumb) { + /* PreviewImage assumes premultiplied alpha... */ + IMB_premultiply_alpha(thumb); + + icon_copy_rect(thumb, + preview->w[request->icon_size], + preview->h[request->icon_size], + preview->rect[request->icon_size]); + IMB_freeImBuf(thumb); + } + + *do_update = true; + } + + IMB_thumb_locks_release(); +} + +/* Only execute on the main thread! */ +void PreviewLoadJob::finish_request(RequestedPreview &request) +{ + PreviewImage *preview = request.preview; + + preview->tag &= ~PRV_TAG_DEFFERED_RENDERING; + BKE_previewimg_finish(preview, request.icon_size); + + BLI_assert_msg(BLI_thread_is_main(), + "Deferred releasing of preview images should only run on the main thread"); + if (preview->tag & PRV_TAG_DEFFERED_DELETE) { + BLI_assert(preview->tag & PRV_TAG_DEFFERED); + BKE_previewimg_deferred_release(preview); + } +} + +void PreviewLoadJob::update_fn(void *customdata) +{ + PreviewLoadJob *job_data = reinterpret_cast<PreviewLoadJob *>(customdata); + + for (auto request_it = job_data->requested_previews_.begin(); + request_it != job_data->requested_previews_.end();) { + RequestedPreview &requested = *request_it; + /* Skip items that are not done loading yet. */ + if (requested.preview->tag & PRV_TAG_DEFFERED_RENDERING) { + ++request_it; + continue; + } + finish_request(requested); + + /* Remove properly finished previews from the job data. */ + auto next_it = job_data->requested_previews_.erase(request_it); + request_it = next_it; + } +} + +void PreviewLoadJob::end_fn(void *customdata) +{ + PreviewLoadJob *job_data = reinterpret_cast<PreviewLoadJob *>(customdata); + + /* Finish any possibly remaining queued previews. */ + for (RequestedPreview &request : job_data->requested_previews_) { + finish_request(request); + } + job_data->requested_previews_.clear(); +} + +void PreviewLoadJob::free_fn(void *customdata) +{ + MEM_delete(reinterpret_cast<PreviewLoadJob *>(customdata)); +} + static void icon_preview_free(void *customdata) { IconPreview *ip = (IconPreview *)customdata; @@ -1698,8 +1874,19 @@ bool ED_preview_id_is_supported(const ID *id) } void ED_preview_icon_render( - const bContext *C, Scene *scene, ID *id, uint *rect, int sizex, int sizey) + const bContext *C, Scene *scene, PreviewImage *prv_img, ID *id, eIconSizes icon_size) { + /* Deferred loading of previews from the file system. */ + if (prv_img->tag & PRV_TAG_DEFFERED) { + if (prv_img->flag[icon_size] & PRV_RENDERING) { + /* Already in the queue, don't add it again. */ + return; + } + + PreviewLoadJob::load_jobless(prv_img, icon_size); + return; + } + IconPreview ip = {nullptr}; short stop = false, update = false; float progress = 0.0f; @@ -1716,7 +1903,10 @@ void ED_preview_icon_render( ip.id_copy = duplicate_ids(id, true); ip.active_object = CTX_data_active_object(C); - icon_preview_add_size(&ip, rect, sizex, sizey); + prv_img->flag[icon_size] |= PRV_RENDERING; + + icon_preview_add_size( + &ip, prv_img->rect[icon_size], prv_img->w[icon_size], prv_img->h[icon_size]); icon_preview_startjob_all_sizes(&ip, &stop, &update, &progress); @@ -1729,20 +1919,31 @@ void ED_preview_icon_render( } void ED_preview_icon_job( - const bContext *C, void *owner, ID *id, uint *rect, int sizex, int sizey, const bool delay) + const bContext *C, PreviewImage *prv_img, ID *id, eIconSizes icon_size, const bool delay) { - wmJob *wm_job; + /* Deferred loading of previews from the file system. */ + if (prv_img->tag & PRV_TAG_DEFFERED) { + if (prv_img->flag[icon_size] & PRV_RENDERING) { + /* Already in the queue, don't add it again. */ + return; + } + PreviewLoadJob &load_job = PreviewLoadJob::ensure_job(CTX_wm_manager(C), CTX_wm_window(C)); + load_job.push_load_request(prv_img, icon_size); + + return; + } + IconPreview *ip, *old_ip; ED_preview_ensure_dbase(); /* suspended start means it starts after 1 timer step, see WM_jobs_timer below */ - wm_job = WM_jobs_get(CTX_wm_manager(C), - CTX_wm_window(C), - owner, - "Icon Preview", - WM_JOB_EXCL_RENDER, - WM_JOB_TYPE_RENDER_PREVIEW); + wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), + CTX_wm_window(C), + prv_img, + "Icon Preview", + WM_JOB_EXCL_RENDER, + WM_JOB_TYPE_RENDER_PREVIEW); ip = MEM_cnew<IconPreview>("icon preview"); @@ -1757,20 +1958,14 @@ void ED_preview_icon_job( ip->depsgraph = CTX_data_ensure_evaluated_depsgraph(C); ip->scene = DEG_get_input_scene(ip->depsgraph); ip->active_object = CTX_data_active_object(C); - ip->owner = owner; + ip->owner = prv_img; ip->id = id; ip->id_copy = duplicate_ids(id, false); - icon_preview_add_size(ip, rect, sizex, sizey); + prv_img->flag[icon_size] |= PRV_RENDERING; - /* Special threading hack: - * warn main code that this preview is being rendered and cannot be freed... */ - { - PreviewImage *prv_img = static_cast<PreviewImage *>(owner); - if (prv_img->tag & PRV_TAG_DEFFERED) { - prv_img->tag |= PRV_TAG_DEFFERED_RENDERING; - } - } + icon_preview_add_size( + ip, prv_img->rect[icon_size], prv_img->w[icon_size], prv_img->h[icon_size]); /* setup job */ WM_jobs_customdata_set(wm_job, ip, icon_preview_free); diff --git a/source/blender/editors/render/render_shading.cc b/source/blender/editors/render/render_shading.cc index bad4208cf19..cd395674177 100644 --- a/source/blender/editors/render/render_shading.cc +++ b/source/blender/editors/render/render_shading.cc @@ -310,7 +310,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op)) } } } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) { Nurb *nu; ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data); @@ -411,7 +411,7 @@ static int material_slot_de_select(bContext *C, bool select) changed = EDBM_deselect_by_material(em, mat_nr_active, select); } } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) { ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data); Nurb *nu; BPoint *bp; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 95534d2a036..af84f6f99a9 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -3438,6 +3438,37 @@ bool ED_area_is_global(const ScrArea *area) return area->global != NULL; } +ScrArea *ED_area_find_under_cursor(const bContext *C, int spacetype, const int xy[2]) +{ + bScreen *screen = CTX_wm_screen(C); + wmWindow *win = CTX_wm_window(C); + + ScrArea *area = NULL; + + if (win->parent) { + /* If active window is a child, check itself first. */ + area = BKE_screen_find_area_xy(screen, spacetype, xy); + } + + if (!area) { + /* Check all windows except the active one. */ + int scr_pos[2]; + wmWindow *r_win = WM_window_find_under_cursor(win, xy, scr_pos); + if (r_win && r_win != win) { + win = r_win; + screen = WM_window_get_active_screen(win); + area = BKE_screen_find_area_xy(screen, spacetype, scr_pos); + } + } + + if (!area && !win->parent) { + /* If active window is a parent window, check itself last. */ + area = BKE_screen_find_area_xy(screen, spacetype, xy); + } + + return area; +} + ScrArea *ED_screen_areas_iter_first(const wmWindow *win, const bScreen *screen) { ScrArea *global_area = win->global_areas.areabase.first; diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index f43bc08151a..8a84f4cf079 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -77,8 +77,9 @@ void immDrawPixelsTexScaledFullSize(const IMMDrawPixelsTexState *state, * filtering results. Mipmaps can be used to get better results (i.e. #GL_LINEAR_MIPMAP_LINEAR), * so always use mipmaps when filtering. */ const bool use_mipmap = use_filter && ((draw_width < img_w) || (draw_height < img_h)); + const int mips = use_mipmap ? 9999 : 1; - GPUTexture *tex = GPU_texture_create_2d("immDrawPixels", img_w, img_h, 1, gpu_format, NULL); + GPUTexture *tex = GPU_texture_create_2d("immDrawPixels", img_w, img_h, mips, gpu_format, NULL); const bool use_float_data = ELEM(gpu_format, GPU_RGBA16F, GPU_RGB16F, GPU_R16F); eGPUDataFormat gpu_data_format = (use_float_data) ? GPU_DATA_FLOAT : GPU_DATA_UBYTE; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 7171aa7ac3b..ee3bc3cba76 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -585,7 +585,7 @@ bool ED_operator_uvmap(bContext *C) bool ED_operator_editsurfcurve(bContext *C) { Object *obedit = CTX_data_edit_object(C); - if (obedit && ELEM(obedit->type, OB_CURVE, OB_SURF)) { + if (obedit && ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { return NULL != ((Curve *)obedit->data)->editnurb; } return false; @@ -604,7 +604,7 @@ bool ED_operator_editsurfcurve_region_view3d(bContext *C) bool ED_operator_editcurve(bContext *C) { Object *obedit = CTX_data_edit_object(C); - if (obedit && obedit->type == OB_CURVE) { + if (obedit && obedit->type == OB_CURVES_LEGACY) { return NULL != ((Curve *)obedit->data)->editnurb; } return false; @@ -613,7 +613,7 @@ bool ED_operator_editcurve(bContext *C) bool ED_operator_editcurve_3d(bContext *C) { Object *obedit = CTX_data_edit_object(C); - if (obedit && obedit->type == OB_CURVE) { + if (obedit && obedit->type == OB_CURVES_LEGACY) { Curve *cu = (Curve *)obedit->data; return (cu->flag & CU_3D) && (NULL != cu->editnurb); @@ -1008,9 +1008,6 @@ static void actionzone_exit(wmOperator *op) static void actionzone_apply(bContext *C, wmOperator *op, int type) { wmWindow *win = CTX_wm_window(C); - sActionzoneData *sad = op->customdata; - - sad->modifier = RNA_int_get(op->ptr, "modifier"); wmEvent event; wm_event_init_from_window(win, &event); @@ -1026,7 +1023,7 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type) } event.val = KM_NOTHING; - event.is_repeat = false; + event.flag = 0; event.customdata = op->customdata; event.customdata_free = true; op->customdata = NULL; @@ -1051,6 +1048,7 @@ static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event) sad->az = az; sad->x = event->xy[0]; sad->y = event->xy[1]; + sad->modifier = RNA_int_get(op->ptr, "modifier"); /* region azone directly reacts on mouse clicks */ if (ELEM(sad->az->type, AZONE_REGION, AZONE_FULLSCREEN)) { @@ -1114,7 +1112,17 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) /* What area are we now in? */ ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->xy); - if (area == sad->sa1) { + if (sad->modifier == 1) { + /* Duplicate area into new window. */ + WM_cursor_set(win, WM_CURSOR_EDIT); + is_gesture = (delta_max > area_threshold); + } + else if (sad->modifier == 2) { + /* Swap areas. */ + WM_cursor_set(win, WM_CURSOR_SWAP_AREA); + is_gesture = true; + } + else if (area == sad->sa1) { /* Same area, so possible split. */ WM_cursor_set(win, SCREEN_DIR_IS_VERTICAL(sad->gesture_dir) ? WM_CURSOR_H_SPLIT : @@ -1320,8 +1328,9 @@ static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event) switch (event->type) { case MOUSEMOVE: - /* second area, for join */ - sad->sa2 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->xy); + /* Second area to swap with. */ + sad->sa2 = ED_area_find_under_cursor(C, SPACE_TYPE_ANY, event->xy); + WM_cursor_set(CTX_wm_window(C), (sad->sa2) ? WM_CURSOR_SWAP_AREA : WM_CURSOR_STOP); break; case LEFTMOUSE: /* release LMB */ if (event->val == KM_RELEASE) { diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 55099e2e750..59fbc3a64fb 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -9,6 +9,7 @@ set(INC ../../bmesh ../../depsgraph ../../draw + ../../functions ../../gpu ../../imbuf ../../makesdna @@ -24,11 +25,13 @@ set(INC ) set(SRC + curves_sculpt_ops.cc paint_cursor.c paint_curve.c paint_curve_undo.c paint_hide.c - paint_image.c + paint_image.cc + paint_image_ops_paint.cc paint_image_2d.c paint_image_2d_curve_mask.cc paint_image_proj.c @@ -66,6 +69,7 @@ set(SRC sculpt_undo.c sculpt_uv.c + curves_sculpt_intern.h paint_intern.h sculpt_intern.h ) @@ -75,5 +79,16 @@ set(LIB bf_blenlib ) +if(WITH_TBB) + list(APPEND INC_SYS + ${TBB_INCLUDE_DIRS} + ) + 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() +endif() blender_add_lib(bf_editor_sculpt_paint "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_intern.h b/source/blender/editors/sculpt_paint/curves_sculpt_intern.h new file mode 100644 index 00000000000..0d99e61192f --- /dev/null +++ b/source/blender/editors/sculpt_paint/curves_sculpt_intern.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +struct bContext; + +#ifdef __cplusplus +extern "C" { +#endif + +bool CURVES_SCULPT_mode_poll(struct bContext *C); +bool CURVES_SCULPT_mode_poll_view3d(struct bContext *C); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc new file mode 100644 index 00000000000..936226a03ed --- /dev/null +++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc @@ -0,0 +1,411 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_utildefines.h" + +#include "BKE_brush.h" +#include "BKE_context.h" +#include "BKE_curves.hh" +#include "BKE_paint.h" + +#include "WM_api.h" +#include "WM_toolsystem.h" + +#include "ED_curves_sculpt.h" +#include "ED_object.h" +#include "ED_screen.h" +#include "ED_view3d.h" + +#include "DEG_depsgraph.h" + +#include "DNA_brush_types.h" +#include "DNA_curves_types.h" +#include "DNA_screen_types.h" + +#include "RNA_access.h" + +#include "BLI_index_mask_ops.hh" +#include "BLI_math_vector.hh" + +#include "curves_sculpt_intern.h" +#include "paint_intern.h" + +/* -------------------------------------------------------------------- */ +/** \name Poll Functions + * \{ */ + +bool CURVES_SCULPT_mode_poll(bContext *C) +{ + Object *ob = CTX_data_active_object(C); + return ob && ob->mode & OB_MODE_SCULPT_CURVES; +} + +bool CURVES_SCULPT_mode_poll_view3d(bContext *C) +{ + if (!CURVES_SCULPT_mode_poll(C)) { + return false; + } + if (CTX_wm_region_view3d(C) == nullptr) { + return false; + } + return true; +} + +/** \} */ + +namespace blender::ed::sculpt_paint { + +using blender::bke::CurvesGeometry; + +/* -------------------------------------------------------------------- */ +/** \name * SCULPT_CURVES_OT_brush_stroke + * \{ */ + +struct StrokeExtension { + bool is_first; + float2 mouse_position; +}; + +/** + * Base class for stroke based operations in curves sculpt mode. + */ +class CurvesSculptStrokeOperation { + public: + virtual ~CurvesSculptStrokeOperation() = default; + virtual void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) = 0; +}; + +class DeleteOperation : public CurvesSculptStrokeOperation { + private: + float2 last_mouse_position_; + + public: + void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) + { + Scene &scene = *CTX_data_scene(C); + Object &object = *CTX_data_active_object(C); + ARegion *region = CTX_wm_region(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + + CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt; + Brush &brush = *BKE_paint_brush(&curves_sculpt.paint); + const float brush_radius = BKE_brush_size_get(&scene, &brush); + + float4x4 projection; + ED_view3d_ob_project_mat_get(rv3d, &object, projection.values); + + Curves &curves_id = *static_cast<Curves *>(object.data); + CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry); + MutableSpan<float3> positions = curves.positions(); + + const float2 mouse_start = stroke_extension.is_first ? stroke_extension.mouse_position : + last_mouse_position_; + const float2 mouse_end = stroke_extension.mouse_position; + + /* Find indices of curves that have to be removed. */ + Vector<int64_t> indices; + const IndexMask curves_to_remove = index_mask_ops::find_indices_based_on_predicate( + curves.curves_range(), 512, indices, [&](const int curve_i) { + const IndexRange point_range = curves.range_for_curve(curve_i); + for (const int segment_i : IndexRange(point_range.size() - 1)) { + const float3 pos1 = positions[point_range[segment_i]]; + const float3 pos2 = positions[point_range[segment_i + 1]]; + + float2 pos1_proj, pos2_proj; + ED_view3d_project_float_v2_m4(region, pos1, pos1_proj, projection.values); + ED_view3d_project_float_v2_m4(region, pos2, pos2_proj, projection.values); + + const float dist = dist_seg_seg_v2(pos1_proj, pos2_proj, mouse_start, mouse_end); + if (dist <= brush_radius) { + return true; + } + } + return false; + }); + + /* Just reset positions instead of actually removing the curves. This is just a prototype. */ + threading::parallel_for(curves_to_remove.index_range(), 512, [&](const IndexRange range) { + for (const int curve_i : curves_to_remove.slice(range)) { + for (const int point_i : curves.range_for_curve(curve_i)) { + positions[point_i] = {0.0f, 0.0f, 0.0f}; + } + } + }); + + curves.tag_positions_changed(); + DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY); + ED_region_tag_redraw(region); + + last_mouse_position_ = stroke_extension.mouse_position; + } +}; + +class MoveOperation : public CurvesSculptStrokeOperation { + private: + Vector<int64_t> points_to_move_indices_; + IndexMask points_to_move_; + float2 last_mouse_position_; + + public: + void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) + { + Scene &scene = *CTX_data_scene(C); + Object &object = *CTX_data_active_object(C); + ARegion *region = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + + CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt; + Brush &brush = *BKE_paint_brush(&curves_sculpt.paint); + const float brush_radius = BKE_brush_size_get(&scene, &brush); + + float4x4 projection; + ED_view3d_ob_project_mat_get(rv3d, &object, projection.values); + + Curves &curves_id = *static_cast<Curves *>(object.data); + CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry); + MutableSpan<float3> positions = curves.positions(); + + if (stroke_extension.is_first) { + /* Find point indices to move. */ + points_to_move_ = index_mask_ops::find_indices_based_on_predicate( + curves.points_range(), 512, points_to_move_indices_, [&](const int64_t point_i) { + const float3 position = positions[point_i]; + float2 screen_position; + ED_view3d_project_float_v2_m4(region, position, screen_position, projection.values); + const float distance = len_v2v2(screen_position, stroke_extension.mouse_position); + return distance <= brush_radius; + }); + } + else { + /* Move points based on mouse movement. */ + const float2 mouse_diff = stroke_extension.mouse_position - last_mouse_position_; + threading::parallel_for(points_to_move_.index_range(), 512, [&](const IndexRange range) { + for (const int point_i : points_to_move_.slice(range)) { + const float3 old_position = positions[point_i]; + float2 old_position_screen; + ED_view3d_project_float_v2_m4( + region, old_position, old_position_screen, projection.values); + const float2 new_position_screen = old_position_screen + mouse_diff; + float3 new_position; + ED_view3d_win_to_3d(v3d, region, old_position, new_position_screen, new_position); + positions[point_i] = new_position; + } + }); + + curves.tag_positions_changed(); + DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY); + ED_region_tag_redraw(region); + } + + last_mouse_position_ = stroke_extension.mouse_position; + } +}; + +static std::unique_ptr<CurvesSculptStrokeOperation> start_brush_operation(bContext *C, + wmOperator *UNUSED(op)) +{ + Scene &scene = *CTX_data_scene(C); + CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt; + Brush &brush = *BKE_paint_brush(&curves_sculpt.paint); + switch (brush.curves_sculpt_tool) { + case CURVES_SCULPT_TOOL_TEST1: + return std::make_unique<MoveOperation>(); + case CURVES_SCULPT_TOOL_TEST2: + return std::make_unique<DeleteOperation>(); + } + BLI_assert_unreachable(); + return {}; +} + +struct SculptCurvesBrushStrokeData { + std::unique_ptr<CurvesSculptStrokeOperation> operation; + PaintStroke *stroke; +}; + +static bool stroke_get_location(bContext *C, float out[3], const float mouse[2]) +{ + out[0] = mouse[0]; + out[1] = mouse[1]; + out[2] = 0; + UNUSED_VARS(C); + return true; +} + +static bool stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2]) +{ + UNUSED_VARS(C, op, mouse); + return true; +} + +static void stroke_update_step(bContext *C, + wmOperator *op, + PaintStroke *UNUSED(stroke), + PointerRNA *stroke_element) +{ + SculptCurvesBrushStrokeData *op_data = static_cast<SculptCurvesBrushStrokeData *>( + op->customdata); + + StrokeExtension stroke_extension; + RNA_float_get_array(stroke_element, "mouse", stroke_extension.mouse_position); + + if (!op_data->operation) { + stroke_extension.is_first = true; + op_data->operation = start_brush_operation(C, op); + } + else { + stroke_extension.is_first = false; + } + + op_data->operation->on_stroke_extended(C, stroke_extension); +} + +static void stroke_done(const bContext *C, PaintStroke *stroke) +{ + UNUSED_VARS(C, stroke); +} + +static int sculpt_curves_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + SculptCurvesBrushStrokeData *op_data = MEM_new<SculptCurvesBrushStrokeData>(__func__); + op_data->stroke = paint_stroke_new(C, + op, + stroke_get_location, + stroke_test_start, + stroke_update_step, + nullptr, + stroke_done, + event->type); + op->customdata = op_data; + + int return_value = op->type->modal(C, op, event); + if (return_value == OPERATOR_FINISHED) { + paint_stroke_free(C, op, op_data->stroke); + MEM_delete(op_data); + return OPERATOR_FINISHED; + } + + WM_event_add_modal_handler(C, op); + return OPERATOR_RUNNING_MODAL; +} + +static int sculpt_curves_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + SculptCurvesBrushStrokeData *op_data = static_cast<SculptCurvesBrushStrokeData *>( + op->customdata); + int return_value = paint_stroke_modal(C, op, event, op_data->stroke); + if (ELEM(return_value, OPERATOR_FINISHED, OPERATOR_CANCELLED)) { + MEM_delete(op_data); + } + return return_value; +} + +static void sculpt_curves_stroke_cancel(bContext *C, wmOperator *op) +{ + SculptCurvesBrushStrokeData *op_data = static_cast<SculptCurvesBrushStrokeData *>( + op->customdata); + paint_stroke_cancel(C, op, op_data->stroke); + MEM_delete(op_data); +} + +static void SCULPT_CURVES_OT_brush_stroke(struct wmOperatorType *ot) +{ + ot->name = "Stroke Curves Sculpt"; + ot->idname = "SCULPT_CURVES_OT_brush_stroke"; + ot->description = "Sculpt curves using a brush"; + + ot->invoke = sculpt_curves_stroke_invoke; + ot->modal = sculpt_curves_stroke_modal; + ot->cancel = sculpt_curves_stroke_cancel; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + paint_stroke_operator_properties(ot); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name * CURVES_OT_sculptmode_toggle + * \{ */ + +static bool curves_sculptmode_toggle_poll(bContext *C) +{ + Object *ob = CTX_data_active_object(C); + if (ob == nullptr) { + return false; + } + if (ob->type != OB_CURVES) { + return false; + } + return true; +} + +static void curves_sculptmode_enter(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->curves_sculpt); + CurvesSculpt *curves_sculpt = scene->toolsettings->curves_sculpt; + + ob->mode = OB_MODE_SCULPT_CURVES; + + paint_cursor_start(&curves_sculpt->paint, CURVES_SCULPT_mode_poll_view3d); +} + +static void curves_sculptmode_exit(bContext *C) +{ + Object *ob = CTX_data_active_object(C); + ob->mode = OB_MODE_OBJECT; +} + +static int curves_sculptmode_toggle_exec(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + const bool is_mode_set = ob->mode == OB_MODE_SCULPT_CURVES; + + if (is_mode_set) { + if (!ED_object_mode_compat_set(C, ob, OB_MODE_SCULPT_CURVES, op->reports)) { + return OPERATOR_CANCELLED; + } + } + + if (is_mode_set) { + curves_sculptmode_exit(C); + } + else { + curves_sculptmode_enter(C); + } + + WM_toolsystem_update_from_context_view3d(C); + WM_event_add_notifier(C, NC_SCENE | ND_MODE, nullptr); + return OPERATOR_CANCELLED; +} + +static void CURVES_OT_sculptmode_toggle(wmOperatorType *ot) +{ + ot->name = "Curve Sculpt Mode Toggle"; + ot->idname = "CURVES_OT_sculptmode_toggle"; + ot->description = "Enter/Exit sculpt mode for curves"; + + ot->exec = curves_sculptmode_toggle_exec; + ot->poll = curves_sculptmode_toggle_poll; + + ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER; +} + +} // namespace blender::ed::sculpt_paint + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name * Registration + * \{ */ + +void ED_operatortypes_sculpt_curves() +{ + using namespace blender::ed::sculpt_paint; + WM_operatortype_append(SCULPT_CURVES_OT_brush_stroke); + WM_operatortype_append(CURVES_OT_sculptmode_toggle); +} + +/** \} */ diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.cc index df9e2cf136f..0c73c2e1f43 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.cc @@ -6,10 +6,10 @@ * \brief Functions to paint images in 2D and 3D. */ -#include <float.h> -#include <math.h> -#include <stdio.h> -#include <string.h> +#include <cfloat> +#include <cmath> +#include <cstdio> +#include <cstring> #include "MEM_guardedalloc.h" @@ -67,6 +67,8 @@ #include "paint_intern.h" +extern "C" { + /** * This is a static resource for non-global access. * Maybe it should be exposed as part of the paint operation, @@ -84,7 +86,7 @@ void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr) imapaintpartial = *ippr; } -/* Imagepaint Partial Redraw & Dirty Region */ +/* Image paint Partial Redraw & Dirty Region. */ void ED_imapaint_clear_partial_redraw(void) { @@ -96,7 +98,7 @@ void imapaint_region_tiles( { int srcx = 0, srcy = 0; - IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h); + IMB_rectclip(ibuf, nullptr, &x, &y, &srcx, &srcy, &w, &h); *tw = ((x + w - 1) >> ED_IMAGE_UNDO_TILE_BITS); *th = ((y + h - 1) >> ED_IMAGE_UNDO_TILE_BITS); @@ -107,11 +109,11 @@ void imapaint_region_tiles( void ED_imapaint_dirty_region( Image *ima, ImBuf *ibuf, ImageUser *iuser, int x, int y, int w, int h, bool find_old) { - ImBuf *tmpibuf = NULL; + ImBuf *tmpibuf = nullptr; int tilex, tiley, tilew, tileh, tx, ty; int srcx = 0, srcy = 0; - IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h); + IMB_rectclip(ibuf, nullptr, &x, &y, &srcx, &srcy, &w, &h); if (w == 0 || h == 0) { return; @@ -128,7 +130,7 @@ void ED_imapaint_dirty_region( for (ty = tiley; ty <= tileh; ty++) { for (tx = tilex; tx <= tilew; tx++) { ED_image_paint_tile_push( - undo_tiles, ima, ibuf, &tmpibuf, iuser, tx, ty, NULL, NULL, false, find_old); + undo_tiles, ima, ibuf, &tmpibuf, iuser, tx, ty, nullptr, nullptr, false, find_old); } } @@ -169,17 +171,19 @@ void imapaint_image_update( BlurKernel *paint_new_blur_kernel(Brush *br, bool proj) { int i, j; - BlurKernel *kernel = MEM_mallocN(sizeof(BlurKernel), "blur kernel"); + BlurKernel *kernel = MEM_new<BlurKernel>("BlurKernel"); + float radius; int side; - eBlurKernelType type = br->blur_mode; + eBlurKernelType type = static_cast<eBlurKernelType>(br->blur_mode); if (proj) { radius = 0.5f; side = kernel->side = 2; kernel->side_squared = kernel->side * kernel->side; - kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data"); + kernel->wdata = static_cast<float *>( + MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data")); kernel->pixel_len = radius; } else { @@ -191,7 +195,8 @@ BlurKernel *paint_new_blur_kernel(Brush *br, bool proj) side = kernel->side = radius * 2 + 1; kernel->side_squared = kernel->side * kernel->side; - kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data"); + kernel->wdata = static_cast<float *>( + MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data")); kernel->pixel_len = br->blur_kernel_radius; } @@ -224,9 +229,9 @@ BlurKernel *paint_new_blur_kernel(Brush *br, bool proj) default: printf("unidentified kernel type, aborting\n"); - MEM_freeN(kernel->wdata); - MEM_freeN(kernel); - return NULL; + paint_delete_blur_kernel(kernel); + MEM_delete(kernel); + return nullptr; } return kernel; @@ -267,7 +272,7 @@ static bool image_paint_poll_ex(bContext *C, bool check_tool) SpaceImage *sima = CTX_wm_space_image(C); if (sima) { - if (sima->image != NULL && ID_IS_LINKED(sima->image)) { + if (sima->image != nullptr && ID_IS_LINKED(sima->image)) { return false; } ARegion *region = CTX_wm_region(C); @@ -281,7 +286,7 @@ static bool image_paint_poll_ex(bContext *C, bool check_tool) return false; } -static bool image_paint_poll(bContext *C) +bool image_paint_poll(bContext *C) { return image_paint_poll_ex(C, true); } @@ -307,24 +312,6 @@ static bool image_paint_2d_clone_poll(bContext *C) } /************************ paint operator ************************/ -typedef enum eTexPaintMode { - PAINT_MODE_2D, - PAINT_MODE_3D_PROJECT, -} eTexPaintMode; - -typedef struct PaintOperation { - eTexPaintMode mode; - - void *custom_paint; - - float prevmouse[2]; - float startmouse[2]; - double starttime; - - void *cursor; - ViewContext vc; -} PaintOperation; - bool paint_use_opacity_masking(Brush *brush) { return ((brush->flag & BRUSH_AIRBRUSH) || (brush->flag & BRUSH_DRAG_DOT) || @@ -369,7 +356,7 @@ void paint_brush_color_get(struct Scene *scene, break; } } - /* Gradient / Colorband colors are not considered PROP_COLOR_GAMMA. + /* Gradient / Color-band colors are not considered #PROP_COLOR_GAMMA. * Brush colors are expected to be in sRGB though. */ IMB_colormanagement_scene_linear_to_srgb_v3(color_gr); @@ -414,340 +401,11 @@ void paint_brush_exit_tex(Brush *brush) } } -static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customdata) -{ - PaintOperation *pop = (PaintOperation *)customdata; - - if (pop) { - GPU_line_smooth(true); - GPU_blend(GPU_BLEND_ALPHA); - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - - ARegion *region = pop->vc.region; - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - GPU_line_width(4.0); - immUniformColor4ub(0, 0, 0, 255); - - immBegin(GPU_PRIM_LINES, 2); - immVertex2i(pos, x, y); - immVertex2i( - pos, pop->startmouse[0] + region->winrct.xmin, pop->startmouse[1] + region->winrct.ymin); - immEnd(); - - GPU_line_width(2.0); - immUniformColor4ub(255, 255, 255, 255); - - immBegin(GPU_PRIM_LINES, 2); - immVertex2i(pos, x, y); - immVertex2i( - pos, pop->startmouse[0] + region->winrct.xmin, pop->startmouse[1] + region->winrct.ymin); - immEnd(); - - immUnbindProgram(); - - GPU_blend(GPU_BLEND_NONE); - GPU_line_smooth(false); - } -} - -static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const float mouse[2]) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene = CTX_data_scene(C); - ToolSettings *settings = scene->toolsettings; - PaintOperation *pop = MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */ - Brush *brush = BKE_paint_brush(&settings->imapaint.paint); - int mode = RNA_enum_get(op->ptr, "mode"); - ED_view3d_viewcontext_init(C, &pop->vc, depsgraph); - - copy_v2_v2(pop->prevmouse, mouse); - copy_v2_v2(pop->startmouse, mouse); - - /* initialize from context */ - if (CTX_wm_region_view3d(C)) { - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - bool uvs, mat, tex, stencil; - if (!ED_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, &stencil)) { - ED_paint_data_warning(op->reports, uvs, mat, tex, stencil); - MEM_freeN(pop); - WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); - return NULL; - } - pop->mode = PAINT_MODE_3D_PROJECT; - pop->custom_paint = paint_proj_new_stroke(C, ob, mouse, mode); - } - else { - pop->mode = PAINT_MODE_2D; - pop->custom_paint = paint_2d_new_stroke(C, op, mode); - } - - if (!pop->custom_paint) { - MEM_freeN(pop); - return NULL; - } - - if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) { - pop->cursor = WM_paint_cursor_activate( - SPACE_TYPE_ANY, RGN_TYPE_ANY, image_paint_poll, gradient_draw_line, pop); - } - - settings->imapaint.flag |= IMAGEPAINT_DRAWING; - ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D); - - return pop; -} - -static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr) -{ - PaintOperation *pop = paint_stroke_mode_data(stroke); - Scene *scene = CTX_data_scene(C); - ToolSettings *toolsettings = CTX_data_tool_settings(C); - UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings; - Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint); - - float alphafac = (brush->flag & BRUSH_ACCUMULATE) ? ups->overlap_factor : 1.0f; - - /* initial brush values. Maybe it should be considered moving these to stroke system */ - float startalpha = BKE_brush_alpha_get(scene, brush); - - float mouse[2]; - float pressure; - float size; - float distance = paint_stroke_distance_get(stroke); - int eraser; - - RNA_float_get_array(itemptr, "mouse", mouse); - pressure = RNA_float_get(itemptr, "pressure"); - eraser = RNA_boolean_get(itemptr, "pen_flip"); - size = RNA_float_get(itemptr, "size"); - - /* stroking with fill tool only acts on stroke end */ - if (brush->imagepaint_tool == PAINT_TOOL_FILL) { - copy_v2_v2(pop->prevmouse, mouse); - return; - } - - if (BKE_brush_use_alpha_pressure(brush)) { - BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure * alphafac)); - } - else { - BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * alphafac)); - } - - if ((brush->flag & BRUSH_DRAG_DOT) || (brush->flag & BRUSH_ANCHORED)) { - UndoStack *ustack = CTX_wm_manager(C)->undo_stack; - ED_image_undo_restore(ustack->step_init); - } - - if (pop->mode == PAINT_MODE_3D_PROJECT) { - paint_proj_stroke( - C, pop->custom_paint, pop->prevmouse, mouse, eraser, pressure, distance, size); - } - else { - paint_2d_stroke(pop->custom_paint, pop->prevmouse, mouse, eraser, pressure, distance, size); - } - - copy_v2_v2(pop->prevmouse, mouse); - - /* restore brush values */ - BKE_brush_alpha_set(scene, brush, startalpha); -} - -static void paint_stroke_redraw(const bContext *C, struct PaintStroke *stroke, bool final) -{ - PaintOperation *pop = paint_stroke_mode_data(stroke); - - if (pop->mode == PAINT_MODE_3D_PROJECT) { - paint_proj_redraw(C, pop->custom_paint, final); - } - else { - paint_2d_redraw(C, pop->custom_paint, final); - } -} - -static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke) -{ - Scene *scene = CTX_data_scene(C); - ToolSettings *toolsettings = scene->toolsettings; - PaintOperation *pop = paint_stroke_mode_data(stroke); - Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint); - - toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING; - - if (brush->imagepaint_tool == PAINT_TOOL_FILL) { - if (brush->flag & BRUSH_USE_GRADIENT) { - if (pop->mode == PAINT_MODE_2D) { - paint_2d_gradient_fill(C, brush, pop->startmouse, pop->prevmouse, pop->custom_paint); - } - else { - paint_proj_stroke(C, - pop->custom_paint, - pop->startmouse, - pop->prevmouse, - paint_stroke_flipped(stroke), - 1.0, - 0.0, - BKE_brush_size_get(scene, brush)); - /* two redraws, one for GPU update, one for notification */ - paint_proj_redraw(C, pop->custom_paint, false); - paint_proj_redraw(C, pop->custom_paint, true); - } - } - else { - if (pop->mode == PAINT_MODE_2D) { - float color[3]; - if (paint_stroke_inverted(stroke)) { - srgb_to_linearrgb_v3_v3(color, BKE_brush_secondary_color_get(scene, brush)); - } - else { - srgb_to_linearrgb_v3_v3(color, BKE_brush_color_get(scene, brush)); - } - paint_2d_bucket_fill(C, color, brush, pop->startmouse, pop->prevmouse, pop->custom_paint); - } - else { - paint_proj_stroke(C, - pop->custom_paint, - pop->startmouse, - pop->prevmouse, - paint_stroke_flipped(stroke), - 1.0, - 0.0, - BKE_brush_size_get(scene, brush)); - /* two redraws, one for GPU update, one for notification */ - paint_proj_redraw(C, pop->custom_paint, false); - paint_proj_redraw(C, pop->custom_paint, true); - } - } - } - if (pop->mode == PAINT_MODE_3D_PROJECT) { - paint_proj_stroke_done(pop->custom_paint); - } - else { - paint_2d_stroke_done(pop->custom_paint); - } - - if (pop->cursor) { - WM_paint_cursor_end(pop->cursor); - } - - ED_image_undo_push_end(); - - /* duplicate warning, see texpaint_init */ -#if 0 - if (pop->s.warnmultifile) { - BKE_reportf(op->reports, - RPT_WARNING, - "Image requires 4 color channels to paint: %s", - pop->s.warnmultifile); - } - if (pop->s.warnpackedfile) { - BKE_reportf(op->reports, - RPT_WARNING, - "Packed MultiLayer files cannot be painted: %s", - pop->s.warnpackedfile); - } -#endif - MEM_freeN(pop); -} - -static bool paint_stroke_test_start(bContext *C, wmOperator *op, const float mouse[2]) -{ - PaintOperation *pop; - - /* TODO: Should avoid putting this here. Instead, last position should be requested - * from stroke system. */ - - if (!(pop = texture_paint_init(C, op, mouse))) { - return false; - } - - paint_stroke_set_mode_data(op->customdata, pop); - - return true; -} - -static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - int retval; - - op->customdata = paint_stroke_new(C, - op, - NULL, - paint_stroke_test_start, - paint_stroke_update_step, - paint_stroke_redraw, - paint_stroke_done, - event->type); - - if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) { - paint_stroke_free(C, op); - return OPERATOR_FINISHED; - } - /* add modal handler */ - WM_event_add_modal_handler(C, op); - - OPERATOR_RETVAL_CHECK(retval); - BLI_assert(retval == OPERATOR_RUNNING_MODAL); - - return OPERATOR_RUNNING_MODAL; -} - -static int paint_exec(bContext *C, wmOperator *op) -{ - PropertyRNA *strokeprop; - PointerRNA firstpoint; - float mouse[2]; - - strokeprop = RNA_struct_find_property(op->ptr, "stroke"); - - if (!RNA_property_collection_lookup_int(op->ptr, strokeprop, 0, &firstpoint)) { - return OPERATOR_CANCELLED; - } - - RNA_float_get_array(&firstpoint, "mouse", mouse); - - op->customdata = paint_stroke_new(C, - op, - NULL, - paint_stroke_test_start, - paint_stroke_update_step, - paint_stroke_redraw, - paint_stroke_done, - 0); - /* frees op->customdata */ - return paint_stroke_exec(C, op); -} - -void PAINT_OT_image_paint(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Image Paint"; - ot->idname = "PAINT_OT_image_paint"; - ot->description = "Paint a stroke into the image"; - - /* api callbacks */ - ot->invoke = paint_invoke; - ot->modal = paint_stroke_modal; - ot->exec = paint_exec; - ot->poll = image_paint_poll; - ot->cancel = paint_stroke_cancel; - - /* flags */ - ot->flag = OPTYPE_BLOCKING; - - paint_stroke_operator_properties(ot); -} - bool get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy) { ScrArea *area = CTX_wm_area(C); if (area && area->spacetype == SPACE_IMAGE) { - SpaceImage *sima = area->spacedata.first; + SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first); if (sima->mode == SI_MODE_PAINT) { ARegion *region = CTX_wm_region(C); ED_space_image_get_zoom(sima, region, zoomx, zoomy); @@ -768,8 +426,8 @@ static void toggle_paint_cursor(Scene *scene, bool enable) Paint *p = &settings->imapaint.paint; if (p->paint_cursor && !enable) { - WM_paint_cursor_end(p->paint_cursor); - p->paint_cursor = NULL; + WM_paint_cursor_end(static_cast<wmPaintCursor *>(p->paint_cursor)); + p->paint_cursor = nullptr; paint_cursor_delete_textures(); } else if (enable) { @@ -807,10 +465,10 @@ void ED_space_image_paint_update(Main *bmain, wmWindowManager *wm, Scene *scene) /************************ grab clone operator ************************/ -typedef struct GrabClone { +struct GrabClone { float startoffset[2]; int startx, starty; -} GrabClone; +}; static void grab_clone_apply(bContext *C, wmOperator *op) { @@ -834,7 +492,7 @@ static int grab_clone_invoke(bContext *C, wmOperator *op, const wmEvent *event) Brush *brush = image_paint_brush(C); GrabClone *cmv; - cmv = MEM_callocN(sizeof(GrabClone), "GrabClone"); + cmv = MEM_new<GrabClone>("GrabClone"); copy_v2_v2(cmv->startoffset, brush->clone.offset); cmv->startx = event->xy[0]; cmv->starty = event->xy[1]; @@ -849,7 +507,7 @@ static int grab_clone_modal(bContext *C, wmOperator *op, const wmEvent *event) { Brush *brush = image_paint_brush(C); ARegion *region = CTX_wm_region(C); - GrabClone *cmv = op->customdata; + GrabClone *cmv = static_cast<GrabClone *>(op->customdata); float startfx, startfy, fx, fy, delta[2]; int xmin = region->winrct.xmin, ymin = region->winrct.ymin; @@ -880,7 +538,8 @@ static int grab_clone_modal(bContext *C, wmOperator *op, const wmEvent *event) static void grab_clone_cancel(bContext *UNUSED(C), wmOperator *op) { - MEM_freeN(op->customdata); + GrabClone *cmv = static_cast<GrabClone *>(op->customdata); + MEM_delete(cmv); } void PAINT_OT_grab_clone(wmOperatorType *ot) @@ -904,7 +563,7 @@ void PAINT_OT_grab_clone(wmOperatorType *ot) RNA_def_float_vector(ot->srna, "delta", 2, - NULL, + nullptr, -FLT_MAX, FLT_MAX, "Delta", @@ -914,12 +573,12 @@ void PAINT_OT_grab_clone(wmOperatorType *ot) } /******************** sample color operator ********************/ -typedef struct { +struct SampleColorData { bool show_cursor; short launch_event; float initcolor[3]; bool sample_palette; -} SampleColorData; +}; static void sample_color_update_header(SampleColorData *data, bContext *C) { @@ -973,7 +632,7 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event Scene *scene = CTX_data_scene(C); Paint *paint = BKE_paint_get_active_from_context(C); Brush *brush = BKE_paint_brush(paint); - SampleColorData *data = MEM_mallocN(sizeof(SampleColorData), "sample color custom data"); + SampleColorData *data = MEM_new<SampleColorData>("sample color custom data"); ARegion *region = CTX_wm_region(C); wmWindow *win = CTX_wm_window(C); @@ -1009,7 +668,7 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event) { Scene *scene = CTX_data_scene(C); - SampleColorData *data = op->customdata; + SampleColorData *data = static_cast<SampleColorData *>(op->customdata); Paint *paint = BKE_paint_get_active_from_context(C); Brush *brush = BKE_paint_brush(paint); @@ -1023,8 +682,8 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event) RNA_boolean_set(op->ptr, "palette", true); } WM_cursor_modal_restore(CTX_wm_window(C)); - MEM_freeN(data); - ED_workspace_status_text(C, NULL); + MEM_delete(data); + ED_workspace_status_text(C, nullptr); return OPERATOR_FINISHED; } @@ -1083,25 +742,26 @@ void PAINT_OT_sample_color(wmOperatorType *ot) /* properties */ PropertyRNA *prop; - prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "", 0, 16384); - RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); + prop = RNA_def_int_vector( + ot->srna, "location", 2, nullptr, 0, INT_MAX, "Location", "", 0, 16384); + RNA_def_property_flag(prop, static_cast<PropertyFlag>(PROP_SKIP_SAVE | PROP_HIDDEN)); - RNA_def_boolean(ot->srna, "merged", 0, "Sample Merged", "Sample the output display color"); - RNA_def_boolean(ot->srna, "palette", 0, "Add to Palette", ""); + RNA_def_boolean(ot->srna, "merged", false, "Sample Merged", "Sample the output display color"); + RNA_def_boolean(ot->srna, "palette", false, "Add to Palette", ""); } /******************** texture paint toggle operator ********************/ void ED_object_texture_paint_mode_enter_ex(Main *bmain, Scene *scene, Object *ob) { - Image *ima = NULL; + Image *ima = nullptr; ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; /* This has to stay here to regenerate the texture paint * cache in case we are loading a file */ BKE_texpaint_slots_refresh_object(scene, ob); - ED_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + ED_paint_proj_mesh_data_check(scene, ob, nullptr, nullptr, nullptr, nullptr); /* entering paint mode also sets image to editors */ if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) { @@ -1117,11 +777,11 @@ void ED_object_texture_paint_mode_enter_ex(Main *bmain, Scene *scene, Object *ob } if (ima) { - wmWindowManager *wm = bmain->wm.first; - for (wmWindow *win = wm->windows.first; win; win = win->next) { + wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { const bScreen *screen = WM_window_get_active_screen(win); - for (ScrArea *area = screen->areabase.first; area; area = area->next) { - SpaceLink *sl = area->spacedata.first; + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first); if (sl->spacetype == SPACE_IMAGE) { SpaceImage *sima = (SpaceImage *)sl; @@ -1142,12 +802,12 @@ void ED_object_texture_paint_mode_enter_ex(Main *bmain, Scene *scene, Object *ob if (U.glreslimit != 0) { BKE_image_free_all_gputextures(bmain); } - BKE_image_paint_set_mipmap(bmain, 0); + BKE_image_paint_set_mipmap(bmain, false); toggle_paint_cursor(scene, true); Mesh *me = BKE_mesh_from_object(ob); - BLI_assert(me != NULL); + BLI_assert(me != nullptr); DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE); WM_main_add_notifier(NC_SCENE | ND_MODE, scene); } @@ -1167,11 +827,11 @@ void ED_object_texture_paint_mode_exit_ex(Main *bmain, Scene *scene, Object *ob) if (U.glreslimit != 0) { BKE_image_free_all_gputextures(bmain); } - BKE_image_paint_set_mipmap(bmain, 1); + BKE_image_paint_set_mipmap(bmain, true); toggle_paint_cursor(scene, false); Mesh *me = BKE_mesh_from_object(ob); - BLI_assert(me != NULL); + BLI_assert(me != nullptr); DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE); WM_main_add_notifier(NC_SCENE | ND_MODE, scene); } @@ -1187,7 +847,7 @@ void ED_object_texture_paint_mode_exit(bContext *C) static bool texture_paint_toggle_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - if (ob == NULL || ob->type != OB_MESH) { + if (ob == nullptr || ob->type != OB_MESH) { return false; } if (!ob->data || ID_IS_LINKED(ob->data)) { @@ -1207,7 +867,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) const bool is_mode_set = (ob->mode & mode_flag) != 0; if (!is_mode_set) { - if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) { + if (!ED_object_mode_compat_set(C, ob, static_cast<eObjectMode>(mode_flag), op->reports)) { return OPERATOR_CANCELLED; } } @@ -1274,7 +934,7 @@ static bool brush_colors_flip_poll(bContext *C) } else { Object *ob = CTX_data_active_object(C); - if (ob != NULL) { + if (ob != nullptr) { if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT | OB_MODE_SCULPT)) { return true; } @@ -1310,8 +970,8 @@ void ED_imapaint_bucket_fill(struct bContext *C, ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D); - const float mouse_init[2] = {mouse[0], mouse[1]}; - paint_2d_bucket_fill(C, color, NULL, mouse_init, NULL, NULL); + const float mouse_init[2] = {static_cast<float>(mouse[0]), static_cast<float>(mouse[1])}; + paint_2d_bucket_fill(C, color, nullptr, mouse_init, nullptr, nullptr); ED_image_undo_push_end(); @@ -1349,3 +1009,4 @@ bool mask_paint_poll(bContext *C) { return BKE_paint_select_elem_test(CTX_data_active_object(C)); } +} diff --git a/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc b/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc index 64115f7c6eb..f5657b004e2 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc +++ b/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc @@ -53,6 +53,7 @@ static void update_curve_mask(CurveMaskCache *curve_mask_cache, { BLI_assert(curve_mask_cache->curve_mask != nullptr); int offset = (int)floorf(diameter / 2.0f); + int clamped_radius = max_ff(radius, 1.0); unsigned short *m = curve_mask_cache->curve_mask; @@ -76,7 +77,7 @@ static void update_curve_mask(CurveMaskCache *curve_mask_cache, pixel_xy[1] = static_cast<float>(y) + aa_offset; for (int j = 0; j < aa_samples; j++) { const float len = len_v2v2(pixel_xy, bpos); - const int sample_index = min_ii((len / radius) * CurveSamplesBaseLen, + const int sample_index = min_ii((len / clamped_radius) * CurveSamplesBaseLen, CurveSamplesLen - 1); const float sample_weight = curve_mask_cache->sampled_curve[sample_index]; diff --git a/source/blender/editors/sculpt_paint/paint_image_ops_paint.cc b/source/blender/editors/sculpt_paint/paint_image_ops_paint.cc new file mode 100644 index 00000000000..786fcc47526 --- /dev/null +++ b/source/blender/editors/sculpt_paint/paint_image_ops_paint.cc @@ -0,0 +1,531 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2001-2002 NaN Holding BV. All rights reserved. */ + +/** \file + * \ingroup edsculpt + * \brief Painting operator to paint in 2D and 3D. + */ + +#include "DNA_brush_types.h" +#include "DNA_color_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" + +#include "BKE_brush.h" +#include "BKE_context.h" +#include "BKE_paint.h" +#include "BKE_undo_system.h" + +#include "DEG_depsgraph.h" + +#include "ED_paint.h" +#include "ED_view3d.h" + +#include "GPU_immediate.h" +#include "GPU_state.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_message.h" +#include "WM_toolsystem.h" +#include "WM_types.h" + +#include "paint_intern.h" + +namespace blender::ed::sculpt_paint::image::ops::paint { + +/** + * Interface to use the same painting operator for 3D and 2D painting. Interface removes the + * differences between the actual calls that are being performed. + */ +class AbstractPaintMode { + public: + virtual ~AbstractPaintMode() = default; + virtual void *paint_new_stroke( + bContext *C, wmOperator *op, Object *ob, const float mouse[2], int mode) = 0; + virtual void paint_stroke(bContext *C, + void *stroke_handle, + float prev_mouse[2], + float mouse[2], + int eraser, + float pressure, + float distance, + float size) = 0; + + virtual void paint_stroke_redraw(const bContext *C, void *stroke_handle, bool final) = 0; + virtual void paint_stroke_done(void *stroke_handle) = 0; + virtual void paint_gradient_fill(const bContext *C, + const Scene *scene, + Brush *brush, + struct PaintStroke *stroke, + void *stroke_handle, + float mouse_start[2], + float mouse_end[2]) = 0; + virtual void paint_bucket_fill(const bContext *C, + const Scene *scene, + Brush *brush, + struct PaintStroke *stroke, + void *stroke_handle, + float mouse_start[2], + float mouse_end[2]) = 0; +}; + +class ImagePaintMode : public AbstractPaintMode { + public: + void *paint_new_stroke(bContext *C, + wmOperator *op, + Object *UNUSED(ob), + const float UNUSED(mouse[2]), + int mode) override + { + return paint_2d_new_stroke(C, op, mode); + } + + void paint_stroke(bContext *UNUSED(C), + void *stroke_handle, + float prev_mouse[2], + float mouse[2], + int eraser, + float pressure, + float distance, + float size) override + { + paint_2d_stroke(stroke_handle, prev_mouse, mouse, eraser, pressure, distance, size); + } + + void paint_stroke_redraw(const bContext *C, void *stroke_handle, bool final) override + { + paint_2d_redraw(C, stroke_handle, final); + } + + void paint_stroke_done(void *stroke_handle) override + { + paint_2d_stroke_done(stroke_handle); + } + + void paint_gradient_fill(const bContext *C, + const Scene *UNUSED(scene), + Brush *brush, + struct PaintStroke *UNUSED(stroke), + void *stroke_handle, + float mouse_start[2], + float mouse_end[2]) override + { + paint_2d_gradient_fill(C, brush, mouse_start, mouse_end, stroke_handle); + } + + void paint_bucket_fill(const bContext *C, + const Scene *scene, + Brush *brush, + struct PaintStroke *stroke, + void *stroke_handle, + float mouse_start[2], + float mouse_end[2]) override + { + float color[3]; + if (paint_stroke_inverted(stroke)) { + srgb_to_linearrgb_v3_v3(color, BKE_brush_secondary_color_get(scene, brush)); + } + else { + srgb_to_linearrgb_v3_v3(color, BKE_brush_color_get(scene, brush)); + } + paint_2d_bucket_fill(C, color, brush, mouse_start, mouse_end, stroke_handle); + } +}; + +class ProjectionPaintMode : public AbstractPaintMode { + public: + void *paint_new_stroke( + bContext *C, wmOperator *UNUSED(op), Object *ob, const float mouse[2], int mode) override + { + return paint_proj_new_stroke(C, ob, mouse, mode); + } + + void paint_stroke(bContext *C, + void *stroke_handle, + float prev_mouse[2], + float mouse[2], + int eraser, + float pressure, + float distance, + float size) override + { + paint_proj_stroke(C, stroke_handle, prev_mouse, mouse, eraser, pressure, distance, size); + }; + + void paint_stroke_redraw(const bContext *C, void *stroke_handle, bool final) override + { + paint_proj_redraw(C, stroke_handle, final); + } + + void paint_stroke_done(void *stroke_handle) override + { + paint_proj_stroke_done(stroke_handle); + } + + void paint_gradient_fill(const bContext *C, + const Scene *scene, + Brush *brush, + struct PaintStroke *stroke, + void *stroke_handle, + float mouse_start[2], + float mouse_end[2]) override + { + paint_fill(C, scene, brush, stroke, stroke_handle, mouse_start, mouse_end); + } + + void paint_bucket_fill(const bContext *C, + const Scene *scene, + Brush *brush, + struct PaintStroke *stroke, + void *stroke_handle, + float mouse_start[2], + float mouse_end[2]) override + { + paint_fill(C, scene, brush, stroke, stroke_handle, mouse_start, mouse_end); + } + + private: + void paint_fill(const bContext *C, + const Scene *scene, + Brush *brush, + struct PaintStroke *stroke, + void *stroke_handle, + float mouse_start[2], + float mouse_end[2]) + { + paint_proj_stroke(C, + stroke_handle, + mouse_start, + mouse_end, + paint_stroke_flipped(stroke), + 1.0, + 0.0, + BKE_brush_size_get(scene, brush)); + /* two redraws, one for GPU update, one for notification */ + paint_proj_redraw(C, stroke_handle, false); + paint_proj_redraw(C, stroke_handle, true); + } +}; + +struct PaintOperation { + AbstractPaintMode *mode = nullptr; + + void *stroke_handle = nullptr; + + float prevmouse[2] = {0.0f, 0.0f}; + float startmouse[2] = {0.0f, 0.0f}; + double starttime = 0.0; + + wmPaintCursor *cursor = nullptr; + ViewContext vc = {nullptr}; + + PaintOperation() = default; + ~PaintOperation() + { + MEM_delete(mode); + mode = nullptr; + + if (cursor) { + WM_paint_cursor_end(cursor); + cursor = nullptr; + } + } +}; + +static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customdata) +{ + PaintOperation *pop = (PaintOperation *)customdata; + + if (pop) { + GPU_line_smooth(true); + GPU_blend(GPU_BLEND_ALPHA); + + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); + + ARegion *region = pop->vc.region; + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + GPU_line_width(4.0); + immUniformColor4ub(0, 0, 0, 255); + + immBegin(GPU_PRIM_LINES, 2); + immVertex2i(pos, x, y); + immVertex2i( + pos, pop->startmouse[0] + region->winrct.xmin, pop->startmouse[1] + region->winrct.ymin); + immEnd(); + + GPU_line_width(2.0); + immUniformColor4ub(255, 255, 255, 255); + + immBegin(GPU_PRIM_LINES, 2); + immVertex2i(pos, x, y); + immVertex2i( + pos, pop->startmouse[0] + region->winrct.xmin, pop->startmouse[1] + region->winrct.ymin); + immEnd(); + + immUnbindProgram(); + + GPU_blend(GPU_BLEND_NONE); + GPU_line_smooth(false); + } +} + +static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const float mouse[2]) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); + ToolSettings *settings = scene->toolsettings; + PaintOperation *pop = MEM_new<PaintOperation>("PaintOperation"); /* caller frees */ + Brush *brush = BKE_paint_brush(&settings->imapaint.paint); + int mode = RNA_enum_get(op->ptr, "mode"); + ED_view3d_viewcontext_init(C, &pop->vc, depsgraph); + + copy_v2_v2(pop->prevmouse, mouse); + copy_v2_v2(pop->startmouse, mouse); + + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + + /* initialize from context */ + if (CTX_wm_region_view3d(C)) { + bool uvs, mat, tex, stencil; + if (!ED_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, &stencil)) { + ED_paint_data_warning(op->reports, uvs, mat, tex, stencil); + MEM_delete(pop); + WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, nullptr); + return nullptr; + } + pop->mode = MEM_new<ProjectionPaintMode>("ProjectionPaintMode"); + } + else { + pop->mode = MEM_new<ImagePaintMode>("ImagePaintMode"); + } + + pop->stroke_handle = pop->mode->paint_new_stroke(C, op, ob, mouse, mode); + if (!pop->stroke_handle) { + MEM_delete(pop); + return nullptr; + } + + if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) { + pop->cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, image_paint_poll, gradient_draw_line, pop); + } + + settings->imapaint.flag |= IMAGEPAINT_DRAWING; + ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D); + + return pop; +} + +static void paint_stroke_update_step(bContext *C, + wmOperator *UNUSED(op), + struct PaintStroke *stroke, + PointerRNA *itemptr) +{ + PaintOperation *pop = static_cast<PaintOperation *>(paint_stroke_mode_data(stroke)); + Scene *scene = CTX_data_scene(C); + ToolSettings *toolsettings = CTX_data_tool_settings(C); + UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings; + Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint); + + float alphafac = (brush->flag & BRUSH_ACCUMULATE) ? ups->overlap_factor : 1.0f; + + /* initial brush values. Maybe it should be considered moving these to stroke system */ + float startalpha = BKE_brush_alpha_get(scene, brush); + + float mouse[2]; + float pressure; + float size; + float distance = paint_stroke_distance_get(stroke); + int eraser; + + RNA_float_get_array(itemptr, "mouse", mouse); + pressure = RNA_float_get(itemptr, "pressure"); + eraser = RNA_boolean_get(itemptr, "pen_flip"); + size = RNA_float_get(itemptr, "size"); + + /* stroking with fill tool only acts on stroke end */ + if (brush->imagepaint_tool == PAINT_TOOL_FILL) { + copy_v2_v2(pop->prevmouse, mouse); + return; + } + + if (BKE_brush_use_alpha_pressure(brush)) { + BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure * alphafac)); + } + else { + BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * alphafac)); + } + + if ((brush->flag & BRUSH_DRAG_DOT) || (brush->flag & BRUSH_ANCHORED)) { + UndoStack *ustack = CTX_wm_manager(C)->undo_stack; + ED_image_undo_restore(ustack->step_init); + } + + pop->mode->paint_stroke( + C, pop->stroke_handle, pop->prevmouse, mouse, eraser, pressure, distance, size); + + copy_v2_v2(pop->prevmouse, mouse); + + /* restore brush values */ + BKE_brush_alpha_set(scene, brush, startalpha); +} + +static void paint_stroke_redraw(const bContext *C, struct PaintStroke *stroke, bool final) +{ + PaintOperation *pop = static_cast<PaintOperation *>(paint_stroke_mode_data(stroke)); + pop->mode->paint_stroke_redraw(C, pop->stroke_handle, final); +} + +static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke) +{ + Scene *scene = CTX_data_scene(C); + ToolSettings *toolsettings = scene->toolsettings; + PaintOperation *pop = static_cast<PaintOperation *>(paint_stroke_mode_data(stroke)); + Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint); + + toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING; + + if (brush->imagepaint_tool == PAINT_TOOL_FILL) { + if (brush->flag & BRUSH_USE_GRADIENT) { + pop->mode->paint_gradient_fill( + C, scene, brush, stroke, pop->stroke_handle, pop->startmouse, pop->prevmouse); + } + else { + pop->mode->paint_bucket_fill( + C, scene, brush, stroke, pop->stroke_handle, pop->startmouse, pop->prevmouse); + } + } + pop->mode->paint_stroke_done(pop->stroke_handle); + pop->stroke_handle = nullptr; + + ED_image_undo_push_end(); + +/* duplicate warning, see texpaint_init */ +#if 0 + if (pop->s.warnmultifile) { + BKE_reportf(op->reports, + RPT_WARNING, + "Image requires 4 color channels to paint: %s", + pop->s.warnmultifile); + } + if (pop->s.warnpackedfile) { + BKE_reportf(op->reports, + RPT_WARNING, + "Packed MultiLayer files cannot be painted: %s", + pop->s.warnpackedfile); + } +#endif + MEM_delete(pop); +} + +static bool paint_stroke_test_start(bContext *C, wmOperator *op, const float mouse[2]) +{ + PaintOperation *pop; + + /* TODO: Should avoid putting this here. Instead, last position should be requested + * from stroke system. */ + + if (!(pop = texture_paint_init(C, op, mouse))) { + return false; + } + + paint_stroke_set_mode_data(static_cast<PaintStroke *>(op->customdata), pop); + + return true; +} + +static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + int retval; + + op->customdata = paint_stroke_new(C, + op, + nullptr, + paint_stroke_test_start, + paint_stroke_update_step, + paint_stroke_redraw, + paint_stroke_done, + event->type); + + if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) { + paint_stroke_free(C, op, static_cast<PaintStroke *>(op->customdata)); + return OPERATOR_FINISHED; + } + /* add modal handler */ + WM_event_add_modal_handler(C, op); + + OPERATOR_RETVAL_CHECK(retval); + BLI_assert(retval == OPERATOR_RUNNING_MODAL); + + return OPERATOR_RUNNING_MODAL; +} + +static int paint_exec(bContext *C, wmOperator *op) +{ + PropertyRNA *strokeprop; + PointerRNA firstpoint; + float mouse[2]; + + strokeprop = RNA_struct_find_property(op->ptr, "stroke"); + + if (!RNA_property_collection_lookup_int(op->ptr, strokeprop, 0, &firstpoint)) { + return OPERATOR_CANCELLED; + } + + RNA_float_get_array(&firstpoint, "mouse", mouse); + + op->customdata = paint_stroke_new(C, + op, + nullptr, + paint_stroke_test_start, + paint_stroke_update_step, + paint_stroke_redraw, + paint_stroke_done, + 0); + /* frees op->customdata */ + return paint_stroke_exec(C, op, static_cast<PaintStroke *>(op->customdata)); +} + +static int paint_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + return paint_stroke_modal(C, op, event, static_cast<PaintStroke *>(op->customdata)); +} + +static void paint_cancel(bContext *C, wmOperator *op) +{ + paint_stroke_cancel(C, op, static_cast<PaintStroke *>(op->customdata)); +} +} // namespace blender::ed::sculpt_paint::image::ops::paint + +extern "C" { +void PAINT_OT_image_paint(wmOperatorType *ot) +{ + using namespace blender::ed::sculpt_paint::image::ops::paint; + + /* identifiers */ + ot->name = "Image Paint"; + ot->idname = "PAINT_OT_image_paint"; + ot->description = "Paint a stroke into the image"; + + /* api callbacks */ + ot->invoke = paint_invoke; + ot->modal = paint_modal; + ot->exec = paint_exec; + ot->poll = image_paint_poll; + ot->cancel = paint_cancel; + + /* flags */ + ot->flag = OPTYPE_BLOCKING; + + paint_stroke_operator_properties(ot); +} +} diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index f1e79b98b83..82fdf49c28e 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -49,6 +49,7 @@ typedef struct CoNo { typedef bool (*StrokeGetLocation)(struct bContext *C, float location[3], const float mouse[2]); typedef bool (*StrokeTestStart)(struct bContext *C, struct wmOperator *op, const float mouse[2]); typedef void (*StrokeUpdateStep)(struct bContext *C, + struct wmOperator *op, struct PaintStroke *stroke, struct PointerRNA *itemptr); typedef void (*StrokeRedraw)(const struct bContext *C, struct PaintStroke *stroke, bool final); @@ -62,7 +63,7 @@ struct PaintStroke *paint_stroke_new(struct bContext *C, StrokeRedraw redraw, StrokeDone done, int event_type); -void paint_stroke_free(struct bContext *C, struct wmOperator *op); +void paint_stroke_free(struct bContext *C, struct wmOperator *op, struct PaintStroke *stroke); /** * Returns zero if the stroke dots should not be spaced, non-zero otherwise. @@ -84,9 +85,12 @@ bool paint_supports_jitter(enum ePaintMode mode); * Called in paint_ops.c, on each regeneration of key-maps. */ struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf); -int paint_stroke_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); -int paint_stroke_exec(struct bContext *C, struct wmOperator *op); -void paint_stroke_cancel(struct bContext *C, struct wmOperator *op); +int paint_stroke_modal(struct bContext *C, + struct wmOperator *op, + const struct wmEvent *event, + struct PaintStroke *stroke); +int paint_stroke_exec(struct bContext *C, struct wmOperator *op, struct PaintStroke *stroke); +void paint_stroke_cancel(struct bContext *C, struct wmOperator *op, struct PaintStroke *stroke); bool paint_stroke_flipped(struct PaintStroke *stroke); bool paint_stroke_inverted(struct PaintStroke *stroke); struct ViewContext *paint_stroke_view_context(struct PaintStroke *stroke); @@ -265,6 +269,7 @@ void paint_brush_color_get(struct Scene *scene, bool paint_use_opacity_masking(struct Brush *brush); void paint_brush_init_tex(struct Brush *brush); void paint_brush_exit_tex(struct Brush *brush); +bool image_paint_poll(struct bContext *C); void PAINT_OT_grab_clone(struct wmOperatorType *ot); void PAINT_OT_sample_color(struct wmOperatorType *ot); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 1b876235ad0..926a564184a 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -39,6 +39,7 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "curves_sculpt_intern.h" #include "paint_intern.h" #include "sculpt_intern.h" @@ -758,6 +759,7 @@ static const ePaintMode brush_select_paint_modes[] = { PAINT_MODE_VERTEX_GPENCIL, PAINT_MODE_SCULPT_GPENCIL, PAINT_MODE_WEIGHT_GPENCIL, + PAINT_MODE_SCULPT_CURVES, }; static int brush_select_exec(bContext *C, wmOperator *op) @@ -1388,6 +1390,10 @@ void ED_keymap_paint(wmKeyConfig *keyconf) keymap = paint_stroke_modal_keymap(keyconf); WM_modalkeymap_assign(keymap, "SCULPT_OT_brush_stroke"); + /* Curves Sculpt mode. */ + keymap = WM_keymap_ensure(keyconf, "Sculpt Curves", 0, 0); + keymap->poll = CURVES_SCULPT_mode_poll; + /* sculpt expand. */ sculpt_expand_modal_keymap(keyconf); } diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 9bbfb81e08e..ae7570d21a1 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -505,16 +505,13 @@ static bool paint_stroke_use_jitter(ePaintMode mode, Brush *brush, bool invert) } /* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */ -static void paint_brush_stroke_add_step(bContext *C, - wmOperator *op, - const float mouse_in[2], - float pressure) +static void paint_brush_stroke_add_step( + bContext *C, wmOperator *op, PaintStroke *stroke, const float mouse_in[2], float pressure) { Scene *scene = CTX_data_scene(C); Paint *paint = BKE_paint_get_active_from_context(C); ePaintMode mode = BKE_paintmode_get_active_from_context(C); Brush *brush = BKE_paint_brush(paint); - PaintStroke *stroke = op->customdata; UnifiedPaintSettings *ups = stroke->ups; float mouse_out[2]; PointerRNA itemptr; @@ -614,7 +611,7 @@ static void paint_brush_stroke_add_step(bContext *C, RNA_float_set(&itemptr, "x_tilt", stroke->x_tilt); RNA_float_set(&itemptr, "y_tilt", stroke->y_tilt); - stroke->update_step(C, stroke, &itemptr); + stroke->update_step(C, op, stroke, &itemptr); /* don't record this for now, it takes up a lot of memory when doing long * strokes with small brush size, and operators have register disabled */ @@ -785,12 +782,12 @@ static float paint_space_stroke_spacing_variable(bContext *C, * towards the final mouse location. */ static int paint_space_stroke(bContext *C, wmOperator *op, + PaintStroke *stroke, const float final_mouse[2], float final_pressure) { const Scene *scene = CTX_data_scene(C); ARegion *region = CTX_wm_region(C); - PaintStroke *stroke = op->customdata; UnifiedPaintSettings *ups = stroke->ups; Paint *paint = BKE_paint_get_active_from_context(C); ePaintMode mode = BKE_paintmode_get_active_from_context(C); @@ -852,7 +849,7 @@ static int paint_space_stroke(bContext *C, spacing / no_pressure_spacing); stroke->stroke_distance += spacing / stroke->zoom_2d; - paint_brush_stroke_add_step(C, op, mouse, pressure); + paint_brush_stroke_add_step(C, op, stroke, mouse, pressure); length -= spacing; pressure = stroke->last_pressure; @@ -929,7 +926,7 @@ PaintStroke *paint_stroke_new(bContext *C, return stroke; } -void paint_stroke_free(bContext *C, wmOperator *op) +void paint_stroke_free(bContext *C, wmOperator *UNUSED(op), PaintStroke *stroke) { RegionView3D *rv3d = CTX_wm_region_view3d(C); if (rv3d) { @@ -938,7 +935,6 @@ void paint_stroke_free(bContext *C, wmOperator *op) BKE_paint_set_overlay_override(0); - PaintStroke *stroke = op->customdata; if (stroke == NULL) { return; } @@ -961,12 +957,11 @@ void paint_stroke_free(bContext *C, wmOperator *op) BLI_freelistN(&stroke->line); - MEM_SAFE_FREE(op->customdata); + MEM_SAFE_FREE(stroke); } -static void stroke_done(bContext *C, wmOperator *op) +static void stroke_done(bContext *C, wmOperator *op, PaintStroke *stroke) { - PaintStroke *stroke = op->customdata; UnifiedPaintSettings *ups = stroke->ups; /* reset rotation here to avoid doing so in cursor display */ @@ -988,7 +983,7 @@ static void stroke_done(bContext *C, wmOperator *op) } } - paint_stroke_free(C, op); + paint_stroke_free(C, op, stroke); } bool paint_space_stroke_enabled(Brush *br, ePaintMode mode) @@ -1230,7 +1225,7 @@ static void paint_line_strokes_spacing(bContext *C, ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, 1.0); stroke->stroke_distance += spacing / stroke->zoom_2d; - paint_brush_stroke_add_step(C, op, mouse, 1.0); + paint_brush_stroke_add_step(C, op, stroke, mouse, 1.0); length -= spacing; spacing_final = spacing; @@ -1252,8 +1247,8 @@ static void paint_stroke_line_end(bContext *C, if (stroke->stroke_started && (br->flag & BRUSH_LINE)) { stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0); - paint_brush_stroke_add_step(C, op, stroke->last_mouse_position, 1.0); - paint_space_stroke(C, op, mouse, 1.0); + paint_brush_stroke_add_step(C, op, stroke, stroke->last_mouse_position, 1.0); + paint_space_stroke(C, op, stroke, mouse, 1.0); } } @@ -1331,7 +1326,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position); if (stroke->stroke_started) { - paint_brush_stroke_add_step(C, op, data + 2 * j, 1.0); + paint_brush_stroke_add_step(C, op, stroke, data + 2 * j, 1.0); paint_line_strokes_spacing( C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1)); } @@ -1343,7 +1338,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str } } - stroke_done(C, op); + stroke_done(C, op, stroke); #ifdef DEBUG_TIME TIMEIT_END_AVERAGED(whole_stroke); @@ -1384,11 +1379,10 @@ static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2]) } } -int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) +int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintStroke *stroke) { Paint *p = BKE_paint_get_active_from_context(C); ePaintMode mode = BKE_paintmode_get_active_from_context(C); - PaintStroke *stroke = op->customdata; Brush *br = stroke->brush = BKE_paint_brush(p); PaintSample sample_average; float mouse[2]; @@ -1482,7 +1476,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) op->type->cancel(C, op); } else { - paint_stroke_cancel(C, op); + paint_stroke_cancel(C, op, stroke); } return OPERATOR_CANCELLED; } @@ -1492,17 +1486,17 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) copy_v2_fl2(mouse, event->mval[0], event->mval[1]); paint_stroke_line_constrain(stroke, mouse); paint_stroke_line_end(C, op, stroke, mouse); - stroke_done(C, op); + stroke_done(C, op, stroke); return OPERATOR_FINISHED; } } else if (ELEM(event->type, EVT_RETKEY, EVT_SPACEKEY)) { paint_stroke_line_end(C, op, stroke, sample_average.mouse); - stroke_done(C, op); + stroke_done(C, op, stroke); return OPERATOR_FINISHED; } else if (br->flag & BRUSH_LINE) { - if (event->alt) { + if (event->modifier & KM_ALT) { stroke->constrain_line = true; } else { @@ -1530,7 +1524,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, &pressure)) { if (stroke->stroke_started) { if (paint_space_stroke_enabled(br, mode)) { - if (paint_space_stroke(C, op, mouse, pressure)) { + if (paint_space_stroke(C, op, stroke, mouse, pressure)) { redraw = true; } } @@ -1538,7 +1532,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) float dmouse[2]; sub_v2_v2v2(dmouse, mouse, stroke->last_mouse_position); stroke->stroke_distance += len_v2(dmouse); - paint_brush_stroke_add_step(C, op, mouse, pressure); + paint_brush_stroke_add_step(C, op, stroke, mouse, pressure); redraw = true; } } @@ -1549,7 +1543,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) * instead of waiting till we have moved the space distance */ if (first_dab && paint_space_stroke_enabled(br, mode) && !(br->flag & BRUSH_SMOOTH_STROKE)) { stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0); - paint_brush_stroke_add_step(C, op, sample_average.mouse, sample_average.pressure); + paint_brush_stroke_add_step(C, op, stroke, sample_average.mouse, sample_average.pressure); redraw = true; } @@ -1572,10 +1566,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_RUNNING_MODAL; } -int paint_stroke_exec(bContext *C, wmOperator *op) +int paint_stroke_exec(bContext *C, wmOperator *op, PaintStroke *stroke) { - PaintStroke *stroke = op->customdata; - /* only when executed for the first time */ if (stroke->stroke_started == 0) { PropertyRNA *strokeprop; @@ -1592,21 +1584,21 @@ int paint_stroke_exec(bContext *C, wmOperator *op) if (stroke->stroke_started) { RNA_BEGIN (op->ptr, itemptr, "stroke") { - stroke->update_step(C, stroke, &itemptr); + stroke->update_step(C, op, stroke, &itemptr); } RNA_END; } bool ok = (stroke->stroke_started != 0); - stroke_done(C, op); + stroke_done(C, op, stroke); return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } -void paint_stroke_cancel(bContext *C, wmOperator *op) +void paint_stroke_cancel(bContext *C, wmOperator *op, PaintStroke *stroke) { - stroke_done(C, op); + stroke_done(C, op, stroke); } ViewContext *paint_stroke_view_context(PaintStroke *stroke) diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index f54b012b8dd..31b965c6a92 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -130,13 +130,12 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], flo { Object *ob = vc->obact; float delta[3], scale, loc[3]; - const float mval_f[2] = {pixel_radius, 0.0f}; - float zfac; + const float xy_delta[2] = {pixel_radius, 0.0f}; mul_v3_m4v3(loc, ob->obmat, center); - zfac = ED_view3d_calc_zfac(vc->rv3d, loc, NULL); - ED_view3d_win_to_delta(vc->region, mval_f, delta, zfac); + const float zfac = ED_view3d_calc_zfac(vc->rv3d, loc); + ED_view3d_win_to_delta(vc->region, xy_delta, zfac, delta); scale = fabsf(mat4_to_scale(ob->obmat)); scale = (scale == 0.0f) ? 1.0f : scale; @@ -585,7 +584,8 @@ void BRUSH_OT_curve_preset(wmOperatorType *ot) ot->poll = brush_curve_preset_poll; prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", ""); - RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ + RNA_def_property_translation_context(prop, + BLT_I18NCONTEXT_ID_CURVE_LEGACY); /* Abusing id_curve :/ */ } /* face-select ops */ diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index a82636023f8..e2f8d81fe13 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -2370,7 +2370,10 @@ static void wpaint_do_symmetrical_brush_actions( cache->is_last_valid = true; } -static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr) +static void wpaint_stroke_update_step(bContext *C, + wmOperator *UNUSED(op), + struct PaintStroke *stroke, + PointerRNA *itemptr) { Scene *scene = CTX_data_scene(C); ToolSettings *ts = CTX_data_tool_settings(C); @@ -2551,7 +2554,7 @@ static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event) event->type); if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) { - paint_stroke_free(C, op); + paint_stroke_free(C, op, op->customdata); return OPERATOR_FINISHED; } /* add modal handler */ @@ -2575,7 +2578,7 @@ static int wpaint_exec(bContext *C, wmOperator *op) 0); /* frees op->customdata */ - paint_stroke_exec(C, op); + paint_stroke_exec(C, op, op->customdata); return OPERATOR_FINISHED; } @@ -2588,7 +2591,12 @@ static void wpaint_cancel(bContext *C, wmOperator *op) ob->sculpt->cache = NULL; } - paint_stroke_cancel(C, op); + paint_stroke_cancel(C, op, op->customdata); +} + +static int wpaint_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + return paint_stroke_modal(C, op, event, op->customdata); } void PAINT_OT_weight_paint(wmOperatorType *ot) @@ -2600,7 +2608,7 @@ void PAINT_OT_weight_paint(wmOperatorType *ot) /* api callbacks */ ot->invoke = wpaint_invoke; - ot->modal = paint_stroke_modal; + ot->modal = wpaint_modal; ot->exec = wpaint_exec; ot->poll = weight_paint_poll; ot->cancel = wpaint_cancel; @@ -3395,7 +3403,10 @@ static void vpaint_do_symmetrical_brush_actions( cache->is_last_valid = true; } -static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr) +static void vpaint_stroke_update_step(bContext *C, + wmOperator *UNUSED(op), + struct PaintStroke *stroke, + PointerRNA *itemptr) { Scene *scene = CTX_data_scene(C); ToolSettings *ts = CTX_data_tool_settings(C); @@ -3497,7 +3508,7 @@ static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event) event->type); if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) { - paint_stroke_free(C, op); + paint_stroke_free(C, op, op->customdata); return OPERATOR_FINISHED; } @@ -3522,7 +3533,7 @@ static int vpaint_exec(bContext *C, wmOperator *op) 0); /* frees op->customdata */ - paint_stroke_exec(C, op); + paint_stroke_exec(C, op, op->customdata); return OPERATOR_FINISHED; } @@ -3535,7 +3546,12 @@ static void vpaint_cancel(bContext *C, wmOperator *op) ob->sculpt->cache = NULL; } - paint_stroke_cancel(C, op); + paint_stroke_cancel(C, op, op->customdata); +} + +static int vpaint_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + return paint_stroke_modal(C, op, event, op->customdata); } void PAINT_OT_vertex_paint(wmOperatorType *ot) @@ -3547,7 +3563,7 @@ void PAINT_OT_vertex_paint(wmOperatorType *ot) /* api callbacks */ ot->invoke = vpaint_invoke; - ot->modal = paint_stroke_modal; + ot->modal = vpaint_modal; ot->exec = vpaint_exec; ot->poll = vertex_paint_poll; ot->cancel = vpaint_cancel; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 68edf9cd54a..70ff7596d6d 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2648,13 +2648,13 @@ static void update_sculpt_normal(Sculpt *sd, Object *ob, PBVHNode **nodes, int t static void calc_local_y(ViewContext *vc, const float center[3], float y[3]) { Object *ob = vc->obact; - float loc[3], mval_f[2] = {0.0f, 1.0f}; - float zfac; + float loc[3]; + const float xy_delta[2] = {0.0f, 1.0f}; mul_v3_m4v3(loc, ob->imat, center); - zfac = ED_view3d_calc_zfac(vc->rv3d, loc, NULL); + const float zfac = ED_view3d_calc_zfac(vc->rv3d, loc); - ED_view3d_win_to_delta(vc->region, mval_f, y, zfac); + ED_view3d_win_to_delta(vc->region, xy_delta, zfac, y); normalize_v3(y); add_v3_v3(y, ob->loc); @@ -5186,6 +5186,7 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f } static void sculpt_stroke_update_step(bContext *C, + wmOperator *UNUSED(op), struct PaintStroke *UNUSED(stroke), PointerRNA *itemptr) { @@ -5333,12 +5334,12 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent ignore_background_click = RNA_boolean_get(op->ptr, "ignore_background_click"); if (ignore_background_click && !over_mesh(C, op, event->xy[0], event->xy[1])) { - paint_stroke_free(C, op); + paint_stroke_free(C, op, op->customdata); return OPERATOR_PASS_THROUGH; } if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) { - paint_stroke_free(C, op); + paint_stroke_free(C, op, op->customdata); return OPERATOR_FINISHED; } /* Add modal handler. */ @@ -5364,7 +5365,7 @@ static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op) 0); /* Frees op->customdata. */ - paint_stroke_exec(C, op); + paint_stroke_exec(C, op, op->customdata); return OPERATOR_FINISHED; } @@ -5382,7 +5383,7 @@ static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op) paint_mesh_restore_co(sd, ob); } - paint_stroke_cancel(C, op); + paint_stroke_cancel(C, op, op->customdata); if (ss->cache) { SCULPT_cache_free(ss->cache); @@ -5392,6 +5393,11 @@ static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op) sculpt_brush_exit_tex(sd); } +static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + return paint_stroke_modal(C, op, event, op->customdata); +} + void SCULPT_OT_brush_stroke(wmOperatorType *ot) { /* Identifiers. */ @@ -5401,7 +5407,7 @@ void SCULPT_OT_brush_stroke(wmOperatorType *ot) /* API callbacks. */ ot->invoke = sculpt_brush_stroke_invoke; - ot->modal = paint_stroke_modal; + ot->modal = sculpt_brush_stroke_modal; ot->exec = sculpt_brush_stroke_exec; ot->poll = SCULPT_poll; ot->cancel = sculpt_brush_stroke_cancel; diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index a6b412b2b7e..6f9df4d8252 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -1105,10 +1105,10 @@ bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v); bool SCULPT_search_circle_cb(PBVHNode *node, void *data_v); /** - * Initialize a point-in-brush test with a given falloff shape + * Initialize a point-in-brush test with a given falloff shape. * - * \param falloff_shape PAINT_FALLOFF_SHAPE_SPHERE or PAINT_FALLOFF_SHAPE_TUBE - * \return The brush falloff function + * \param falloff_shape: #PAINT_FALLOFF_SHAPE_SPHERE or #PAINT_FALLOFF_SHAPE_TUBE. + * \return The brush falloff function. */ SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss, SculptBrushTest *test, diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c index 72640893dea..8fc10061f83 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c +++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c @@ -245,7 +245,7 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent * /* When pressing Ctrl, expand directly to the max number of iterations. This allows to flood fill * mask and face sets by connectivity directly. */ - if (event->ctrl) { + if (event->modifier & KM_CTRL) { mask_expand_update_it = ss->filter_cache->mask_update_last_it - 1; } diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index e383ada1331..8e8902c2ea7 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -659,7 +659,7 @@ static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *even { /* NOTE: this is hardcoded to match the behavior for the unlink button * (in interface_templates.c). */ - RNA_boolean_set(op->ptr, "force_delete", event->shift != 0); + RNA_boolean_set(op->ptr, "force_delete", event->modifier & KM_SHIFT); return action_unlink_exec(C, op); } diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 897091731a4..d53fe2efb03 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -29,6 +29,7 @@ #include "ED_clip.h" #include "ED_curve.h" #include "ED_curves.h" +#include "ED_curves_sculpt.h" #include "ED_fileselect.h" #include "ED_geometry.h" #include "ED_gizmo_library.h" @@ -96,6 +97,7 @@ void ED_spacetypes_init(void) ED_operatortypes_mesh(); ED_operatortypes_geometry(); ED_operatortypes_sculpt(); + ED_operatortypes_sculpt_curves(); ED_operatortypes_uvedit(); ED_operatortypes_paint(); ED_operatortypes_physics(); diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 287aef178ae..4e80e7ea5c2 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -230,7 +230,7 @@ static bool buttons_context_path_data(ButsContextPath *path, int type) return true; } if (RNA_struct_is_a(ptr->type, &RNA_Curve) && - (type == -1 || ELEM(type, OB_CURVE, OB_SURF, OB_FONT))) { + (type == -1 || ELEM(type, OB_CURVES_LEGACY, OB_SURF, OB_FONT))) { return true; } if (RNA_struct_is_a(ptr->type, &RNA_Armature) && (ELEM(type, -1, OB_ARMATURE))) { @@ -293,7 +293,7 @@ static bool buttons_context_path_modifier(ButsContextPath *path) if (ELEM(ob->type, OB_MESH, - OB_CURVE, + OB_CURVES_LEGACY, OB_FONT, OB_SURF, OB_LATTICE, diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index cad6d34af24..e215b7c7992 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -282,11 +282,11 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* Useful yet irritating feature, Shift+Click to open the file * Alt+Click to browse a folder in the OS's browser. */ - if (event->shift || event->alt) { + if (event->modifier & (KM_SHIFT | KM_ALT)) { wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true); PointerRNA props_ptr; - if (event->alt) { + if (event->modifier & KM_ALT) { char *lslash = (char *)BLI_path_slash_rfind(str); if (lslash) { *lslash = '\0'; diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index ba0b3a59e24..a24eae6a0ce 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -408,7 +408,7 @@ static int console_insert_invoke(bContext *C, wmOperator *op, const wmEvent *eve * (when input method are used for utf8 inputs, the user may assign key event * including alt/ctrl/super like ctrl+m to commit utf8 string. in such case, * the modifiers in the utf8 character event make no sense.) */ - if ((event->ctrl || event->oskey) && !event->utf8_buf[0]) { + if ((event->modifier & (KM_CTRL | KM_OSKEY)) && !event->utf8_buf[0]) { return OPERATOR_PASS_THROUGH; } @@ -456,7 +456,18 @@ void CONSOLE_OT_insert(wmOperatorType *ot) static int console_indent_or_autocomplete_exec(bContext *C, wmOperator *UNUSED(op)) { ConsoleLine *ci = console_history_verify(C); - bool text_before_cursor = ci->cursor != 0 && !ELEM(ci->line[ci->cursor - 1], ' ', '\t'); + bool text_before_cursor = false; + + /* Check any text before cursor (not just the previous character) as is done for + * #TEXT_OT_indent_or_autocomplete because Python auto-complete operates on import + * statements such as completing possible sub-modules: `from bpy import `. */ + for (int i = 0; i < ci->cursor; i += BLI_str_utf8_size_safe(&ci->line[i])) { + if (!ELEM(ci->line[i], ' ', '\t')) { + text_before_cursor = true; + break; + } + } + if (text_before_cursor) { WM_operator_name_call(C, "CONSOLE_OT_autocomplete", WM_OP_INVOKE_DEFAULT, NULL); } diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 3b3d968aed6..daa4b53803f 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -2245,7 +2245,7 @@ FileDirEntry *filelist_file_ex(struct FileList *filelist, const int index, const cache->misc_entries_indices[cache->misc_cursor] = index; cache->misc_cursor = (cache->misc_cursor + 1) % cache_size; -#if 0 /* Actually no, only block cached entries should have preview imho. */ +#if 0 /* Actually no, only block cached entries should have preview IMHO. */ if (cache->previews_pool) { filelist_cache_previews_push(filelist, ret, index); } diff --git a/source/blender/editors/space_graph/graph_slider_ops.c b/source/blender/editors/space_graph/graph_slider_ops.c index 1006ba4b3f4..1a3355b0139 100644 --- a/source/blender/editors/space_graph/graph_slider_ops.c +++ b/source/blender/editors/space_graph/graph_slider_ops.c @@ -163,6 +163,18 @@ static void reset_bezts(tGraphSliderOp *gso) ANIM_animdata_freelist(&anim_data); } +/** + * Get factor value and store it in RNA property. + * Custom data of #wmOperator needs to contain #tGraphSliderOp. + */ +static float slider_factor_get_and_remember(wmOperator *op) +{ + tGraphSliderOp *gso = op->customdata; + const float factor = ED_slider_factor_get(gso->slider); + RNA_property_float_set(op->ptr, gso->factor_prop, factor); + return factor; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -378,8 +390,7 @@ static void decimate_modal_update(bContext *C, wmOperator *op) reset_bezts(gso); /* Apply... */ - float factor = ED_slider_factor_get(gso->slider); - RNA_property_float_set(op->ptr, gso->factor_prop, factor); + const float factor = slider_factor_get_and_remember(op); /* We don't want to limit the decimation to a certain error margin. */ const float error_sq_max = FLT_MAX; decimate_graph_keys(&gso->ac, factor, error_sq_max); @@ -598,8 +609,7 @@ static void blend_to_neighbor_modal_update(bContext *C, wmOperator *op) /* Reset keyframe data to the state at invoke. */ reset_bezts(gso); - const float factor = ED_slider_factor_get(gso->slider); - RNA_property_float_set(op->ptr, gso->factor_prop, factor); + const float factor = slider_factor_get_and_remember(op); blend_to_neighbor_graph_keys(&gso->ac, factor); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); @@ -725,7 +735,8 @@ static void breakdown_modal_update(bContext *C, wmOperator *op) /* Reset keyframe data to the state at invoke. */ reset_bezts(gso); - breakdown_graph_keys(&gso->ac, ED_slider_factor_get(gso->slider)); + const float factor = slider_factor_get_and_remember(op); + breakdown_graph_keys(&gso->ac, factor); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } @@ -739,6 +750,7 @@ static int breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event) tGraphSliderOp *gso = op->customdata; gso->modal_update = breakdown_modal_update; + gso->factor_prop = RNA_struct_find_property(op->ptr, "factor"); breakdown_draw_status_header(C, gso); return invoke_result; diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c index 4351186dc6f..9f934e47ebb 100644 --- a/source/blender/editors/space_graph/graph_utils.c +++ b/source/blender/editors/space_graph/graph_utils.c @@ -185,6 +185,7 @@ bool graphop_editable_keyframes_poll(bContext *C) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE); items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); if (items == 0) { + CTX_wm_operator_poll_msg_set(C, "There is no animation data to operate on"); return found; } diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 27ac34ba346..22427675ff3 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -242,7 +242,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *region) GPU_blend(GPU_BLEND_NONE); - /* Vertical component of of the cursor. */ + /* Vertical component of the cursor. */ if (sipo->mode == SIPO_MODE_DRIVERS) { /* cursor x-value */ float x = sipo->cursorTime; diff --git a/source/blender/editors/space_info/info_stats.cc b/source/blender/editors/space_info/info_stats.cc index da899ef4c9a..6f0d5c2dbe9 100644 --- a/source/blender/editors/space_info/info_stats.cc +++ b/source/blender/editors/space_info/info_stats.cc @@ -152,7 +152,7 @@ static void stats_object(Object *ob, } break; case OB_SURF: - case OB_CURVE: + case OB_CURVES_LEGACY: case OB_FONT: { const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); if ((me_eval != nullptr) && !BLI_gset_add(objects_gset, (void *)me_eval)) { @@ -260,7 +260,7 @@ static void stats_object_edit(Object *obedit, SceneStats *stats) stats->totvert += 2; } } - else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { /* OB_FONT has no cu->editnurb */ + else if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { /* OB_FONT has no cu->editnurb */ /* Curve Edit */ Curve *cu = static_cast<Curve *>(obedit->data); BezTriple *bezt; diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 4a507aa3bf2..8b059b33a9a 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -583,7 +583,7 @@ static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent * { /* NOTE: this is hardcoded to match the behavior for the unlink button * (in interface_templates.c) */ - RNA_boolean_set(op->ptr, "force_delete", event->shift != 0); + RNA_boolean_set(op->ptr, "force_delete", event->modifier & KM_SHIFT); return nla_action_unlink_exec(C, op); } diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index eda9f89b51c..d8a0fde6d07 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -110,7 +110,7 @@ static void nla_action_draw_keyframes( */ Range2f frame_range; - ED_keylist_frame_range(keylist, &frame_range); + ED_keylist_all_keys_frame_range(keylist, &frame_range); immRectf(pos_id, frame_range.min, ymin + 2, frame_range.max, ymax - 2); immUnbindProgram(); diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index 28ac7a34fa8..afb205f9f9e 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -147,7 +147,7 @@ static void node_buts_curvefloat(uiLayout *layout, bContext *UNUSED(C), PointerR } // namespace blender::ed::space_node #define SAMPLE_FLT_ISNONE FLT_MAX -/* Bad bad, 2.5 will do better? ... no it won't! */ +/* Bad! 2.5 will do better? ... no it won't! */ static float _sample_col[4] = {SAMPLE_FLT_ISNONE}; void ED_node_sample_set(const float col[4]) { @@ -1967,9 +1967,10 @@ void node_draw_link_bezier(const bContext &C, const bNodeLink &link, const int th_col1, const int th_col2, - const int th_col3) + const int th_col3, + const bool selected) { - const float dim_factor = node_link_dim_factor(v2d, link); + const float dim_factor = selected ? 1.0f : node_link_dim_factor(v2d, link); float thickness = 1.5f; float dash_factor = 1.0f; @@ -2025,19 +2026,17 @@ void node_draw_link_bezier(const bContext &C, } /* Highlight links connected to selected nodes. */ - const bool is_fromnode_selected = link.fromnode && link.fromnode->flag & SELECT; - const bool is_tonode_selected = link.tonode && link.tonode->flag & SELECT; - if (is_fromnode_selected || is_tonode_selected) { + if (selected) { float color_selected[4]; UI_GetThemeColor4fv(TH_EDGE_SELECT, color_selected); const float alpha = color_selected[3]; /* Interpolate color if highlight color is not fully transparent. */ if (alpha != 0.0) { - if (is_fromnode_selected) { + if (link.fromsock) { interp_v3_v3v3(colors[1], colors[1], color_selected, alpha); } - if (is_tonode_selected) { + if (link.tosock) { interp_v3_v3v3(colors[2], colors[2], color_selected, alpha); } } @@ -2102,7 +2101,8 @@ void node_draw_link_bezier(const bContext &C, void node_draw_link(const bContext &C, const View2D &v2d, const SpaceNode &snode, - const bNodeLink &link) + const bNodeLink &link, + const bool selected) { int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE; @@ -2146,7 +2146,7 @@ void node_draw_link(const bContext &C, } } - node_draw_link_bezier(C, v2d, snode, link, th_col1, th_col2, th_col3); + node_draw_link_bezier(C, v2d, snode, link, th_col1, th_col2, th_col3, selected); } } // namespace blender::ed::space_node diff --git a/source/blender/editors/space_node/node_context_path.cc b/source/blender/editors/space_node/node_context_path.cc index a76988a60d0..349fa92d06d 100644 --- a/source/blender/editors/space_node/node_context_path.cc +++ b/source/blender/editors/space_node/node_context_path.cc @@ -47,7 +47,7 @@ static void context_path_add_object_data(Vector<ui::ContextPathItem> &path, Obje Light *light = (Light *)object.data; ui::context_path_add_generic(path, RNA_Light, light); } - if (ELEM(object.type, OB_CURVE, OB_FONT, OB_SURF) && object.data) { + if (ELEM(object.type, OB_CURVES_LEGACY, OB_FONT, OB_SURF) && object.data) { Curve *curve = (Curve *)object.data; ui::context_path_add_generic(path, RNA_Curve, curve); } diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 455eceed293..1286f6a818c 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -660,7 +660,7 @@ static void node_draw_mute_line(const bContext &C, GPU_blend(GPU_BLEND_ALPHA); LISTBASE_FOREACH (const bNodeLink *, link, &node.internal_links) { - node_draw_link_bezier(C, v2d, snode, *link, TH_WIRE_INNER, TH_WIRE_INNER, TH_WIRE); + node_draw_link_bezier(C, v2d, snode, *link, TH_WIRE_INNER, TH_WIRE_INNER, TH_WIRE, false); } GPU_blend(GPU_BLEND_NONE); @@ -718,7 +718,12 @@ static void node_socket_draw_multi_input(const float color[4], const int locx, const int locy) { - const float outline_width = 1.0f; + /* The other sockets are drawn with the keyframe shader. There, the outline has a base thickness + * that can be varied but always scales with the size the socket is drawn at. Using `U.dpi_fac` + * has the the same effect here. It scales the outline correctly across different screen DPIs + * and UI scales without being affected by the 'line-width'. */ + const float outline_width = NODE_SOCK_OUTLINE_SCALE * U.dpi_fac; + /* UI_draw_roundbox draws the outline on the outer side, so compensate for the outline width. */ const rctf rect = { locx - width + outline_width * 0.5f, @@ -1049,7 +1054,7 @@ static void node_socket_draw_nested(const bContext &C, }, data, MEM_freeN); - /* Disable the button so that clicks on it are ignored the the link operator still works. */ + /* Disable the button so that clicks on it are ignored the link operator still works. */ UI_but_flag_enable(but, UI_BUT_DISABLED); UI_block_emboss_set(&block, old_emboss); } @@ -1060,7 +1065,7 @@ void ED_node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[ { using namespace blender::ed::space_node; - const float size = 2.25f * NODE_SOCKSIZE * scale; + const float size = NODE_SOCKSIZE_DRAW_MULIPLIER * NODE_SOCKSIZE * scale; rcti draw_rect = *rect; float outline_color[4] = {0}; @@ -1081,7 +1086,7 @@ void ED_node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[ GPU_program_point_size(true); immBindBuiltinProgram(GPU_SHADER_KEYFRAME_SHAPE); - immUniform1f("outline_scale", 1.0f); + immUniform1f("outline_scale", NODE_SOCK_OUTLINE_SCALE); immUniform2f("ViewportSize", -1.0f, -1.0f); /* Single point. */ @@ -1232,13 +1237,14 @@ static void node_draw_sockets(const View2D &v2d, GPU_blend(GPU_BLEND_ALPHA); GPU_program_point_size(true); immBindBuiltinProgram(GPU_SHADER_KEYFRAME_SHAPE); - immUniform1f("outline_scale", 1.0f); + immUniform1f("outline_scale", NODE_SOCK_OUTLINE_SCALE); immUniform2f("ViewportSize", -1.0f, -1.0f); /* Set handle size. */ + const float socket_draw_size = NODE_SOCKSIZE * NODE_SOCKSIZE_DRAW_MULIPLIER; float scale; UI_view2d_scale_get(&v2d, &scale, nullptr); - scale *= 2.25f * NODE_SOCKSIZE; + scale *= socket_draw_size; if (!select_all) { immBeginAtMost(GPU_PRIM_POINTS, total_input_len + total_output_len); @@ -1251,7 +1257,10 @@ static void node_draw_sockets(const View2D &v2d, continue; } if (select_all || (sock->flag & SELECT)) { - selected_input_len++; + if (!(sock->flag & SOCK_MULTI_INPUT)) { + /* Don't add multi-input sockets here since they are drawn in a different batch. */ + selected_input_len++; + } continue; } /* Don't draw multi-input sockets here since they are drawn in a different batch. */ @@ -1318,6 +1327,10 @@ static void node_draw_sockets(const View2D &v2d, if (nodeSocketIsHidden(sock)) { continue; } + /* Don't draw multi-input sockets here since they are drawn in a different batch. */ + if (sock->flag & SOCK_MULTI_INPUT) { + continue; + } if (select_all || (sock->flag & SELECT)) { node_socket_draw_nested(C, ntree, @@ -1383,13 +1396,13 @@ static void node_draw_sockets(const View2D &v2d, } const bool is_node_hidden = (node.flag & NODE_HIDDEN); - const float width = NODE_SOCKSIZE; + const float width = 0.5f * socket_draw_size; float height = is_node_hidden ? width : node_socket_calculate_height(*socket) - width; float color[4]; float outline_color[4]; node_socket_color_get(C, ntree, node_ptr, *socket, color); - node_socket_outline_color_get(selected, socket->type, outline_color); + node_socket_outline_color_get(socket->flag & SELECT, socket->type, outline_color); node_socket_draw_multi_input(color, outline_color, width, height, socket->locx, socket->locy); } @@ -2650,10 +2663,18 @@ static void node_draw_nodetree(const bContext &C, nodelink_batch_start(snode); LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { - if (!nodeLinkIsHidden(link)) { - node_draw_link(C, region.v2d, snode, *link); + if (!nodeLinkIsHidden(link) && !nodeLinkIsSelected(link)) { + node_draw_link(C, region.v2d, snode, *link, false); } } + + /* Draw selected node links after the unselected ones, so they are shown on top. */ + LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { + if (!nodeLinkIsHidden(link) && nodeLinkIsSelected(link)) { + node_draw_link(C, region.v2d, snode, *link, true); + } + } + nodelink_batch_end(snode); GPU_blend(GPU_BLEND_NONE); @@ -2838,7 +2859,7 @@ void node_draw_space(const bContext &C, ARegion ®ion) GPU_line_smooth(true); if (snode.runtime->linkdrag) { for (const bNodeLink *link : snode.runtime->linkdrag->links) { - node_draw_link(C, v2d, snode, *link); + node_draw_link(C, v2d, snode, *link, true); } } GPU_line_smooth(false); diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 7b7aaef518b..b30be6ae0af 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -89,7 +89,7 @@ struct CompoJob { float node_socket_calculate_height(const bNodeSocket &socket) { - float sock_height = NODE_SOCKSIZE * 2.0f; + float sock_height = NODE_SOCKSIZE * NODE_SOCKSIZE_DRAW_MULIPLIER; if (socket.flag & SOCK_MULTI_INPUT) { sock_height += max_ii(NODE_MULTI_INPUT_LINK_GAP * 0.5f * socket.total_inputs, NODE_SOCKSIZE); } @@ -1160,12 +1160,16 @@ bool node_find_indicated_socket(SpaceNode &snode, { rctf rect; + const float size_sock_padded = NODE_SOCKSIZE + 4; + *nodep = nullptr; *sockp = nullptr; /* check if we click in a socket */ LISTBASE_FOREACH (bNode *, node, &snode.edittree->nodes) { - BLI_rctf_init_pt_radius(&rect, cursor, NODE_SOCKSIZE + 4); + BLI_rctf_init_pt_radius(&rect, cursor, size_sock_padded); + rctf node_visible; + BLI_rctf_init_pt_radius(&node_visible, cursor, size_sock_padded); if (!(node->flag & NODE_HIDDEN)) { /* extra padding inside and out - allow dragging on the text areas too */ @@ -1184,7 +1188,7 @@ bool node_find_indicated_socket(SpaceNode &snode, if (!nodeSocketIsHidden(sock)) { if (sock->flag & SOCK_MULTI_INPUT && !(node->flag & NODE_HIDDEN)) { if (cursor_isect_multi_input_socket(cursor, *sock)) { - if (node == visible_node(snode, rect)) { + if (node == visible_node(snode, node_visible)) { *nodep = node; *sockp = sock; return true; @@ -1192,7 +1196,7 @@ bool node_find_indicated_socket(SpaceNode &snode, } } else if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) { - if (node == visible_node(snode, rect)) { + if (node == visible_node(snode, node_visible)) { *nodep = node; *sockp = sock; return true; @@ -1205,7 +1209,7 @@ bool node_find_indicated_socket(SpaceNode &snode, LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { if (!nodeSocketIsHidden(sock)) { if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) { - if (node == visible_node(snode, rect)) { + if (node == visible_node(snode, node_visible)) { *nodep = node; *sockp = sock; return true; diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh index 592db3f7877..319f97e57f5 100644 --- a/source/blender/editors/space_node/node_intern.hh +++ b/source/blender/editors/space_node/node_intern.hh @@ -104,6 +104,8 @@ ENUM_OPERATORS(NodeResizeDirection, NODE_RESIZE_LEFT); #define NODE_HEIGHT(node) (node.height * UI_DPI_FAC) #define NODE_MARGIN_X (1.2f * U.widget_unit) #define NODE_SOCKSIZE (0.25f * U.widget_unit) +#define NODE_SOCKSIZE_DRAW_MULIPLIER 2.25f +#define NODE_SOCK_OUTLINE_SCALE 1.0f #define NODE_MULTI_INPUT_LINK_GAP (0.25f * U.widget_unit) #define NODE_RESIZE_MARGIN (0.20f * U.widget_unit) #define NODE_LINK_RESOL 12 @@ -196,7 +198,8 @@ void nodelink_batch_end(SpaceNode &snode); void node_draw_link(const bContext &C, const View2D &v2d, const SpaceNode &snode, - const bNodeLink &link); + const bNodeLink &link, + bool selected); /** * Don't do shadows if th_col3 is -1. */ @@ -206,7 +209,8 @@ void node_draw_link_bezier(const bContext &C, const bNodeLink &link, int th_col1, int th_col2, - int th_col3); + int th_col3, + bool selected); /** If v2d not nullptr, it clips and returns 0 if not visible. */ bool node_link_bezier_points(const View2D *v2d, const SpaceNode *snode, diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index 1cfa932356b..299e7e5658c 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -2436,16 +2436,18 @@ void ED_node_link_insert(Main *bmain, ScrArea *area) bNodeSocket *best_input = get_main_socket(ntree, *node_to_insert, SOCK_IN); bNodeSocket *best_output = get_main_socket(ntree, *node_to_insert, SOCK_OUT); - /* Ignore main sockets when the types don't match. */ - if (best_input != nullptr && ntree.typeinfo->validate_link != nullptr && - !ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(old_link->fromsock->type), - static_cast<eNodeSocketDatatype>(best_input->type))) { - best_input = nullptr; - } - if (best_output != nullptr && ntree.typeinfo->validate_link != nullptr && - !ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(best_output->type), - static_cast<eNodeSocketDatatype>(old_link->tosock->type))) { - best_output = nullptr; + if (node_to_insert->type != NODE_REROUTE) { + /* Ignore main sockets when the types don't match. */ + if (best_input != nullptr && ntree.typeinfo->validate_link != nullptr && + !ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(old_link->fromsock->type), + static_cast<eNodeSocketDatatype>(best_input->type))) { + best_input = nullptr; + } + if (best_output != nullptr && ntree.typeinfo->validate_link != nullptr && + !ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(best_output->type), + static_cast<eNodeSocketDatatype>(old_link->tosock->type))) { + best_output = nullptr; + } } bNode *from_node = old_link->fromnode; diff --git a/source/blender/editors/space_outliner/outliner_collections.cc b/source/blender/editors/space_outliner/outliner_collections.cc index 765661aa9d5..f38f6c2855d 100644 --- a/source/blender/editors/space_outliner/outliner_collections.cc +++ b/source/blender/editors/space_outliner/outliner_collections.cc @@ -1071,7 +1071,7 @@ static int collection_isolate_exec(bContext *C, wmOperator *op) static int collection_isolate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "extend"); - if (!RNA_property_is_set(op->ptr, prop) && (event->shift)) { + if (!RNA_property_is_set(op->ptr, prop) && (event->modifier & KM_SHIFT)) { RNA_property_boolean_set(op->ptr, prop, true); } return collection_isolate_exec(C, op); diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.cc b/source/blender/editors/space_outliner/outliner_dragdrop.cc index 0d8ee76d2f0..edd2e5f304f 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.cc +++ b/source/blender/editors/space_outliner/outliner_dragdrop.cc @@ -319,7 +319,7 @@ static bool parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) } if (!allow_parenting_without_modifier_key(space_outliner)) { - if (!event->shift) { + if ((event->modifier & KM_SHIFT) == 0) { return false; } } @@ -417,8 +417,12 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) ListBase *lb = reinterpret_cast<ListBase *>(event->customdata); wmDrag *drag = reinterpret_cast<wmDrag *>(lb->first); - parent_drop_set_parents( - C, op->reports, reinterpret_cast<wmDragID *>(drag->ids.first), par, PAR_OBJECT, event->alt); + parent_drop_set_parents(C, + op->reports, + reinterpret_cast<wmDragID *>(drag->ids.first), + par, + PAR_OBJECT, + event->modifier & KM_ALT); return OPERATOR_FINISHED; } @@ -446,7 +450,7 @@ static bool parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *event) SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); if (!allow_parenting_without_modifier_key(space_outliner)) { - if (!event->shift) { + if ((event->modifier & KM_SHIFT) == 0) { return false; } } @@ -471,7 +475,7 @@ static bool parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *event) case ID_OB: return ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE); case ID_GR: - return event->shift || ELEM(tselem->type, TSE_LIBRARY_OVERRIDE_BASE); + return (event->modifier & KM_SHIFT) || ELEM(tselem->type, TSE_LIBRARY_OVERRIDE_BASE); default: return true; } @@ -496,7 +500,8 @@ static int parent_clear_invoke(bContext *C, wmOperator *UNUSED(op), const wmEven if (GS(drag_id->id->name) == ID_OB) { Object *object = (Object *)drag_id->id; - ED_object_parent_clear(object, event->alt ? CLEAR_PARENT_KEEP_TRANSFORM : CLEAR_PARENT_ALL); + ED_object_parent_clear( + object, (event->modifier & KM_ALT) ? CLEAR_PARENT_KEEP_TRANSFORM : CLEAR_PARENT_ALL); } } @@ -1166,10 +1171,11 @@ static bool collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event &space_outliner->tree, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false); CollectionDrop data; - if (!event->shift && collection_drop_init(C, drag, event->xy, event->ctrl, &data)) { + if (((event->modifier & KM_SHIFT) == 0) && + collection_drop_init(C, drag, event->xy, event->modifier & KM_CTRL, &data)) { TreeElement *te = data.te; TreeStoreElem *tselem = TREESTORE(te); - if (!data.from || event->ctrl) { + if (!data.from || event->modifier & KM_CTRL) { tselem->flag |= TSE_DRAG_INTO; changed = true; } @@ -1210,9 +1216,10 @@ static char *collection_drop_tooltip(bContext *C, const wmEvent *event = win ? win->eventstate : nullptr; CollectionDrop data; - if (event && !event->shift && collection_drop_init(C, drag, xy, event->ctrl, &data)) { + if (event && ((event->modifier & KM_SHIFT) == 0) && + collection_drop_init(C, drag, xy, event->modifier & KM_CTRL, &data)) { TreeElement *te = data.te; - if (!data.from || event->ctrl) { + if (!data.from || event->modifier & KM_CTRL) { return BLI_strdup(TIP_("Link inside Collection")); } switch (data.insert_type) { @@ -1263,7 +1270,7 @@ static int collection_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmE wmDrag *drag = reinterpret_cast<wmDrag *>(lb->first); CollectionDrop data; - if (!collection_drop_init(C, drag, event->xy, event->ctrl, &data)) { + if (!collection_drop_init(C, drag, event->xy, event->modifier & KM_CTRL, &data)) { return OPERATOR_CANCELLED; } @@ -1291,7 +1298,9 @@ static int collection_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmE LISTBASE_FOREACH (wmDragID *, drag_id, &drag->ids) { /* Ctrl enables linking, so we don't need a from collection then. */ - Collection *from = (event->ctrl) ? nullptr : collection_parent_from_ID(drag_id->from_parent); + Collection *from = (event->modifier & KM_CTRL) ? + nullptr : + collection_parent_from_ID(drag_id->from_parent); if (GS(drag_id->id->name) == ID_OB) { /* Move/link object into collection. */ diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index dd7ca128282..2da416c8671 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -166,7 +166,7 @@ static void restrictbutton_bone_visibility_fn(bContext *C, void *poin, void *UNU { Bone *bone = (Bone *)poin; - if (CTX_wm_window(C)->eventstate->shift) { + if (CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) { restrictbutton_recursive_bone(bone, BONE_HIDDEN_P, (bone->flag & BONE_HIDDEN_P) != 0); } } @@ -178,7 +178,7 @@ static void restrictbutton_bone_select_fn(bContext *C, void *UNUSED(poin), void bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); } - if (CTX_wm_window(C)->eventstate->shift) { + if (CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) { restrictbutton_recursive_bone(bone, BONE_UNSELECTABLE, (bone->flag & BONE_UNSELECTABLE) != 0); } @@ -194,7 +194,7 @@ static void restrictbutton_ebone_select_fn(bContext *C, void *poin, void *poin2) ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); } - if (CTX_wm_window(C)->eventstate->shift) { + if (CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) { restrictbutton_recursive_ebone( arm, ebone, BONE_UNSELECTABLE, (ebone->flag & BONE_UNSELECTABLE) != 0); } @@ -210,7 +210,7 @@ static void restrictbutton_ebone_visibility_fn(bContext *C, void *poin, void *po ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); } - if (CTX_wm_window(C)->eventstate->shift) { + if (CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) { restrictbutton_recursive_ebone(arm, ebone, BONE_HIDDEN_A, (ebone->flag & BONE_HIDDEN_A) != 0); } @@ -250,7 +250,7 @@ static void outliner_object_set_flag_recursive_fn(bContext *C, ViewLayer *view_layer = CTX_data_view_layer(C); PointerRNA ptr; - bool extend = (win->eventstate->shift != 0); + bool extend = (win->eventstate->modifier & KM_SHIFT); if (!extend) { return; @@ -571,8 +571,8 @@ static void outliner_collection_set_flag_recursive_fn(bContext *C, ViewLayer *view_layer = CTX_data_view_layer(C); PointerRNA ptr; - bool do_isolate = (win->eventstate->ctrl != 0); - bool extend = (win->eventstate->shift != 0); + bool do_isolate = (win->eventstate->modifier & KM_CTRL); + bool extend = (win->eventstate->modifier & KM_SHIFT); if (!ELEM(true, do_isolate, extend)) { return; @@ -2043,7 +2043,7 @@ static void outliner_mode_toggle_fn(bContext *C, void *tselem_poin, void *UNUSED const bool object_data_shared = (ob->data == tvc.obact->data); wmWindow *win = CTX_wm_window(C); - const bool do_extend = win->eventstate->ctrl != 0 && !object_data_shared; + const bool do_extend = (win->eventstate->modifier & KM_CTRL) && !object_data_shared; outliner_item_mode_toggle(C, &tvc, te, do_extend); } @@ -2592,7 +2592,7 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case OB_CAMERA: data.icon = ICON_OUTLINER_OB_CAMERA; break; - case OB_CURVE: + case OB_CURVES_LEGACY: data.icon = ICON_OUTLINER_OB_CURVE; break; case OB_MBALL: @@ -2655,7 +2655,7 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case ID_ME: data.icon = ICON_OUTLINER_DATA_MESH; break; - case ID_CU: + case ID_CU_LEGACY: data.icon = ICON_OUTLINER_DATA_CURVE; break; case ID_MB: diff --git a/source/blender/editors/space_outliner/outliner_edit.cc b/source/blender/editors/space_outliner/outliner_edit.cc index a6ac2a5a1f3..6916f5fe502 100644 --- a/source/blender/editors/space_outliner/outliner_edit.cc +++ b/source/blender/editors/space_outliner/outliner_edit.cc @@ -240,7 +240,7 @@ static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmE outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region); /* Only toggle once for single click toggling */ - if (event->type == LEFTMOUSE) { + if ((event->type == LEFTMOUSE) && (event->val != KM_CLICK_DRAG)) { return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_outliner/outliner_intern.hh b/source/blender/editors/space_outliner/outliner_intern.hh index bba4bac0e37..0516758e887 100644 --- a/source/blender/editors/space_outliner/outliner_intern.hh +++ b/source/blender/editors/space_outliner/outliner_intern.hh @@ -108,7 +108,7 @@ typedef struct TreeElementIcon { ID_LI, \ ID_OB, \ ID_ME, \ - ID_CU, \ + ID_CU_LEGACY, \ ID_MB, \ ID_NT, \ ID_MA, \ diff --git a/source/blender/editors/space_outliner/outliner_select.cc b/source/blender/editors/space_outliner/outliner_select.cc index df10ce002c3..c6b9d9577b5 100644 --- a/source/blender/editors/space_outliner/outliner_select.cc +++ b/source/blender/editors/space_outliner/outliner_select.cc @@ -1171,7 +1171,7 @@ static void outliner_set_properties_tab(bContext *C, TreeElement *te, TreeStoreE context = BCONTEXT_OBJECT; break; case ID_ME: - case ID_CU: + case ID_CU_LEGACY: case ID_MB: case ID_IM: case ID_LT: diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc index 18c37e08eff..8fcf967bce8 100644 --- a/source/blender/editors/space_outliner/outliner_tools.cc +++ b/source/blender/editors/space_outliner/outliner_tools.cc @@ -117,7 +117,7 @@ static void get_element_operation_type( break; case ID_ME: - case ID_CU: + case ID_CU_LEGACY: case ID_MB: case ID_LT: case ID_LA: @@ -236,7 +236,7 @@ static void unlink_material_fn(bContext *UNUSED(C), totcol = me->totcol; matar = me->mat; } - else if (GS(tsep->id->name) == ID_CU) { + else if (GS(tsep->id->name) == ID_CU_LEGACY) { Curve *cu = (Curve *)tsep->id; totcol = cu->totcol; matar = cu->mat; @@ -766,29 +766,37 @@ static void id_override_library_create_fn(bContext *C, void *user_data) { BLI_assert(TSE_IS_REAL_ID(tselem)); - ID *id_root = tselem->id; + + /* We can only safely apply this operation on one item at a time, so only do it on the active + * one. */ + if ((tselem->flag & TSE_ACTIVE) == 0) { + return; + } + + ID *id_root_reference = tselem->id; OutlinerLibOverrideData *data = reinterpret_cast<OutlinerLibOverrideData *>(user_data); const bool do_hierarchy = data->do_hierarchy; bool success = false; - ID *id_reference = nullptr; + ID *id_instance_hint = nullptr; bool is_override_instancing_object = false; if (tsep != nullptr && tsep->type == TSE_SOME_ID && tsep->id != nullptr && GS(tsep->id->name) == ID_OB && !ID_IS_OVERRIDE_LIBRARY(tsep->id)) { Object *ob = (Object *)tsep->id; - if (ob->type == OB_EMPTY && &ob->instance_collection->id == id_root) { - BLI_assert(GS(id_root->name) == ID_GR); + if (ob->type == OB_EMPTY && &ob->instance_collection->id == id_root_reference) { + BLI_assert(GS(id_root_reference->name) == ID_GR); /* Empty instantiating the collection we override, we need to pass it to BKE overriding code * for proper handling. */ - id_reference = tsep->id; + id_instance_hint = tsep->id; is_override_instancing_object = true; } } - if (ID_IS_OVERRIDABLE_LIBRARY(id_root) || (ID_IS_LINKED(id_root) && do_hierarchy)) { + if (ID_IS_OVERRIDABLE_LIBRARY(id_root_reference) || + (ID_IS_LINKED(id_root_reference) && do_hierarchy)) { Main *bmain = CTX_data_main(C); - id_root->tag |= LIB_TAG_DOIT; + id_root_reference->tag |= LIB_TAG_DOIT; /* For now, remap all local usages of linked ID to local override one here. */ ID *id_iter; @@ -804,38 +812,100 @@ static void id_override_library_create_fn(bContext *C, if (do_hierarchy) { /* Tag all linked parents in tree hierarchy to be also overridden. */ + ID *id_hierarchy_root_reference = id_root_reference; while ((te = te->parent) != nullptr) { if (!TSE_IS_REAL_ID(te->store_elem)) { continue; } - if (!ID_IS_LINKED(te->store_elem->id)) { + + /* Tentative hierarchy root. */ + ID *id_current_hierarchy_root = te->store_elem->id; + + /* If the parent ID is from a different library than the reference root one, we are done + * with upwards tree processing in any case. */ + if (id_current_hierarchy_root->lib != id_root_reference->lib) { + if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id_current_hierarchy_root)) { + /* Virtual overrides (i.e. embedded IDs), we can simply keep processing their parent to + * get an actual real override. */ + continue; + } + + /* If the parent ID is already an override, and is valid (i.e. local override), we can + * access its hierarchy root directly. */ + if (!ID_IS_LINKED(id_current_hierarchy_root) && + ID_IS_OVERRIDE_LIBRARY_REAL(id_current_hierarchy_root) && + id_current_hierarchy_root->override_library->reference->lib == + id_root_reference->lib) { + id_hierarchy_root_reference = + id_current_hierarchy_root->override_library->hierarchy_root; + BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root_reference)); + break; + } + + if (ID_IS_LINKED(id_current_hierarchy_root)) { + /* No local 'anchor' was found for the hierarchy to override, do not proceed, as this + * would most likely generate invisible/confusing/hard to use and manage overrides. */ + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + BKE_reportf(reports, + RPT_WARNING, + "Invalid anchor ('%s') found, needed to create library override from " + "data-block '%s'", + id_current_hierarchy_root->name, + id_root_reference->name); + return; + } + + /* In all other cases, `id_current_hierarchy_root` cannot be a valid hierarchy root, so + * current `id_hierarchy_root_reference` is our best candidate. */ + break; } + /* If some element in the tree needs to be overridden, but its ID is not overridable, * abort. */ - if (!ID_IS_OVERRIDABLE_LIBRARY_HIERARCHY(te->store_elem->id)) { + if (!ID_IS_OVERRIDABLE_LIBRARY_HIERARCHY(id_current_hierarchy_root)) { BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); BKE_reportf(reports, RPT_WARNING, "Could not create library override from data-block '%s', one of its parents " "is not overridable ('%s')", - id_root->name, - te->store_elem->id->name); + id_root_reference->name, + id_current_hierarchy_root->name); return; } - te->store_elem->id->tag |= LIB_TAG_DOIT; + id_current_hierarchy_root->tag |= LIB_TAG_DOIT; + id_hierarchy_root_reference = id_current_hierarchy_root; + } + + /* That case can happen when linked data is a complex mix involving several libraries and/or + * linked overrides. E.g. a mix of overrides from one library, and indirectly linked data + * from another library. Do not try to support such cases for now. */ + if (!((id_hierarchy_root_reference->lib == id_root_reference->lib) || + (!ID_IS_LINKED(id_hierarchy_root_reference) && + ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root_reference) && + id_hierarchy_root_reference->override_library->reference->lib == + id_root_reference->lib))) { + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + BKE_reportf(reports, + RPT_WARNING, + "Invalid hierarchy root ('%s') found, needed to create library override from " + "data-block '%s'", + id_hierarchy_root_reference->name, + id_root_reference->name); + return; } success = BKE_lib_override_library_create(bmain, CTX_data_scene(C), CTX_data_view_layer(C), nullptr, - id_root, - id_reference, + id_root_reference, + id_hierarchy_root_reference, + id_instance_hint, nullptr); } - else if (ID_IS_OVERRIDABLE_LIBRARY(id_root)) { - success = BKE_lib_override_library_create_from_id(bmain, id_root, true) != nullptr; + else if (ID_IS_OVERRIDABLE_LIBRARY(id_root_reference)) { + success = BKE_lib_override_library_create_from_id(bmain, id_root_reference, true) != nullptr; /* Cleanup. */ BKE_main_id_newptr_and_tag_clear(bmain); @@ -845,14 +915,14 @@ static void id_override_library_create_fn(bContext *C, /* Remove the instance empty from this scene, the items now have an overridden collection * instead. */ if (success && is_override_instancing_object) { - ED_object_base_free_and_unlink(bmain, scene, (Object *)id_reference); + ED_object_base_free_and_unlink(bmain, scene, (Object *)id_instance_hint); } } if (!success) { BKE_reportf(reports, RPT_WARNING, "Could not create library override from data-block '%s'", - id_root->name); + id_root_reference->name); } } @@ -1770,13 +1840,15 @@ static const EnumPropertyItem prop_id_op_types[] = { {OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE, "OVERRIDE_LIBRARY_CREATE", 0, - "Make Library Override", - "Make a local override of this linked data-block"}, + "Make Library Override Single", + "Make a single, out-of-hierarchy local override of this linked data-block - only applies to " + "active Outliner item"}, {OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY, "OVERRIDE_LIBRARY_CREATE_HIERARCHY", 0, "Make Library Override Hierarchy", - "Make a local override of this linked data-block, and its hierarchy of dependencies"}, + "Make a local override of this linked data-block, and its hierarchy of dependencies - only " + "applies to active Outliner item"}, {OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET, "OVERRIDE_LIBRARY_RESET", 0, diff --git a/source/blender/editors/space_outliner/outliner_tree.cc b/source/blender/editors/space_outliner/outliner_tree.cc index 1605d5874ae..06a5918f25c 100644 --- a/source/blender/editors/space_outliner/outliner_tree.cc +++ b/source/blender/editors/space_outliner/outliner_tree.cc @@ -579,7 +579,7 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, * would require going over all tfaces, sort images in use. etc... */ break; } - case ID_CU: { + case ID_CU_LEGACY: { Curve *cu = (Curve *)id; if (outliner_animdata_test(cu->adt)) { diff --git a/source/blender/editors/space_outliner/tree/tree_display.cc b/source/blender/editors/space_outliner/tree/tree_display.cc index 6b68f1ee4a4..f9141dffd6a 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.cc +++ b/source/blender/editors/space_outliner/tree/tree_display.cc @@ -7,6 +7,8 @@ #include "DNA_listBase.h" #include "DNA_space_types.h" +#include "BLI_utildefines.h" + #include "tree_display.hh" using namespace blender::ed::outliner; @@ -30,11 +32,11 @@ std::unique_ptr<AbstractTreeDisplay> AbstractTreeDisplay::createFromDisplayMode( case SO_OVERRIDES_LIBRARY: return std::make_unique<TreeDisplayOverrideLibrary>(space_outliner); case SO_VIEW_LAYER: - /* FIXME(Julian): this should not be the default! Return nullptr and handle that as valid - * case. */ - default: return std::make_unique<TreeDisplayViewLayer>(space_outliner); } + + BLI_assert_unreachable(); + return nullptr; } bool AbstractTreeDisplay::hasWarnings() const 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 43d67ee106d..f94727ba356 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 @@ -23,11 +23,6 @@ namespace blender::ed::outliner { /* Convenience/readability. */ -/* Convenience/readability. */ -/* Convenience/readability. */ -/* Convenience/readability. */ -/* Convenience/readability. */ -/* Convenience/readability. */ template<typename T> using List = ListBaseWrapper<T>; TreeDisplayOverrideLibrary::TreeDisplayOverrideLibrary(SpaceOutliner &space_outliner) diff --git a/source/blender/editors/space_outliner/tree/tree_element.hh b/source/blender/editors/space_outliner/tree/tree_element.hh index 996f51eee82..2fbc86705b9 100644 --- a/source/blender/editors/space_outliner/tree/tree_element.hh +++ b/source/blender/editors/space_outliner/tree/tree_element.hh @@ -89,8 +89,8 @@ void tree_element_expand(const AbstractTreeElement &tree_element, SpaceOutliner /** * Get actual warning data of a tree element, if any. * - * \param r_icon The icon to display as warning. - * \param r_message The message to display as warning. + * \param r_icon: The icon to display as warning. + * \param r_message: The message to display as warning. * \return true if there is a warning, false otherwise. */ bool tree_element_warnings_get(struct TreeElement *te, int *r_icon, const char **r_message); diff --git a/source/blender/editors/space_outliner/tree/tree_element_id.cc b/source/blender/editors/space_outliner/tree/tree_element_id.cc index e126b024d52..64c73f57107 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_id.cc +++ b/source/blender/editors/space_outliner/tree/tree_element_id.cc @@ -34,7 +34,7 @@ std::unique_ptr<TreeElementID> TreeElementID::createFromID(TreeElement &legacy_t return std::make_unique<TreeElementIDScene>(legacy_te, (Scene &)id); case ID_OB: case ID_ME: - case ID_CU: + case ID_CU_LEGACY: case ID_MB: case ID_MA: case ID_TE: diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 8c12193fb88..5ac4363e63d 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1636,7 +1636,9 @@ static void sequencer_draw_gpencil_overlay(const bContext *C) ED_annotation_draw_view2d(C, 0); } -/* Draw content and safety borders borders. */ +/** + * Draw content and safety borders. + */ static void sequencer_draw_borders_overlay(const SpaceSeq *sseq, const View2D *v2d, const Scene *scene) @@ -1926,7 +1928,6 @@ static void sequencer_draw_display_buffer(const bContext *C, if (!glsl_used) { immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); immUniformColor3f(1.0f, 1.0f, 1.0f); - immUniform1i("image", 0); } immBegin(GPU_PRIM_TRI_FAN, 4); diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc index 3be890bfcc5..fbdc451cf06 100644 --- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc +++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc @@ -264,7 +264,7 @@ Object *spreadsheet_get_object_eval(const SpaceSpreadsheet *sspreadsheet, return nullptr; } Object *object_orig = (Object *)used_id; - if (!ELEM(object_orig->type, OB_MESH, OB_POINTCLOUD, OB_VOLUME, OB_CURVE, OB_FONT)) { + if (!ELEM(object_orig->type, OB_MESH, OB_POINTCLOUD, OB_VOLUME, OB_CURVES_LEGACY, OB_FONT)) { return nullptr; } diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c index 496f500ef04..55873740491 100644 --- a/source/blender/editors/space_text/text_autocomplete.c +++ b/source/blender/editors/space_text/text_autocomplete.c @@ -408,7 +408,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e case EVT_BACKSPACEKEY: if (event->val == KM_PRESS) { if (tools & TOOL_SUGG_LIST) { - if (event->ctrl) { + if (event->modifier & KM_CTRL) { texttool_suggest_clear(); retval = OPERATOR_CANCELLED; draw = 1; @@ -445,7 +445,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e case EVT_RIGHTARROWKEY: if (event->val == KM_PRESS) { if (tools & TOOL_SUGG_LIST) { - if (event->ctrl) { + if (event->modifier & KM_CTRL) { texttool_suggest_clear(); retval = OPERATOR_CANCELLED; draw = 1; diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index ddba6803f61..3c29b32c2fa 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -3495,7 +3495,7 @@ static int text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event) * (when input method are used for utf8 inputs, the user may assign key event * including alt/ctrl/super like ctrl+m to commit utf8 string. in such case, * the modifiers in the utf8 character event make no sense.) */ - if ((event->ctrl || event->oskey) && !event->utf8_buf[0]) { + if ((event->modifier & (KM_CTRL | KM_OSKEY)) && !event->utf8_buf[0]) { return OPERATOR_PASS_THROUGH; } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 7addda0f8c3..4656540c19b 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -413,6 +413,9 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *region) keymap = WM_keymap_ensure(wm->defaultconf, "Particle", 0, 0); WM_event_add_keymap_handler(®ion->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Sculpt Curves", 0, 0); + WM_event_add_keymap_handler(®ion->handlers, keymap); + /* editfont keymap swallows all... */ keymap = WM_keymap_ensure(wm->defaultconf, "Font", 0, 0); WM_event_add_keymap_handler(®ion->handlers, keymap); @@ -1475,6 +1478,9 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C, case CTX_MODE_EDIT_CURVE: ARRAY_SET_ITEMS(contexts, ".curve_edit"); break; + case CTX_MODE_EDIT_CURVES: + ARRAY_SET_ITEMS(contexts, ".curves_edit"); + break; case CTX_MODE_EDIT_SURFACE: ARRAY_SET_ITEMS(contexts, ".curve_edit"); break; @@ -1523,6 +1529,9 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C, case CTX_MODE_VERTEX_GPENCIL: ARRAY_SET_ITEMS(contexts, ".greasepencil_vertex"); break; + case CTX_MODE_SCULPT_CURVES: + ARRAY_SET_ITEMS(contexts, ".curves_sculpt"); + break; default: break; } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index b77994e28cb..cf52134f5ab 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -355,7 +355,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float has_meshdata = (tot || totedgedata); } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) { TransformMedian_Curve *median = &median_basis.curve; Curve *cu = ob->data; BPoint *bp; @@ -1089,7 +1089,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } } } - else if (ELEM(ob->type, OB_CURVE, OB_SURF) && + else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF) && (apply_vcos || median_basis.curve.b_weight || median_basis.curve.weight || median_basis.curve.radius || median_basis.curve.tilt)) { const TransformMedian_Curve *median = &median_basis.curve, diff --git a/source/blender/editors/space_view3d/view3d_cursor_snap.c b/source/blender/editors/space_view3d/view3d_cursor_snap.c index 785c5ab28c8..53f7b3d5871 100644 --- a/source/blender/editors/space_view3d/view3d_cursor_snap.c +++ b/source/blender/editors/space_view3d/view3d_cursor_snap.c @@ -63,7 +63,7 @@ typedef struct SnapCursorDataIntern { int x; int y; #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK - short shift, ctrl, alt, oskey; + uint8_t modifier; #endif } last_eventstate; @@ -478,10 +478,7 @@ static bool v3d_cursor_eventstate_has_changed(SnapCursorDataIntern *data_intern, } #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK if (!(state && (state->flag & V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE))) { - if ((event->ctrl != data_intern->last_eventstate.ctrl) || - (event->shift != data_intern->last_eventstate.shift) || - (event->alt != data_intern->last_eventstate.alt) || - (event->oskey != data_intern->last_eventstate.oskey)) { + if (event->modifier != data_intern->last_eventstate.modifier) { return true; } } @@ -507,19 +504,13 @@ static bool v3d_cursor_is_snap_invert(SnapCursorDataIntern *data_intern, const w } const wmEvent *event = wm->winactive->eventstate; - if ((event->ctrl == data_intern->last_eventstate.ctrl) && - (event->shift == data_intern->last_eventstate.shift) && - (event->alt == data_intern->last_eventstate.alt) && - (event->oskey == data_intern->last_eventstate.oskey)) { + if (event->modifier == data_intern->last_eventstate.modifier) { /* Nothing has changed. */ return data_intern->snap_data.is_snap_invert; } /* Save new eventstate. */ - data_intern->last_eventstate.ctrl = event->ctrl; - data_intern->last_eventstate.shift = event->shift; - data_intern->last_eventstate.alt = event->alt; - data_intern->last_eventstate.oskey = event->oskey; + data_intern->last_eventstate.modifier = event->modifier; const int snap_on = data_intern->snap_on; @@ -530,10 +521,10 @@ static bool v3d_cursor_is_snap_invert(SnapCursorDataIntern *data_intern, const w } if (kmi->propvalue == snap_on) { - if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) && event->ctrl) || - (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) && event->shift) || - (ELEM(kmi->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY) && event->alt) || - ((kmi->type == EVT_OSKEY) && event->oskey)) { + if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) && (event->modifier & KM_CTRL)) || + (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) && (event->modifier & KM_SHIFT)) || + (ELEM(kmi->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY) && (event->modifier & KM_ALT)) || + ((kmi->type == EVT_OSKEY) && (event->modifier & KM_OSKEY))) { return true; } } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index c4078c4a690..593c4f6e755 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1351,7 +1351,7 @@ static void draw_selected_name( } } } - else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) { + else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVES_LEGACY)) { /* try to display active bone and active shapekey too (if they exist) */ if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) { diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index d6bc7ded92e..5adce170e06 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -832,13 +832,13 @@ void ED_view3d_cursor3d_position(bContext *C, return; } - ED_view3d_calc_zfac(rv3d, cursor_co, &flip); + ED_view3d_calc_zfac_ex(rv3d, cursor_co, &flip); /* Reset the depth based on the view offset (we _know_ the offset is in front of us). */ if (flip) { negate_v3_v3(cursor_co, rv3d->ofs); /* re initialize, no need to check flip again */ - ED_view3d_calc_zfac(rv3d, cursor_co, NULL /* &flip */); + ED_view3d_calc_zfac(rv3d, cursor_co); } if (use_depth) { /* maybe this should be accessed some other way */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c index 6cc197c8a43..a0c010a6813 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c @@ -105,8 +105,8 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; /* Hack: Switch action mode based on key input */ - const bool is_ctrl_pressed = WM_event_modifier_flag(event) & KM_CTRL; - const bool is_shift_pressed = WM_event_modifier_flag(event) & KM_SHIFT; + const bool is_ctrl_pressed = (event->modifier & KM_CTRL) != 0; + const bool is_shift_pressed = (event->modifier & KM_SHIFT) != 0; EDBM_preselect_action_set(gz_ele->psel, PRESELECT_ACTION_TRANSFORM); if (is_ctrl_pressed && !is_shift_pressed) { EDBM_preselect_action_set(gz_ele->psel, PRESELECT_ACTION_CREATE); diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index e1fd96ca1d4..055aac041f1 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -25,6 +25,7 @@ #include "BKE_editmesh.h" #include "BKE_mesh_iterators.h" #include "BKE_mesh_runtime.h" +#include "BKE_mesh_wrapper.h" #include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -334,6 +335,7 @@ void mesh_foreachScreenVert( Mesh *me = editbmesh_get_eval_cage_from_orig( vc->depsgraph, vc->scene, vc->obedit, &CD_MASK_BAREMESH); + me = BKE_mesh_wrapper_ensure_subdivision(vc->obedit, me); ED_view3d_check_mats_rv3d(vc->rv3d); @@ -396,6 +398,7 @@ void mesh_foreachScreenEdge(ViewContext *vc, Mesh *me = editbmesh_get_eval_cage_from_orig( vc->depsgraph, vc->scene, vc->obedit, &CD_MASK_BAREMESH); + me = BKE_mesh_wrapper_ensure_subdivision(vc->obedit, me); ED_view3d_check_mats_rv3d(vc->rv3d); @@ -483,6 +486,7 @@ void mesh_foreachScreenEdge_clip_bb_segment(ViewContext *vc, Mesh *me = editbmesh_get_eval_cage_from_orig( vc->depsgraph, vc->scene, vc->obedit, &CD_MASK_BAREMESH); + me = BKE_mesh_wrapper_ensure_subdivision(vc->obedit, me); ED_view3d_check_mats_rv3d(vc->rv3d); @@ -554,6 +558,7 @@ void mesh_foreachScreenFace( Mesh *me = editbmesh_get_eval_cage_from_orig( vc->depsgraph, vc->scene, vc->obedit, &CD_MASK_BAREMESH); + me = BKE_mesh_wrapper_ensure_subdivision(vc->obedit, me); ED_view3d_check_mats_rv3d(vc->rv3d); data.vc = *vc; diff --git a/source/blender/editors/space_view3d/view3d_navigate.c b/source/blender/editors/space_view3d/view3d_navigate.c index 0305989d142..d1e7f6ffb12 100644 --- a/source/blender/editors/space_view3d/view3d_navigate.c +++ b/source/blender/editors/space_view3d/view3d_navigate.c @@ -396,7 +396,7 @@ ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOp { float tvec[3]; negate_v3_v3(tvec, rv3d->ofs); - vod->init.zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL); + vod->init.zfac = ED_view3d_calc_zfac(rv3d, tvec); } vod->reverse = 1.0f; @@ -544,26 +544,24 @@ static void axis_set_view(bContext *C, void viewmove_apply(ViewOpsData *vod, int x, int y) { - if (ED_view3d_offset_lock_check(vod->v3d, vod->rv3d)) { - vod->rv3d->ofs_lock[0] -= ((vod->prev.event_xy[0] - x) * 2.0f) / (float)vod->region->winx; - vod->rv3d->ofs_lock[1] -= ((vod->prev.event_xy[1] - y) * 2.0f) / (float)vod->region->winy; + const float event_ofs[2] = { + vod->prev.event_xy[0] - x, + vod->prev.event_xy[1] - y, + }; + + if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) { + ED_view3d_camera_view_pan(vod->region, event_ofs); } - else if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) { - const float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f; - vod->rv3d->camdx += (vod->prev.event_xy[0] - x) / (vod->region->winx * zoomfac); - vod->rv3d->camdy += (vod->prev.event_xy[1] - y) / (vod->region->winy * zoomfac); - CLAMP(vod->rv3d->camdx, -1.0f, 1.0f); - CLAMP(vod->rv3d->camdy, -1.0f, 1.0f); + else if (ED_view3d_offset_lock_check(vod->v3d, vod->rv3d)) { + vod->rv3d->ofs_lock[0] -= (event_ofs[0] * 2.0f) / (float)vod->region->winx; + vod->rv3d->ofs_lock[1] -= (event_ofs[1] * 2.0f) / (float)vod->region->winy; } else { float dvec[3]; - float mval_f[2]; - mval_f[0] = x - vod->prev.event_xy[0]; - mval_f[1] = y - vod->prev.event_xy[1]; - ED_view3d_win_to_delta(vod->region, mval_f, dvec, vod->init.zfac); + ED_view3d_win_to_delta(vod->region, event_ofs, vod->init.zfac, dvec); - add_v3_v3(vod->rv3d->ofs, dvec); + sub_v3_v3(vod->rv3d->ofs, dvec); if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) { view3d_boxview_sync(vod->area, vod->region); diff --git a/source/blender/editors/space_view3d/view3d_navigate_dolly.c b/source/blender/editors/space_view3d/view3d_navigate_dolly.c index 06b616e71da..7b6b119294d 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_dolly.c +++ b/source/blender/editors/space_view3d/view3d_navigate_dolly.c @@ -50,9 +50,12 @@ void viewdolly_modal_keymap(wmKeyConfig *keyconf) /* disabled mode switching for now, can re-implement better, later on */ #if 0 - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); - WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); - WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); + WM_modalkeymap_add_item( + keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, KM_ANY, VIEWROT_MODAL_SWITCH_ROTATE); + WM_modalkeymap_add_item( + keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, KM_ANY, VIEWROT_MODAL_SWITCH_ROTATE); + WM_modalkeymap_add_item( + keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, KM_ANY, VIEWROT_MODAL_SWITCH_MOVE); #endif /* assign map to operators */ diff --git a/source/blender/editors/space_view3d/view3d_navigate_move.c b/source/blender/editors/space_view3d/view3d_navigate_move.c index d2fd505a703..071643e9314 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_move.c +++ b/source/blender/editors/space_view3d/view3d_navigate_move.c @@ -43,8 +43,8 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf) keymap = WM_modalkeymap_ensure(keyconf, "View3D Move Modal", modal_items); /* items for modal map */ - WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); - WM_modalkeymap_add_item(keymap, EVT_ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, KM_ANY, VIEW_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, EVT_ESCKEY, KM_PRESS, KM_ANY, 0, KM_ANY, VIEW_MODAL_CONFIRM); /* disabled mode switching for now, can re-implement better, later on */ #if 0 diff --git a/source/blender/editors/space_view3d/view3d_navigate_ndof.c b/source/blender/editors/space_view3d/view3d_navigate_ndof.c index ced8eca710b..1ce9bdcb211 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_ndof.c +++ b/source/blender/editors/space_view3d/view3d_navigate_ndof.c @@ -48,7 +48,7 @@ static float view3d_ndof_pan_speed_calc_ex(RegionView3D *rv3d, const float depth float speed = rv3d->pixsize * NDOF_PIXELS_PER_SECOND; if (rv3d->is_persp) { - speed *= ED_view3d_calc_zfac(rv3d, depth_pt, NULL); + speed *= ED_view3d_calc_zfac(rv3d, depth_pt); } return speed; @@ -347,6 +347,70 @@ void view3d_ndof_fly(const wmNDOFMotionData *ndof, /** \} */ /* -------------------------------------------------------------------- */ +/** \name NDOF Camera View Support + * \{ */ + +/** + * 2D orthographic style NDOF navigation within the camera view. + * Support navigating the camera view instead of leaving the camera-view and navigating in 3D. + */ +static int view3d_ndof_cameraview_pan_zoom(bContext *C, const wmEvent *event) +{ + const wmNDOFMotionData *ndof = event->customdata; + View3D *v3d = CTX_wm_view3d(C); + ARegion *region = CTX_wm_region(C); + RegionView3D *rv3d = region->regiondata; + + ED_view3d_smooth_view_force_finish(C, v3d, region); + + if ((v3d->camera && (rv3d->persp == RV3D_CAMOB) && (v3d->flag2 & V3D_LOCK_CAMERA) == 0)) { + /* pass */ + } + else { + return OPERATOR_PASS_THROUGH; + } + + const bool has_translate = !is_zero_v2(ndof->tvec); + const bool has_zoom = ndof->tvec[2] != 0.0f; + + /* NOTE(@campbellbarton): In principle rotating could pass through to regular + * non-camera NDOF behavior (exiting the camera-view and rotating). + * Disabled this block since in practice it's difficult to control NDOF devices + * to perform some rotation with absolutely no translation. Causing rotation to + * randomly exit from the user perspective. Adjusting the dead-zone could avoid + * the motion feeling *glitchy* although in my own tests even then it didn't work reliably. + * Leave rotating out of camera-view disabled unless it can be made to work reliably. */ + if (!(has_translate || has_zoom)) { + // return OPERATOR_PASS_THROUGH; + } + + bool changed = false; + + if (has_translate) { + const float speed = ndof->dt * NDOF_PIXELS_PER_SECOND; + float event_ofs[2] = {ndof->tvec[0] * speed, ndof->tvec[1] * speed}; + if (ED_view3d_camera_view_pan(region, event_ofs)) { + changed = true; + } + } + + if (has_zoom) { + const float scale = 1.0f + (ndof->dt * ndof->tvec[2]); + if (ED_view3d_camera_view_zoom_scale(rv3d, scale)) { + changed = true; + } + } + + if (changed) { + ED_region_tag_redraw(region); + return OPERATOR_FINISHED; + } + return OPERATOR_CANCELLED; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name NDOF Orbit/Translate Operator * \{ */ @@ -436,6 +500,13 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev return OPERATOR_CANCELLED; } + if (U.ndof_flag & NDOF_CAMERA_PAN_ZOOM) { + const int camera_retval = view3d_ndof_cameraview_pan_zoom(C, event); + if (camera_retval != OPERATOR_PASS_THROUGH) { + return camera_retval; + } + } + const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); ViewOpsData *vod; View3D *v3d; @@ -550,6 +621,13 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e return OPERATOR_CANCELLED; } + if (U.ndof_flag & NDOF_CAMERA_PAN_ZOOM) { + const int camera_retval = view3d_ndof_cameraview_pan_zoom(C, event); + if (camera_retval != OPERATOR_PASS_THROUGH) { + return camera_retval; + } + } + const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); diff --git a/source/blender/editors/space_view3d/view3d_navigate_roll.c b/source/blender/editors/space_view3d/view3d_navigate_roll.c index 56bd9c93216..9c070fb0341 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_roll.c +++ b/source/blender/editors/space_view3d/view3d_navigate_roll.c @@ -24,8 +24,17 @@ /** \name View Roll Operator * \{ */ -static void view_roll_angle( - ARegion *region, float quat[4], const float orig_quat[4], const float dvec[3], float angle) +/** + * \param use_axis_view: When true, keep axis-aligned orthographic views + * (when rotating in 90 degree increments). While this may seem obscure some NDOF + * devices have key shortcuts to do this (see #NDOF_BUTTON_ROLL_CW & #NDOF_BUTTON_ROLL_CCW). + */ +static void view_roll_angle(ARegion *region, + float quat[4], + const float orig_quat[4], + const float dvec[3], + float angle, + bool use_axis_view) { RegionView3D *rv3d = region->regiondata; float quat_mul[4]; @@ -38,7 +47,16 @@ static void view_roll_angle( /* avoid precision loss over time */ normalize_qt(quat); - rv3d->view = RV3D_VIEW_USER; + if (use_axis_view && RV3D_VIEW_IS_AXIS(rv3d->view) && (fabsf(angle) == (float)M_PI_2)) { + if (ED_view3d_quat_to_axis_view(quat, 0.01f, &rv3d->view, &rv3d->view_axis_roll)) { + if (rv3d->view != RV3D_VIEW_USER) { + ED_view3d_quat_from_axis_view(rv3d->view, rv3d->view_axis_roll, quat_mul); + } + } + } + else { + rv3d->view = RV3D_VIEW_USER; + } } static void viewroll_apply(ViewOpsData *vod, int x, int y) @@ -46,7 +64,8 @@ static void viewroll_apply(ViewOpsData *vod, int x, int y) float angle = BLI_dial_angle(vod->init.dial, (const float[2]){x, y}); if (angle != 0.0f) { - view_roll_angle(vod->region, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle); + view_roll_angle( + vod->region, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle, false); } if (vod->use_dyn_ofs) { @@ -169,7 +188,7 @@ static int viewroll_exec(bContext *C, wmOperator *op) normalize_v3_v3(mousevec, rv3d->viewinv[2]); negate_v3(mousevec); - view_roll_angle(region, quat_new, rv3d->viewquat, mousevec, angle); + view_roll_angle(region, quat_new, rv3d->viewquat, mousevec, angle, true); const float *dyn_ofs_pt = NULL; float dyn_ofs[3]; diff --git a/source/blender/editors/space_view3d/view3d_navigate_rotate.c b/source/blender/editors/space_view3d/view3d_navigate_rotate.c index 774a8983c67..11de5463cdb 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_rotate.c +++ b/source/blender/editors/space_view3d/view3d_navigate_rotate.c @@ -383,7 +383,7 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event) int event_xy[2]; if (event->type == MOUSEPAN) { - if (event->is_direction_inverted) { + if (event->flag & WM_EVENT_SCROLL_INVERT) { event_xy[0] = 2 * event->xy[0] - event->prev_xy[0]; event_xy[1] = 2 * event->xy[1] - event->prev_xy[1]; } diff --git a/source/blender/editors/space_view3d/view3d_navigate_zoom.c b/source/blender/editors/space_view3d/view3d_navigate_zoom.c index 8eb8fffaa31..5f6f9fde324 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_zoom.c +++ b/source/blender/editors/space_view3d/view3d_navigate_zoom.c @@ -125,18 +125,18 @@ static void view_zoom_to_window_xy_3d(ARegion *region, float dfac, const int zoo float dvec[3]; float tvec[3]; float tpos[3]; - float mval_f[2]; + float xy_delta[2]; float zfac; negate_v3_v3(tpos, rv3d->ofs); - mval_f[0] = (float)(((zoom_xy[0] - region->winrct.xmin) * 2) - region->winx) / 2.0f; - mval_f[1] = (float)(((zoom_xy[1] - region->winrct.ymin) * 2) - region->winy) / 2.0f; + xy_delta[0] = (float)(((zoom_xy[0] - region->winrct.xmin) * 2) - region->winx) / 2.0f; + xy_delta[1] = (float)(((zoom_xy[1] - region->winrct.ymin) * 2) - region->winy) / 2.0f; /* Project cursor position into 3D space */ - zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL); - ED_view3d_win_to_delta(region, mval_f, dvec, zfac); + zfac = ED_view3d_calc_zfac(rv3d, tpos); + ED_view3d_win_to_delta(region, xy_delta, zfac, dvec); /* Calculate view target position for dolly */ add_v3_v3v3(tvec, tpos, dvec); diff --git a/source/blender/editors/space_view3d/view3d_navigate_zoom_border.c b/source/blender/editors/space_view3d/view3d_navigate_zoom_border.c index 4e909151ce4..f834efe4a7b 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_zoom_border.c +++ b/source/blender/editors/space_view3d/view3d_navigate_zoom_border.c @@ -125,7 +125,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) negate_v3_v3(new_ofs, p); } else { - float mval_f[2]; + float xy_delta[2]; float zfac; /* We can't use the depth, fallback to the old way that doesn't set the center depth */ @@ -134,12 +134,12 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) { float tvec[3]; negate_v3_v3(tvec, new_ofs); - zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL); + zfac = ED_view3d_calc_zfac(rv3d, tvec); } - mval_f[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f; - mval_f[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f; - ED_view3d_win_to_delta(region, mval_f, dvec, zfac); + xy_delta[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f; + xy_delta[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f; + ED_view3d_win_to_delta(region, xy_delta, zfac, dvec); /* center the view to the center of the rectangle */ sub_v3_v3(new_ofs, dvec); } diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c index 06b848571d8..98fb914cda9 100644 --- a/source/blender/editors/space_view3d/view3d_placement.c +++ b/source/blender/editors/space_view3d/view3d_placement.c @@ -727,6 +727,17 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv V3DSnapCursorState *snap_state_new = ED_view3d_cursor_snap_active(); if (snap_state_new) { ipd->snap_state = snap_state = snap_state_new; + + /* For drag events, update the location since it will be set from the drag-start. + * This is needed as cursor-drawing doesn't deal with drag events and will use + * the current cursor location instead of the drag-start. */ + if (event->val == KM_CLICK_DRAG) { + /* Set this flag so snapping always updated. */ + int flag_orig = snap_state_new->flag; + snap_state_new->flag |= V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE; + ED_view3d_cursor_snap_data_get(snap_state_new, C, event->mval[0], event->mval[1]); + snap_state_new->flag = flag_orig; + } } snap_state->draw_point = true; diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 2cf9ac0a52e..85d239507ce 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -276,7 +276,7 @@ float ED_view3d_pixel_size_no_ui_scale(const RegionView3D *rv3d, const float co[ return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize; } -float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3], bool *r_flip) +float ED_view3d_calc_zfac_ex(const RegionView3D *rv3d, const float co[3], bool *r_flip) { float zfac = mul_project_m4_v3_zfac(rv3d->persmat, co); @@ -299,10 +299,15 @@ float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3], bool *r_f return zfac; } +float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3]) +{ + return ED_view3d_calc_zfac_ex(rv3d, co, NULL); +} + float ED_view3d_calc_depth_for_comparison(const RegionView3D *rv3d, const float co[3]) { if (rv3d->is_persp) { - return ED_view3d_calc_zfac(rv3d, co, NULL); + return ED_view3d_calc_zfac(rv3d, co); } return -dot_v3v3(rv3d->viewinv[2], co); } @@ -436,8 +441,8 @@ bool view3d_get_view_aligned_coordinate(ARegion *region, if (ret == V3D_PROJ_RET_OK) { const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]), (float)(mval_cpy[1] - mval[1])}; - const float zfac = ED_view3d_calc_zfac(rv3d, fp, NULL); - ED_view3d_win_to_delta(region, mval_f, dvec, zfac); + const float zfac = ED_view3d_calc_zfac(rv3d, fp); + ED_view3d_win_to_delta(region, mval_f, zfac, dvec); sub_v3_v3(fp, dvec); return true; @@ -584,57 +589,57 @@ bool ED_view3d_win_to_3d_on_plane_with_fallback(const ARegion *region, } void ED_view3d_win_to_delta(const ARegion *region, - const float mval[2], - float out[3], - const float zfac) + const float xy_delta[2], + const float zfac, + float r_out[3]) { RegionView3D *rv3d = region->regiondata; float dx, dy; - dx = 2.0f * mval[0] * zfac / region->winx; - dy = 2.0f * mval[1] * zfac / region->winy; + dx = 2.0f * xy_delta[0] * zfac / region->winx; + dy = 2.0f * xy_delta[1] * zfac / region->winy; - out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy); - out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy); - out[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy); + r_out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy); + r_out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy); + r_out[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy); } -void ED_view3d_win_to_origin(const ARegion *region, const float mval[2], float out[3]) +void ED_view3d_win_to_origin(const ARegion *region, const float mval[2], float r_out[3]) { RegionView3D *rv3d = region->regiondata; if (rv3d->is_persp) { - copy_v3_v3(out, rv3d->viewinv[3]); + copy_v3_v3(r_out, rv3d->viewinv[3]); } else { - out[0] = 2.0f * mval[0] / region->winx - 1.0f; - out[1] = 2.0f * mval[1] / region->winy - 1.0f; + r_out[0] = 2.0f * mval[0] / region->winx - 1.0f; + r_out[1] = 2.0f * mval[1] / region->winy - 1.0f; if (rv3d->persp == RV3D_CAMOB) { - out[2] = -1.0f; + r_out[2] = -1.0f; } else { - out[2] = 0.0f; + r_out[2] = 0.0f; } - mul_project_m4_v3(rv3d->persinv, out); + mul_project_m4_v3(rv3d->persinv, r_out); } } -void ED_view3d_win_to_vector(const ARegion *region, const float mval[2], float out[3]) +void ED_view3d_win_to_vector(const ARegion *region, const float mval[2], float r_out[3]) { RegionView3D *rv3d = region->regiondata; if (rv3d->is_persp) { - out[0] = 2.0f * (mval[0] / region->winx) - 1.0f; - out[1] = 2.0f * (mval[1] / region->winy) - 1.0f; - out[2] = -0.5f; - mul_project_m4_v3(rv3d->persinv, out); - sub_v3_v3(out, rv3d->viewinv[3]); + r_out[0] = 2.0f * (mval[0] / region->winx) - 1.0f; + r_out[1] = 2.0f * (mval[1] / region->winy) - 1.0f; + r_out[2] = -0.5f; + mul_project_m4_v3(rv3d->persinv, r_out); + sub_v3_v3(r_out, rv3d->viewinv[3]); } else { - negate_v3_v3(out, rv3d->viewinv[2]); + negate_v3_v3(r_out, rv3d->viewinv[2]); } - normalize_v3(out); + normalize_v3(r_out); } bool ED_view3d_win_to_segment_clipped(struct Depsgraph *depsgraph, diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index f08c53fff47..e380a08dcc7 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1313,7 +1313,7 @@ static bool view3d_lasso_select(bContext *C, case OB_MESH: changed = do_lasso_select_mesh(vc, wm_userdata, mcoords, mcoords_len, sel_op); break; - case OB_CURVE: + case OB_CURVES_LEGACY: case OB_SURF: changed = do_lasso_select_curve(vc, mcoords, mcoords_len, sel_op); break; @@ -2695,7 +2695,7 @@ static int view3d_select_exec(bContext *C, wmOperator *op) retval = ED_lattice_deselect_all_multi(C); } } - else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { + else if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { retval = ED_curve_editnurb_select_pick(C, location, extend, deselect, toggle); if (!retval && deselect_all) { retval = ED_curve_deselect_all_multi(C); @@ -3586,7 +3586,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; - case OB_CURVE: + case OB_CURVES_LEGACY: case OB_SURF: changed = do_nurbs_box_select(&vc, &rect, sel_op); if (changed) { @@ -4342,7 +4342,7 @@ static bool obedit_circle_select(bContext *C, case OB_MESH: changed = mesh_circle_select(vc, wm_userdata, sel_op, mval, rad); break; - case OB_CURVE: + case OB_CURVES_LEGACY: case OB_SURF: changed = nurbscurve_circle_select(vc, sel_op, mval, rad); break; diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index 8a219cd96d1..3e788f2d643 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -510,6 +510,39 @@ bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *re /** \} */ /* -------------------------------------------------------------------- */ +/** \name Camera View Utilities + * + * Utilities for manipulating the camera-view. + * \{ */ + +bool ED_view3d_camera_view_zoom_scale(RegionView3D *rv3d, const float scale) +{ + const float camzoom_init = rv3d->camzoom; + float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); + /* Clamp both before and after conversion to prevent NAN on negative values. */ + + zoomfac = zoomfac * scale; + CLAMP(zoomfac, RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR); + rv3d->camzoom = BKE_screen_view3d_zoom_from_fac(zoomfac); + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + return (rv3d->camzoom != camzoom_init); +} + +bool ED_view3d_camera_view_pan(ARegion *region, const float event_ofs[2]) +{ + RegionView3D *rv3d = region->regiondata; + const float camdxy_init[2] = {rv3d->camdx, rv3d->camdy}; + const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f; + rv3d->camdx += event_ofs[0] / (region->winx * zoomfac); + rv3d->camdy += event_ofs[1] / (region->winy * zoomfac); + CLAMP(rv3d->camdx, -1.0f, 1.0f); + CLAMP(rv3d->camdy, -1.0f, 1.0f); + return (camdxy_init[0] != rv3d->camdx) || (camdxy_init[1] != rv3d->camdy); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Camera Lock API * * Lock the camera to the 3D Viewport, allowing view manipulation to transform the camera. diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 3bcc1b2968e..fd01f708ed2 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -177,8 +177,8 @@ void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy) r_vec[1] = dy; } else { - const float mval_f[2] = {(float)dx, (float)dy}; - ED_view3d_win_to_delta(t->region, mval_f, r_vec, t->zfac); + const float xy_delta[2] = {(float)dx, (float)dy}; + ED_view3d_win_to_delta(t->region, xy_delta, t->zfac, r_vec); } } else if (t->spacetype == SPACE_IMAGE) { @@ -1150,10 +1150,10 @@ int transformEvent(TransInfo *t, const wmEvent *event) else if (event->val == KM_PRESS) { switch (event->type) { case EVT_CKEY: - if (event->is_repeat) { + if (event->flag & WM_EVENT_IS_REPEAT) { break; } - if (event->alt) { + if (event->modifier & KM_ALT) { if (!(t->options & CTX_NO_PET)) { t->flag ^= T_PROP_CONNECTED; sort_trans_data_dist(t); @@ -1164,10 +1164,10 @@ int transformEvent(TransInfo *t, const wmEvent *event) } break; case EVT_OKEY: - if (event->is_repeat) { + if (event->flag & WM_EVENT_IS_REPEAT) { break; } - if (t->flag & T_PROP_EDIT && event->shift) { + if ((t->flag & T_PROP_EDIT) && (event->modifier & KM_SHIFT)) { t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MAX; calculatePropRatio(t); t->redraw |= TREDRAW_HARD; @@ -1175,7 +1175,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) } break; case EVT_PADPLUSKEY: - if (event->alt && t->flag & T_PROP_EDIT) { + if ((event->modifier & KM_ALT) && (t->flag & T_PROP_EDIT)) { t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) { t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->clip_end); @@ -1186,7 +1186,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) } break; case EVT_PADMINUS: - if (event->alt && t->flag & T_PROP_EDIT) { + if ((event->modifier & KM_ALT) && (t->flag & T_PROP_EDIT)) { t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; calculatePropRatio(t); t->redraw = TREDRAW_HARD; @@ -1202,7 +1202,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) } break; case EVT_NKEY: - if (event->is_repeat) { + if (event->flag & WM_EVENT_IS_REPEAT) { break; } if (ELEM(t->mode, TFM_ROTATION)) { @@ -1697,7 +1697,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* Needed to translate tweak events to mouse buttons. */ t->launch_event = event ? WM_userdef_event_type_from_keymap_type(event->type) : -1; - t->is_launch_event_tweak = event ? ISTWEAK(event->type) : false; + t->is_launch_event_drag = event ? (event->val == KM_CLICK_DRAG) : false; /* XXX Remove this when wm_operator_call_internal doesn't use window->eventstate * (which can have type = 0) */ @@ -1780,10 +1780,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } if (kmi->propvalue == TFM_MODAL_SNAP_INV_ON && kmi->val == KM_PRESS) { - if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) && event->ctrl) || - (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) && event->shift) || - (ELEM(kmi->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY) && event->alt) || - ((kmi->type == EVT_OSKEY) && event->oskey)) { + if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) && + (event->modifier & KM_CTRL)) || + (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) && + (event->modifier & KM_SHIFT)) || + (ELEM(kmi->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY) && (event->modifier & KM_ALT)) || + ((kmi->type == EVT_OSKEY) && (event->modifier & KM_OSKEY))) { t->modifiers |= MOD_SNAP_INVERT; } break; @@ -1967,7 +1969,7 @@ bool checkUseAxisMatrix(TransInfo *t) /* currently only checks for editmode */ if (t->flag & T_EDIT) { if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && - (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) { + (ELEM(t->obedit_type, OB_MESH, OB_CURVES_LEGACY, OB_MBALL, OB_ARMATURE))) { /* not all editmode supports axis-matrix */ return true; } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 757c11f1179..3ee5868d5be 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -592,9 +592,11 @@ typedef struct TransInfo { /*************** NEW STUFF *********************/ /** event type used to launch transform. */ short launch_event; - /** Is the actual launch event a tweak event? (launch_event above is set to the corresponding - * mouse button then.) */ - bool is_launch_event_tweak; + /** + * Is the actual launch event a drag event? + * (`launch_event` is set to the corresponding mouse button then.) + */ + bool is_launch_event_drag; bool is_orient_default_overwrite; diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 64ef170a13f..81b35e4539b 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -1041,8 +1041,7 @@ static void setNearestAxis3d(TransInfo *t) * and to overflow the short integers. * The formula used is a bit stupid, just a simplification of the subtraction * of two 2D points 30 pixels apart (that's the last factor in the formula) after - * projecting them with ED_view3d_win_to_delta and then get the length of that vector. - */ + * projecting them with #ED_view3d_win_to_delta and then get the length of that vector. */ zfac = mul_project_m4_v3_zfac(t->persmat, t->center_global); zfac = len_v3(t->persinv[0]) * 2.0f / t->region->winx * zfac * 30.0f; diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 95b810daeaf..4a2169b381e 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -1040,7 +1040,7 @@ static void init_proportional_edit(TransInfo *t) /* Already calculated by uv_set_connectivity_distance. */ } else if (convert_type == TC_CURVE_VERTS) { - BLI_assert(t->obedit_type == OB_CURVE); + BLI_assert(t->obedit_type == OB_CURVES_LEGACY); set_prop_dist(t, false); } else { @@ -1049,7 +1049,7 @@ static void init_proportional_edit(TransInfo *t) sort_trans_data_dist(t); } - else if (ELEM(t->obedit_type, OB_CURVE)) { + else if (ELEM(t->obedit_type, OB_CURVES_LEGACY)) { /* Needed because bezier handles can be partially selected * and are still added into transform data. */ sort_trans_data_selected_first(t); @@ -1286,7 +1286,7 @@ static eTConvertType convert_type_get(const TransInfo *t, Object **r_obj_armatur convert_type = TC_MESH_VERTS; } } - else if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) { + else if (ELEM(t->obedit_type, OB_CURVES_LEGACY, OB_SURF)) { convert_type = TC_CURVE_VERTS; } else if (t->obedit_type == OB_LATTICE) { diff --git a/source/blender/editors/transform/transform_convert_graph.c b/source/blender/editors/transform/transform_convert_graph.c index 608fd59c8b7..54222fbb117 100644 --- a/source/blender/editors/transform/transform_convert_graph.c +++ b/source/blender/editors/transform/transform_convert_graph.c @@ -161,7 +161,7 @@ static void graph_bezt_get_transform_selection(const TransInfo *t, bool left = use_handle ? ((bezt->f1 & SELECT) != 0) : key; bool right = use_handle ? ((bezt->f3 & SELECT) != 0) : key; - if (use_handle && t->is_launch_event_tweak) { + if (use_handle && t->is_launch_event_drag) { if (sipo->runtime.flag & SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT) { key = right = false; } diff --git a/source/blender/editors/transform/transform_convert_object_texspace.c b/source/blender/editors/transform/transform_convert_object_texspace.c index e12d0db8758..763af1f3384 100644 --- a/source/blender/editors/transform/transform_convert_object_texspace.c +++ b/source/blender/editors/transform/transform_convert_object_texspace.c @@ -44,7 +44,7 @@ void createTransTexspace(TransInfo *t) } id = ob->data; - if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) { + if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU_LEGACY, ID_MB)) { BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform"); return; } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 1d86a8f9413..8987325145c 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -731,7 +731,8 @@ void postTrans(bContext *C, TransInfo *t) if (t->data_len_all != 0) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { /* free data malloced per trans-data */ - if (ELEM(t->obedit_type, OB_CURVE, OB_SURF, OB_GPENCIL) || (t->spacetype == SPACE_GRAPH)) { + if (ELEM(t->obedit_type, OB_CURVES_LEGACY, OB_SURF, OB_GPENCIL) || + (t->spacetype == SPACE_GRAPH)) { TransData *td = tc->data; for (int a = 0; a < tc->data_len; a++, td++) { if (td->flag & TD_BEZTRIPLE) { @@ -1145,7 +1146,7 @@ void calculateCenter(TransInfo *t) projectFloatView(t, axis, t->center2d); - /* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */ + /* Rotate only needs correct 2d center, grab needs #ED_view3d_calc_zfac() value. */ if (t->mode == TFM_TRANSLATION) { copy_v3_v3(t->center_global, axis); } @@ -1154,17 +1155,16 @@ void calculateCenter(TransInfo *t) } if (t->spacetype == SPACE_VIEW3D) { - /* ED_view3d_calc_zfac() defines a factor for perspective depth correction, - * used in ED_view3d_win_to_delta() */ + /* #ED_view3d_calc_zfac() defines a factor for perspective depth correction, + * used in #ED_view3d_win_to_delta(). */ - /* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW - * and never used in other cases. + /* NOTE: `t->zfac` is only used #convertViewVec only in cases operator was invoked in + * #RGN_TYPE_WINDOW and never used in other cases. * - * We need special case here as well, since ED_view3d_calc_zfac will crash when called - * for a region different from RGN_TYPE_WINDOW. - */ + * We need special case here as well, since #ED_view3d_calc_zfac will crash when called + * for a region different from #RGN_TYPE_WINDOW. */ if (t->region->regiontype == RGN_TYPE_WINDOW) { - t->zfac = ED_view3d_calc_zfac(t->region->regiondata, t->center_global, NULL); + t->zfac = ED_view3d_calc_zfac(t->region->regiondata, t->center_global); } else { t->zfac = 0.0f; diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c index d2b2d2f116e..da601328192 100644 --- a/source/blender/editors/transform/transform_gizmo_2d.c +++ b/source/blender/editors/transform/transform_gizmo_2d.c @@ -669,6 +669,7 @@ static void gizmo2d_xform_invoke_prepare(const bContext *C, float c[3] = {mid[0], mid[1], 0.0f}; float orient_matrix[3][3]; + unit_m3(orient_matrix); ScrArea *area = CTX_wm_area(C); diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 7e121a717aa..f07fadb7fc1 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -816,7 +816,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, } FOREACH_EDIT_OBJECT_END(); } - else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { + else if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) { Curve *cu = ob_iter->data; Nurb *nu; @@ -1869,7 +1869,7 @@ static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C, if (axis != -1) { wmWindow *win = CTX_wm_window(C); /* Swap single axis for two-axis constraint. */ - bool flip = win->eventstate->shift; + bool flip = (win->eventstate->modifier & KM_SHIFT) != 0; BLI_assert(axis_idx != -1); const short axis_type = gizmo_get_axis_type(axis_idx); if (axis_type != MAN_AXES_ROTATE) { diff --git a/source/blender/editors/transform/transform_gizmo_extrude_3d.c b/source/blender/editors/transform/transform_gizmo_extrude_3d.c index 6873ea862ce..f6f43f867ae 100644 --- a/source/blender/editors/transform/transform_gizmo_extrude_3d.c +++ b/source/blender/editors/transform/transform_gizmo_extrude_3d.c @@ -153,7 +153,7 @@ static void gizmo_mesh_extrude_setup(const bContext *C, wmGizmoGroup *gzgroup) op_idname = "ARMATURE_OT_extrude_move"; ggd->normal_axis = 1; } - else if (obact->type == OB_CURVE) { + else if (obact->type == OB_CURVES_LEGACY) { op_idname = "CURVE_OT_extrude_move"; ggd->normal_axis = 2; } diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index b6c4002b1c7..6162dfc9bb5 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -57,7 +57,7 @@ bool transdata_check_local_center(const TransInfo *t, short around) return ((around == V3D_AROUND_LOCAL_ORIGINS) && ((t->options & (CTX_OBJECT | CTX_POSE_BONE)) || /* implicit: (t->flag & T_EDIT) */ - (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE, OB_GPENCIL)) || + (ELEM(t->obedit_type, OB_MESH, OB_CURVES_LEGACY, OB_MBALL, OB_ARMATURE, OB_GPENCIL)) || (t->spacetype == SPACE_GRAPH) || (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE | CTX_SEQUENCER_IMAGE)))); } diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c index 0afc527d4a8..77c5707d814 100644 --- a/source/blender/editors/transform/transform_mode_vert_slide.c +++ b/source/blender/editors/transform/transform_mode_vert_slide.c @@ -146,9 +146,9 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2] * by finding the closest edge in local-space. * However this skews the outcome with non-uniform-scale. */ - /* first get the direction of the original mouse position */ + /* First get the direction of the original mouse position. */ sub_v2_v2v2(dir, imval_fl, mval_fl); - ED_view3d_win_to_delta(t->region, dir, dir, t->zfac); + ED_view3d_win_to_delta(t->region, dir, t->zfac, dir); normalize_v3(dir); for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { @@ -425,18 +425,18 @@ void drawVertSlide(TransInfo *t) /* direction from active vertex! */ if ((t->mval[0] != t->mouse.imval[0]) || (t->mval[1] != t->mouse.imval[1])) { float zfac; - float mval_ofs[2]; + float xy_delta[2]; float co_orig_3d[3]; float co_dest_3d[3]; - mval_ofs[0] = t->mval[0] - t->mouse.imval[0]; - mval_ofs[1] = t->mval[1] - t->mouse.imval[1]; + xy_delta[0] = t->mval[0] - t->mouse.imval[0]; + xy_delta[1] = t->mval[1] - t->mouse.imval[1]; mul_v3_m4v3( co_orig_3d, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, curr_sv->co_orig_3d); - zfac = ED_view3d_calc_zfac(t->region->regiondata, co_orig_3d, NULL); + zfac = ED_view3d_calc_zfac(t->region->regiondata, co_orig_3d); - ED_view3d_win_to_delta(t->region, mval_ofs, co_dest_3d, zfac); + ED_view3d_win_to_delta(t->region, xy_delta, zfac, co_dest_3d); invert_m4_m4(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 3722e83e451..936aca7d2e0 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -628,7 +628,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) "Proportional Falloff", "Falloff type for proportional editing mode"); /* Abusing id_curve :/ */ - RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE_LEGACY); RNA_def_float(ot->srna, "proportional_size", 1, diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 6ca61d415ea..c0d943e17ee 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -350,7 +350,7 @@ bool BIF_createTransformOrientation(bContext *C, else if (obedit->type == OB_ARMATURE) { ts = createBoneSpace(C, reports, name, overwrite); } - else if (obedit->type == OB_CURVE) { + else if (obedit->type == OB_CURVES_LEGACY) { ts = createCurveSpace(C, reports, name, overwrite); } } @@ -984,7 +984,7 @@ int getTransformOrientation_ex(ViewLayer *view_layer, negate_v3(plane); } /* end editmesh */ - else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { + else if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { Curve *cu = obedit->data; Nurb *nu = NULL; int a; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index ce0cf3aa6cb..2f3c021ba38 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -86,7 +86,7 @@ int BIF_snappingSupported(Object *obedit) int status = 0; /* only support object mesh, armature, curves */ - if (obedit == NULL || ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) { + if (obedit == NULL || ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVES_LEGACY, OB_LATTICE, OB_MBALL)) { status = 1; } @@ -308,7 +308,8 @@ eRedrawFlag handleSnapping(TransInfo *t, const wmEvent *event) eRedrawFlag status = TREDRAW_NOTHING; #if 0 /* XXX need a proper selector for all snap mode */ - if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift) { + if (BIF_snappingSupported(t->obedit) && (event->type == EVT_TABKEY) && + (event->modifier & KM_SHIFT)) { /* toggle snap and reinit */ t->settings->snap_flag ^= SCE_SNAP; initSnapping(t, NULL); @@ -583,7 +584,7 @@ static short snap_mode_from_scene(TransInfo *t) /* All obedit types will match. */ const int obedit_type = t->obedit_type; if ((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) || - ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL, -1)) { + ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVES_LEGACY, OB_LATTICE, OB_MBALL, -1)) { r_snap_mode = ts->snap_mode; if ((r_snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_flag & SCE_SNAP_ABS_GRID) && (t->mode == TFM_TRANSLATION)) { @@ -617,7 +618,7 @@ static short snap_select_type_get(TransInfo *t) * When we're moving the origins, allow snapping onto our own geometry (see T69132). */ } else if ((obedit_type != -1) && - ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) { + ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVES_LEGACY, OB_LATTICE, OB_MBALL)) { /* Edit mode */ /* Temporary limited to edit mode meshes, armature, curves, metaballs. */ diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index ca6940040b2..8b7133892ff 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -477,7 +477,7 @@ static void iter_snap_objects(SnapObjectContext *sctx, } } else if (snap_select == SNAP_NOT_SELECTED) { - if (is_object_active && !(base->object->mode & OB_MODE_OBJECT)) { + if (is_object_active && base->object->mode != OB_MODE_OBJECT) { /* Pass. Consider the selection of elements being edited. */ } else if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) { @@ -1054,7 +1054,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx, dt->r_hit_list); break; } - case OB_CURVE: + case OB_CURVES_LEGACY: case OB_SURF: case OB_FONT: { if (!is_object_active) { @@ -2743,7 +2743,7 @@ static void snap_obj_fn(SnapObjectContext *sctx, dt->r_no, dt->r_index); break; - case OB_CURVE: + case OB_CURVES_LEGACY: retval = snapCurve( sctx, params, ob_eval, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); break; /* Use ATTR_FALLTHROUGH if we want to snap to the generated mesh. */ @@ -3117,7 +3117,7 @@ static short transform_snap_context_project_view3d_mixed_impl( sctx->runtime.has_occlusion_plane = false; /* By convention we only snap to the original elements of a curve. */ - if (has_hit && ob_eval->type != OB_CURVE) { + if (has_hit && ob_eval->type != OB_CURVES_LEGACY) { /* Compute the new clip_pane but do not add it yet. */ float new_clipplane[4]; BLI_ASSERT_UNIT_V3(no); diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index 2300e664dfa..7b4551fdb0c 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -40,6 +40,7 @@ set(SRC ../include/ED_clip.h ../include/ED_curve.h ../include/ED_curves.h + ../include/ED_curves_sculpt.h ../include/ED_datafiles.h ../include/ED_file_indexer.h ../include/ED_fileselect.h diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c index 0523a58825e..c1e093d5555 100644 --- a/source/blender/editors/util/ed_transverts.c +++ b/source/blender/editors/util/ed_transverts.c @@ -45,7 +45,7 @@ void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit) BMEditMesh *em = BKE_editmesh_from_object(obedit); BM_mesh_normals_update(em->bm); } - else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { + else if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { Curve *cu = obedit->data; ListBase *nurbs = BKE_curve_editNurbs_get(cu); Nurb *nu = nurbs->first; @@ -181,7 +181,8 @@ static void set_mapped_co(void *vuserdata, int index, const float co[3], const f bool ED_transverts_check_obedit(const Object *obedit) { - return (ELEM(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)); + return ( + ELEM(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVES_LEGACY, OB_MBALL)); } void ED_transverts_create_from_obedit(TransVertStore *tvs, const Object *obedit, const int mode) @@ -351,7 +352,7 @@ void ED_transverts_create_from_obedit(TransVertStore *tvs, const Object *obedit, } } } - else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { + else if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { Curve *cu = obedit->data; int totmalloc = 0; ListBase *nurbs = BKE_curve_editNurbs_get(cu); diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 15fe944be49..32d405df841 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -306,7 +306,7 @@ bool ED_editors_flush_edits(Main *bmain) /* ***** XXX: functions are using old blender names, cleanup later ***** */ void apply_keyb_grid( - int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert) + bool shift, bool ctrl, float *val, float fac1, float fac2, float fac3, int invert) { /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */ if (invert) { diff --git a/source/blender/editors/util/ed_util_ops.cc b/source/blender/editors/util/ed_util_ops.cc index 014944da916..25deacbcdd1 100644 --- a/source/blender/editors/util/ed_util_ops.cc +++ b/source/blender/editors/util/ed_util_ops.cc @@ -226,7 +226,7 @@ static int lib_id_fake_user_toggle_exec(bContext *C, wmOperator *op) ID *id = (ID *)idptr.data; - if ((id->lib != nullptr) || (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { + if (ID_IS_LINKED(id) || (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { BKE_report(op->reports, RPT_ERROR, "Data-block type does not support fake user"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index 3bf226f6ba1..be6ac6e13e6 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -321,7 +321,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) if (U.flag & USER_FLAG_NUMINPUT_ADVANCED) #endif { - if ((event->ctrl == 0) && (event->alt == 0) && (event->ascii != '\0') && + if (((event->modifier & (KM_CTRL | KM_ALT)) == 0) && (event->ascii != '\0') && strchr("01234567890@%^&*-+/{}()[]<>.|", event->ascii)) { if (!(n->flag & NUM_EDIT_FULL)) { n->flag |= NUM_EDITED; @@ -339,7 +339,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) n->val_flag[idx] |= NUM_EDITED; return true; } - if (event->ctrl) { + if (event->modifier & KM_CTRL) { n->flag &= ~NUM_EDIT_FULL; return true; } @@ -375,7 +375,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) updated = true; break; } - else if (event->shift || !n->str[0]) { + else if ((event->modifier & KM_SHIFT) || !n->str[0]) { n->val[idx] = n->val_org[idx]; n->val_flag[idx] &= ~NUM_EDITED; n->str[0] = '\0'; @@ -390,7 +390,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) case EVT_DELKEY: if ((n->val_flag[idx] & NUM_EDITED) && n->str[0]) { int t_cur = cur = n->str_cur; - if (event->ctrl) { + if (event->modifier & KM_CTRL) { mode = STRCUR_JUMP_DELIM; } BLI_str_cursor_step_utf8(n->str, strlen(n->str), &t_cur, dir, mode, true); @@ -416,7 +416,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) ATTR_FALLTHROUGH; case EVT_RIGHTARROWKEY: cur = n->str_cur; - if (event->ctrl) { + if (event->modifier & KM_CTRL) { mode = STRCUR_JUMP_DELIM; } BLI_str_cursor_step_utf8(n->str, strlen(n->str), &cur, dir, mode, true); @@ -442,7 +442,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) n->val_flag[idx] &= ~(NUM_NEGATE | NUM_INVERSE); #endif - idx = (idx + idx_max + (event->ctrl ? 0 : 2)) % (idx_max + 1); + idx = (idx + idx_max + ((event->modifier & KM_CTRL) ? 0 : 2)) % (idx_max + 1); n->idx = idx; if (n->val_flag[idx] & NUM_EDITED) { value_to_editstr(n, idx); @@ -470,7 +470,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) n->val_flag[idx] |= NUM_EDITED; return true; } - else if (event->ctrl) { + else if (event->modifier & KM_CTRL) { n->flag &= ~NUM_EDIT_FULL; return true; } @@ -480,28 +480,28 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) #ifdef USE_FAKE_EDIT case EVT_PADMINUS: case EVT_MINUSKEY: - if (event->ctrl || !(n->flag & NUM_EDIT_FULL)) { + if ((event->modifier & KM_CTRL) || !(n->flag & NUM_EDIT_FULL)) { n->val_flag[idx] ^= NUM_NEGATE; updated = true; } break; case EVT_PADSLASHKEY: case EVT_SLASHKEY: - if (event->ctrl || !(n->flag & NUM_EDIT_FULL)) { + if ((event->modifier & KM_CTRL) || !(n->flag & NUM_EDIT_FULL)) { n->val_flag[idx] ^= NUM_INVERSE; updated = true; } break; #endif case EVT_CKEY: - if (event->ctrl) { + if (event->modifier & KM_CTRL) { /* Copy current `str` to the copy/paste buffer. */ WM_clipboard_text_set(n->str, 0); updated = true; } break; case EVT_VKEY: - if (event->ctrl) { + if (event->modifier & KM_CTRL) { /* extract the first line from the clipboard */ int pbuf_len; char *pbuf = WM_clipboard_text_get_firstline(false, &pbuf_len); @@ -531,7 +531,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) /* Up to this point, if we have a ctrl modifier, skip. * This allows to still access most of modals' shortcuts even in numinput mode. */ - if (!updated && event->ctrl) { + if (!updated && (event->modifier & KM_CTRL)) { return false; } diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 91b29049ecf..c0d0fe95c8c 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -2598,7 +2598,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event) /* Increase limit */ case EVT_PADPLUSKEY: case WHEELUPMOUSE: - if (event->val == KM_PRESS && event->alt) { + if ((event->val == KM_PRESS) && (event->modifier & KM_ALT)) { ssc->limit_dist += 0.01f; if (!stitch_process_data(ssc, active_state, scene, false)) { stitch_cancel(C, op); @@ -2612,7 +2612,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event) /* Decrease limit */ case EVT_PADMINUS: case WHEELDOWNMOUSE: - if (event->val == KM_PRESS && event->alt) { + if ((event->val == KM_PRESS) && (event->modifier & KM_ALT)) { ssc->limit_dist -= 0.01f; ssc->limit_dist = MAX2(0.01f, ssc->limit_dist); if (!stitch_process_data(ssc, active_state, scene, false)) { @@ -2673,7 +2673,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event) /* Select geometry */ case RIGHTMOUSE: - if (!event->shift) { + if ((event->modifier & KM_SHIFT) == 0) { stitch_cancel(C, op); return OPERATOR_CANCELLED; } |