diff options
Diffstat (limited to 'source/blender/editors')
328 files changed, 8743 insertions, 7714 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 05cbb3ef48f..24bb58535a5 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -133,7 +133,16 @@ static void acf_generic_root_backdrop(bAnimContext *ac, UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); UI_draw_roundbox_3fv_alpha( - true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); + &(const rctf){ + .xmin = offset, + .xmax = v2d->cur.xmax + EXTRA_SCROLL_PAD, + .ymin = yminc, + .ymax = ymaxc, + }, + true, + 8, + color, + 1.0f); } /* get backdrop color for data expanders under top-level Scene/Object */ @@ -421,7 +430,7 @@ static bool acf_generic_dataexpand_setting_valid(bAnimContext *ac, case ACHANNEL_SETTING_MUTE: return ((ac) && (ac->spacetype == SPACE_NLA)); - /* select is ok for most "ds*" channels (e.g. dsmat) */ + /* Select is ok for most `ds*` channels (e.g. `dsmat`) */ case ACHANNEL_SETTING_SELECT: return true; @@ -464,7 +473,16 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi */ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT); UI_draw_roundbox_3fv_alpha( - true, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); + &(const rctf){ + .xmin = 0, + .xmax = v2d->cur.xmax + EXTRA_SCROLL_PAD, + .ymin = yminc - 2, + .ymax = ymaxc, + }, + true, + 8, + color, + 1.0f); } /* name for summary entries */ @@ -875,7 +893,16 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); UI_draw_roundbox_3fv_alpha( - true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); + &(const rctf){ + .xmin = offset, + .xmax = v2d->cur.xmax + EXTRA_SCROLL_PAD, + .ymin = yminc, + .ymax = ymaxc, + }, + true, + 8, + color, + 1.0f); } /* name for group entries */ @@ -1149,7 +1176,16 @@ static void acf_nla_controls_backdrop(bAnimContext *ac, /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); UI_draw_roundbox_3fv_alpha( - true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f); + &(const rctf){ + .xmin = offset, + .xmax = v2d->cur.xmax + EXTRA_SCROLL_PAD, + .ymin = yminc, + .ymax = ymaxc, + }, + true, + 5, + color, + 1.0f); } /* name for nla controls expander entries */ @@ -3936,13 +3972,16 @@ static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float y /* draw slightly shifted up vertically to look like it has more separation from other channels, * but we then need to slightly shorten it so that it doesn't look like it overlaps */ - UI_draw_roundbox_4fv(true, - offset, - yminc + NLACHANNEL_SKIP, - (float)v2d->cur.xmax, - ymaxc + NLACHANNEL_SKIP - 1, - 8, - color); + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = offset, + .xmax = (float)v2d->cur.xmax, + .ymin = yminc + NLACHANNEL_SKIP, + .ymax = ymaxc + NLACHANNEL_SKIP - 1, + }, + true, + 8, + color); } /* name for nla action entries */ @@ -4710,7 +4749,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, (float)CFRA); NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context( - &nla_cache, &id_ptr, adt, &anim_eval_context, false); + &nla_cache, &id_ptr, adt, &anim_eval_context); /* get current frame and apply NLA-mapping to it (if applicable) */ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); @@ -4766,7 +4805,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, (float)CFRA); NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context( - &nla_cache, &id_ptr, key->adt, &anim_eval_context, false); + &nla_cache, &id_ptr, key->adt, &anim_eval_context); /* get current frame and apply NLA-mapping to it (if applicable) */ const float remapped_frame = BKE_nla_tweakedit_remap( diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index a6e96a4d919..109cf79c786 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -393,7 +393,11 @@ static void anim_channels_select_set(bAnimContext *ac, FCurve *fcu = (FCurve *)ale->data; ACHANNEL_SET_FLAG(fcu, sel, FCURVE_SELECTED); - fcu->flag &= ~FCURVE_ACTIVE; + if ((fcu->flag & FCURVE_SELECTED) == 0) { + /* Only erase the ACTIVE flag when deselecting. This ensures that "select all curves" + * retains the currently active curve. */ + fcu->flag &= ~FCURVE_ACTIVE; + } break; } case ANIMTYPE_SHAPEKEY: { @@ -1197,7 +1201,7 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn rearrange_animchannel_islands( &adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK, &anim_data_visible); - /* Add back non-local NLA tracks at the begining of the animation data's list. */ + /* Add back non-local NLA tracks at the beginning of the animation data's list. */ if (!BLI_listbase_is_empty(&extracted_nonlocal_nla_tracks)) { BLI_assert(is_liboverride); ((NlaTrack *)extracted_nonlocal_nla_tracks.last)->next = adt->nla_tracks.first; @@ -1732,7 +1736,7 @@ static int animchannels_group_exec(bContext *C, wmOperator *op) /* free temp data */ ANIM_animdata_freelist(&anim_data); - /* updatss */ + /* Updates. */ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index f2022194ed5..a03f19d0111 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -2403,6 +2403,13 @@ static void animfilter_modifier_idpoin_cb(void *afm_ptr, } break; } + case ID_NT: { + bNodeTree *node_tree = (bNodeTree *)id; + if (!(afm->ads->filterflag & ADS_FILTER_NONTREE)) { + afm->items += animdata_filter_ds_nodetree( + afm->ac, &afm->tmp_data, afm->ads, owner_id, node_tree, afm->filter_mode); + } + } /* TODO: images? */ default: diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c index 088ac9dbcba..aac2465d43a 100644 --- a/source/blender/editors/animation/anim_motion_paths.c +++ b/source/blender/editors/animation/anim_motion_paths.c @@ -331,7 +331,7 @@ static void motionpath_calculate_update_range(MPathTarget *mpt, int fcu_sfra = motionpath_get_prev_prev_keyframe(mpt, &fcu_keys, current_frame); int fcu_efra = motionpath_get_next_next_keyframe(mpt, &fcu_keys, current_frame); - /* Extend range furher, since accelleration compensation propagates even further away. */ + /* Extend range further, since acceleration compensation propagates even further away. */ if (fcu->auto_smoothing != FCURVE_SMOOTH_NONE) { fcu_sfra = motionpath_get_prev_prev_keyframe(mpt, &fcu_keys, fcu_sfra); fcu_efra = motionpath_get_next_next_keyframe(mpt, &fcu_keys, fcu_efra); diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index a5514f6517e..72d9bff545a 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -29,12 +29,10 @@ #include "BLI_math_base.h" #include "BLI_utildefines.h" -#include "DNA_anim_types.h" #include "DNA_scene_types.h" #include "BKE_context.h" #include "BKE_global.h" -#include "BKE_main.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -50,10 +48,8 @@ #include "ED_screen.h" #include "ED_sequencer.h" #include "ED_time_scrub_ui.h" -#include "ED_util.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "SEQ_sequencer.h" #include "SEQ_time.h" diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index b2a9d6ac9b7..43d5efe9ea9 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -33,7 +33,6 @@ #include "DNA_anim_types.h" #include "DNA_object_types.h" -#include "DNA_space_types.h" #include "DNA_texture_types.h" #include "BKE_anim_data.h" diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 542a6d45db7..b9ef69cf8bd 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -258,6 +258,10 @@ static DLRBT_Node *nalloc_ak_gpframe(void *data) /* count keyframes in this column */ ak->totkey = 1; + /* Set as visible block. */ + ak->totblock = 1; + ak->block.sel = ak->sel; + ak->block.flag |= ACTKEYBLOCK_FLAG_GPENCIL; return (DLRBT_Node *)ak; } @@ -689,6 +693,7 @@ static void draw_keylist(View2D *v2d, { const float icon_sz = U.widget_unit * 0.5f * yscale_fac; const float half_icon_sz = 0.5f * icon_sz; + const float quarter_icon_sz = 0.25f * icon_sz; const float smaller_sz = 0.35f * icon_sz; const float ipo_sz = 0.1f * icon_sz; @@ -724,6 +729,7 @@ static void draw_keylist(View2D *v2d, ipo_color_mix[3] *= 0.5f; uint block_len = 0; + uint gpencil_len = 0; LISTBASE_FOREACH (ActKeyColumn *, ab, keys) { if (actkeyblock_get_valid_hold(ab)) { block_len++; @@ -731,50 +737,72 @@ static void draw_keylist(View2D *v2d, if (show_ipo && actkeyblock_is_valid(ab) && (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) { block_len++; } + if ((ab->next != NULL) && (ab->block.flag & ACTKEYBLOCK_FLAG_GPENCIL)) { + gpencil_len++; + } } - if (block_len > 0) { + if ((block_len > 0) || (gpencil_len > 0)) { GPUVertFormat *format = immVertexFormat(); uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); - immBegin(GPU_PRIM_TRIS, 6 * block_len); - LISTBASE_FOREACH (ActKeyColumn *, ab, keys) { - int valid_hold = actkeyblock_get_valid_hold(ab); - if (valid_hold != 0) { - if ((valid_hold & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) { - /* draw "moving hold" long-keyframe block - slightly smaller */ - immRectf_fast_with_color(pos_id, - color_id, - ab->cfra, - ypos - smaller_sz, - ab->next->cfra, - ypos + smaller_sz, - (ab->block.sel) ? sel_mhcol : unsel_mhcol); + /* Normal Dopesheet. */ + if (block_len > 0) { + immBegin(GPU_PRIM_TRIS, 6 * block_len); + LISTBASE_FOREACH (ActKeyColumn *, ab, keys) { + int valid_hold = actkeyblock_get_valid_hold(ab); + if (valid_hold != 0) { + if ((valid_hold & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) { + /* draw "moving hold" long-keyframe block - slightly smaller */ + immRectf_fast_with_color(pos_id, + color_id, + ab->cfra, + ypos - smaller_sz, + ab->next->cfra, + ypos + smaller_sz, + (ab->block.sel) ? sel_mhcol : unsel_mhcol); + } + else { + /* draw standard long-keyframe block */ + immRectf_fast_with_color(pos_id, + color_id, + ab->cfra, + ypos - half_icon_sz, + ab->next->cfra, + ypos + half_icon_sz, + (ab->block.sel) ? sel_color : unsel_color); + } } - else { - /* draw standard long-keyframe block */ - immRectf_fast_with_color(pos_id, - color_id, - ab->cfra, - ypos - half_icon_sz, - ab->next->cfra, - ypos + half_icon_sz, - (ab->block.sel) ? sel_color : unsel_color); + if (show_ipo && actkeyblock_is_valid(ab) && + (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) { + /* draw an interpolation line */ + immRectf_fast_with_color( + pos_id, + color_id, + ab->cfra, + ypos - ipo_sz, + ab->next->cfra, + ypos + ipo_sz, + (ab->block.conflict & ACTKEYBLOCK_FLAG_NON_BEZIER) ? ipo_color_mix : ipo_color); } } - if (show_ipo && actkeyblock_is_valid(ab) && - (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) { - /* draw an interpolation line */ - immRectf_fast_with_color( - pos_id, - color_id, - ab->cfra, - ypos - ipo_sz, - ab->next->cfra, - ypos + ipo_sz, - (ab->block.conflict & ACTKEYBLOCK_FLAG_NON_BEZIER) ? ipo_color_mix : ipo_color); + } + /* Grease Pencil Dopesheet. */ + else { + immBegin(GPU_PRIM_TRIS, 6 * gpencil_len); + LISTBASE_FOREACH (ActKeyColumn *, ab, keys) { + if (ab->next == NULL) { + continue; + } + immRectf_fast_with_color(pos_id, + color_id, + ab->cfra, + ypos - quarter_icon_sz, + ab->next->cfra, + ypos + quarter_icon_sz, + (ab->block.sel) ? sel_mhcol : unsel_mhcol); } } immEnd(); diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 6ed9803dbd3..72e65272f13 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -39,13 +39,11 @@ #include "BKE_action.h" #include "BKE_curve.h" -#include "BKE_deform.h" #include "BKE_fcurve.h" #include "BKE_main.h" #include "BKE_report.h" #include "RNA_access.h" -#include "RNA_enum_types.h" #include "ED_anim_api.h" #include "ED_keyframes_edit.h" diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index e8146ca960a..0d1633ab3a2 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -614,7 +614,7 @@ int insert_vert_fcurve( return -1; } - /* set handletype and interpolation */ + /* Set handle-type and interpolation. */ if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE) == 0) { BezTriple *bezt = (fcu->bezt + a); @@ -1384,7 +1384,7 @@ static AnimationEvalContext nla_time_remap(const AnimationEvalContext *anim_eval if (adt && adt->action == act) { /* Get NLA context for value remapping. */ *r_nla_context = BKE_animsys_get_nla_keyframing_context( - nla_cache, id_ptr, adt, anim_eval_context, false); + nla_cache, id_ptr, adt, anim_eval_context); /* Apply NLA-mapping to frame. */ const float remapped_frame = BKE_nla_tweakedit_remap( diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c index 98b4d93fbf1..034378399b9 100644 --- a/source/blender/editors/animation/time_scrub_ui.c +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -124,23 +124,22 @@ static void draw_current_frame(const Scene *scene, UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_3fv_alpha(true, - frame_x - box_width / 2 + U.pixelsize / 2, - scrub_region_rect->ymin + box_padding, - frame_x + box_width / 2 + U.pixelsize / 2, - scrub_region_rect->ymax - box_padding, - 4 * UI_DPI_FAC, - bg_color, - 1.0f); - - UI_GetThemeColorShade4fv(TH_CFRAME, 5, bg_color); - UI_draw_roundbox_aa(false, - frame_x - box_width / 2 + U.pixelsize / 2, - scrub_region_rect->ymin + box_padding, - frame_x + box_width / 2 + U.pixelsize / 2, - scrub_region_rect->ymax - box_padding, - 4 * UI_DPI_FAC, - bg_color); + float outline_color[4]; + UI_GetThemeColorShade4fv(TH_CFRAME, 5, outline_color); + + UI_draw_roundbox_4fv_ex( + &(const rctf){ + .xmin = frame_x - box_width / 2 + U.pixelsize / 2, + .xmax = frame_x + box_width / 2 + U.pixelsize / 2, + .ymin = scrub_region_rect->ymin + box_padding, + .ymax = scrub_region_rect->ymax - box_padding, + }, + bg_color, + NULL, + 1.0f, + outline_color, + U.pixelsize, + 4 * UI_DPI_FAC); uchar text_color[4]; UI_GetThemeColor4ubv(TH_HEADER_TEXT_HI, text_color); diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index a0b8bf862d7..68fff1091af 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -122,9 +122,6 @@ EditBone *ED_armature_ebone_add_primitive(Object *obedit_arm, float length, bool return bone; } -/* previously addvert_armature */ -/* the ctrl-click method */ - /** * Note this is already ported to multi-objects as it is. * Since only the active bone is extruded even for single objects, @@ -306,8 +303,7 @@ static EditBone *get_named_editbone(ListBase *edbo, const char *name) return NULL; } -/* Call this before doing any duplications - * */ +/* Call this before doing any duplications. */ void preEditBoneDuplicate(ListBase *editbones) { /* clear temp */ diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index da1b29307b1..a0face26bae 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -28,8 +28,6 @@ #include "ED_armature.h" #include "ED_screen.h" -#include "ED_select_utils.h" -#include "ED_transform.h" #include "armature_intern.h" diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index 6951ed6f305..f86ec545712 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -30,7 +30,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_string_utils.h" @@ -50,8 +49,6 @@ #include "ED_armature.h" #include "ED_mesh.h" -#include "eigen_capi.h" - #include "armature_intern.h" #include "meshlaplacian.h" diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index fba88e78162..3d1d8d0d1f1 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -699,11 +699,11 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm) BKE_armature_bonelist_free(&arm->bonebase, true); arm->act_bone = NULL; - /* remove zero sized bones, this gives unstable restposes */ + /* Remove zero sized bones, this gives unstable rest-poses. */ for (eBone = arm->edbo->first; eBone; eBone = neBone) { float len_sq = len_squared_v3v3(eBone->head, eBone->tail); neBone = eBone->next; - /* TODO(sergey): How to ensure this is a constexpr? */ + /* TODO(sergey): How to ensure this is a `constexpr`? */ if (len_sq <= square_f(0.000001f)) { /* FLT_EPSILON is too large? */ EditBone *fBone; diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c index c6d7d2eb869..337d1138b23 100644 --- a/source/blender/editors/armature/editarmature_undo.c +++ b/source/blender/editors/armature/editarmature_undo.c @@ -178,8 +178,11 @@ static bool armature_undosys_step_encode(struct bContext *C, struct Main *bmain, return true; } -static void armature_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) +static void armature_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir UNUSED(dir), + bool UNUSED(is_final)) { ArmatureUndoStep *us = (ArmatureUndoStep *)us_p; diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 3c0b6dacbf6..e362a2e2f40 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -422,7 +422,7 @@ static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTr } } -/* Raytracing for vertex to bone/vertex visibility */ +/* Ray-tracing for vertex to bone/vertex visibility. */ static void heat_ray_tree_create(LaplacianSystem *sys) { const MLoopTri *looptri = sys->heat.mlooptri; @@ -497,7 +497,7 @@ static float heat_source_distance(LaplacianSystem *sys, int vertex, int source) { float closest[3], d[3], dist, cosine; - /* compute euclidian distance */ + /* compute Euclidean distance */ closest_to_line_segment_v3( closest, sys->heat.verts[vertex], sys->heat.root[source], sys->heat.tip[source]); diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index 91893af003f..78bce8679bb 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -149,7 +149,7 @@ bool ED_object_posemode_exit(bContext *C, Object *ob) return ok; } -/* if a selected or active bone is protected, throw error (oonly if warn == 1) and return 1 */ +/* if a selected or active bone is protected, throw error (only if warn == 1) and return 1 */ /* only_selected == 1: the active bone is allowed to be protected */ #if 0 /* UNUSED 2.5 */ static bool pose_has_protected_selected(Object *ob, short warn) diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c index 55c9877e55f..38d15d8b880 100644 --- a/source/blender/editors/armature/pose_group.c +++ b/source/blender/editors/armature/pose_group.c @@ -423,7 +423,7 @@ static int group_sort_exec(bContext *C, wmOperator *UNUSED(op)) BLI_addtail(&pose->agroups, agrp_array[i].agrp); } - /* fix changed bone group indizes in bones */ + /* Fix changed bone group indices in bones. */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { for (i = 0; i < agrp_count; i++) { if (pchan->agrp_index == agrp_array[i].index) { diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index 947e2dbf5aa..45f623f3a9d 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -1106,7 +1106,7 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData if (pchan) { if (!any_bone_selected || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) { if (autokey) { - /* add datasource override for the PoseChannel, to be used later */ + /* Add data-source override for the PoseChannel, to be used later. */ ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan); /* clear any unkeyed tags */ @@ -1142,7 +1142,7 @@ static void poselib_preview_apply(bContext *C, wmOperator *op) /* only recalc pose (and its dependencies) if pose has changed */ if (pld->redraw == PL_PREVIEW_REDRAWALL) { - /* don't clear pose if firsttime */ + /* Don't clear pose if first time. */ if ((pld->flag & PL_PREVIEW_FIRSTTIME) == 0) { poselib_backup_restore(pld); } diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index 4b646bb26e2..d636f0d68af 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -689,7 +689,7 @@ static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso) /* Not strictly a transform, but custom properties contribute * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */ /* TODO Not implemented */ - // pose_slide_apply_props(pso, pfl, "[\""); /* dummy " for texteditor bugs */ + // pose_slide_apply_props(pso, pfl, "[\""); } } @@ -702,7 +702,7 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) { tPChanFCurveLink *pfl; - /* sanitise the frame ranges */ + /* Sanitize the frame ranges. */ if (pso->prevFrame == pso->nextFrame) { /* move out one step either side */ pso->prevFrame--; @@ -765,7 +765,7 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) { /* Not strictly a transform, but custom properties contribute * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */ - pose_slide_apply_props(pso, pfl, "[\""); /* dummy " for texteditor bugs */ + pose_slide_apply_props(pso, pfl, "[\""); } } @@ -1125,7 +1125,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) if (event->val == KM_PRESS) { switch (event->type) { /* Transform Channel Limits */ - /* XXX: Replace these hardcoded hotkeys with a modalmap that can be customised */ + /* XXX: Replace these hard-coded hotkeys with a modal-map that can be customized. */ case EVT_GKEY: /* Location */ { pose_slide_toggle_channels_mode(op, pso, PS_TFM_LOC); @@ -1183,7 +1183,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else { - /* unhandled event - maybe it was some view manip? */ + /* unhandled event - maybe it was some view manipulation? */ /* allow to pass through */ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; } @@ -1246,15 +1246,15 @@ static void pose_slide_opdef_properties(wmOperatorType *ot) { PropertyRNA *prop; - prop = RNA_def_float_percentage(ot->srna, - "percentage", - 0.5f, - 0.0f, - 1.0f, - "Percentage", - "Weighting factor for which keyframe is favored more", - 0.0, - 1.0); + prop = RNA_def_float_factor(ot->srna, + "factor", + 0.5f, + 0.0f, + 1.0f, + "Factor", + "Weighting factor for which keyframe is favored more", + 0.0, + 1.0); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_int(ot->srna, diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 3505aea3f40..722865cc942 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -225,7 +225,7 @@ static void applyarmature_process_selected_recursive(bArmature *arm, ApplyArmature_ParentState new_pstate = {.bone = bone}; if (BLI_findptr(selected, pchan, offsetof(CollectionPointerLink, ptr.data))) { - /* SELECTED BONE: Snap to final pose transform minus unapplied parent effects. + /* SELECTED BONE: Snap to final pose transform minus un-applied parent effects. * * I.e. bone position with accumulated parent effects but no local * transformation will match the original final pose_mat. diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c index 2a6dc9f406b..c75e9c9ef69 100644 --- a/source/blender/editors/armature/pose_utils.c +++ b/source/blender/editors/armature/pose_utils.c @@ -33,7 +33,6 @@ #include "BKE_action.h" #include "BKE_anim_data.h" -#include "BKE_armature.h" #include "BKE_idprop.h" #include "BKE_layer.h" #include "BKE_object.h" @@ -312,7 +311,7 @@ void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks, continue; } - /* add datasource override for the PoseChannel, to be used later */ + /* Add data-source override for the PoseChannel, to be used later. */ ANIM_relative_keyingset_add_source(&dsources, &pfl->ob->id, &RNA_PoseBone, pchan); /* clear any unkeyed tags */ diff --git a/source/blender/editors/asset/CMakeLists.txt b/source/blender/editors/asset/CMakeLists.txt index 6cd94783251..8c5f91561b7 100644 --- a/source/blender/editors/asset/CMakeLists.txt +++ b/source/blender/editors/asset/CMakeLists.txt @@ -29,8 +29,8 @@ set(INC_SYS ) set(SRC - asset_edit.c - asset_ops.c + asset_edit.cc + asset_ops.cc ) set(LIB diff --git a/source/blender/editors/asset/asset_edit.c b/source/blender/editors/asset/asset_edit.cc index 3dca87d3a03..d20de4141cb 100644 --- a/source/blender/editors/asset/asset_edit.c +++ b/source/blender/editors/asset/asset_edit.cc @@ -20,11 +20,9 @@ #include "BKE_asset.h" #include "BKE_context.h" -#include "BKE_idtype.h" #include "BKE_lib_id.h" #include "DNA_ID.h" -#include "DNA_asset_types.h" #include "UI_interface_icons.h" @@ -45,7 +43,7 @@ bool ED_asset_mark_id(const bContext *C, ID *id) id->asset_data = BKE_asset_metadata_create(); - UI_icon_render_id(C, NULL, id, ICON_SIZE_PREVIEW, true); + UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, true); return true; } @@ -65,5 +63,5 @@ bool ED_asset_clear_id(ID *id) bool ED_asset_can_make_single_from_context(const bContext *C) { /* Context needs a "id" pointer to be set for #ASSET_OT_mark()/#ASSET_OT_clear() to use. */ - return CTX_data_pointer_get_type_silent(C, "id", &RNA_ID).data != NULL; + return CTX_data_pointer_get_type_silent(C, "id", &RNA_ID).data != nullptr; } diff --git a/source/blender/editors/asset/asset_ops.c b/source/blender/editors/asset/asset_ops.c deleted file mode 100644 index 29c3174f051..00000000000 --- a/source/blender/editors/asset/asset_ops.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** \file - * \ingroup edasset - */ - -#include <string.h> - -#include "BKE_asset.h" -#include "BKE_context.h" -#include "BKE_report.h" - -#include "BLI_listbase.h" -#include "BLI_string_utils.h" -#include "BLI_utildefines.h" - -#include "DNA_asset_types.h" -#include "DNA_userdef_types.h" - -#include "ED_asset.h" - -#include "MEM_guardedalloc.h" - -#include "RNA_access.h" -#include "RNA_define.h" - -#include "WM_api.h" -#include "WM_types.h" - -/* -------------------------------------------------------------------- */ - -struct AssetMarkResultStats { - int tot_created; - int tot_already_asset; - ID *last_id; -}; - -static bool asset_ops_poll(bContext *UNUSED(C)) -{ - return U.experimental.use_asset_browser; -} - -/** - * Return the IDs to operate on as list of #CollectionPointerLink links. Needs freeing. - */ -static ListBase /* CollectionPointerLink */ asset_operation_get_ids_from_context(const bContext *C) -{ - ListBase list = {0}; - - PointerRNA idptr = CTX_data_pointer_get_type(C, "id", &RNA_ID); - - if (idptr.data) { - CollectionPointerLink *ctx_link = MEM_callocN(sizeof(*ctx_link), __func__); - ctx_link->ptr = idptr; - BLI_addtail(&list, ctx_link); - } - else { - CTX_data_selected_ids(C, &list); - } - - return list; -} - -static void asset_mark_for_idptr_list(const bContext *C, - const ListBase /* CollectionPointerLink */ *ids, - struct AssetMarkResultStats *r_stats) -{ - memset(r_stats, 0, sizeof(*r_stats)); - - LISTBASE_FOREACH (CollectionPointerLink *, ctx_id, ids) { - BLI_assert(RNA_struct_is_ID(ctx_id->ptr.type)); - - ID *id = ctx_id->ptr.data; - if (id->asset_data) { - r_stats->tot_already_asset++; - continue; - } - - if (ED_asset_mark_id(C, id)) { - r_stats->last_id = id; - r_stats->tot_created++; - } - } -} - -static bool asset_mark_results_report(const struct AssetMarkResultStats *stats, - ReportList *reports) -{ - /* User feedback on failure. */ - if ((stats->tot_created < 1) && (stats->tot_already_asset > 0)) { - BKE_report(reports, - RPT_ERROR, - "Selected data-blocks are already assets (or do not support use as assets)"); - return false; - } - if (stats->tot_created < 1) { - BKE_report(reports, - RPT_ERROR, - "No data-blocks to create assets for found (or do not support use as assets)"); - return false; - } - - /* User feedback on success. */ - if (stats->tot_created == 1) { - /* If only one data-block: Give more useful message by printing asset name. */ - BKE_reportf(reports, RPT_INFO, "Data-block '%s' is now an asset", stats->last_id->name + 2); - } - else { - BKE_reportf(reports, RPT_INFO, "%i data-blocks are now assets", stats->tot_created); - } - - return true; -} - -static int asset_mark_exec(bContext *C, wmOperator *op) -{ - ListBase ids = asset_operation_get_ids_from_context(C); - - struct AssetMarkResultStats stats; - asset_mark_for_idptr_list(C, &ids, &stats); - BLI_freelistN(&ids); - - if (!asset_mark_results_report(&stats, op->reports)) { - return OPERATOR_CANCELLED; - } - - WM_main_add_notifier(NC_ID | NA_EDITED, NULL); - WM_main_add_notifier(NC_ASSET | NA_ADDED, NULL); - - return OPERATOR_FINISHED; -} - -static void ASSET_OT_mark(wmOperatorType *ot) -{ - ot->name = "Mark Asset"; - ot->description = - "Enable easier reuse of selected data-blocks through the Asset Browser, with the help of " - "customizable metadata (like previews, descriptions and tags)"; - ot->idname = "ASSET_OT_mark"; - - ot->exec = asset_mark_exec; - ot->poll = asset_ops_poll; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* -------------------------------------------------------------------- */ - -struct AssetClearResultStats { - int tot_removed; - ID *last_id; -}; - -static void asset_clear_from_idptr_list(const ListBase /* CollectionPointerLink */ *ids, - struct AssetClearResultStats *r_stats) -{ - memset(r_stats, 0, sizeof(*r_stats)); - - LISTBASE_FOREACH (CollectionPointerLink *, ctx_id, ids) { - BLI_assert(RNA_struct_is_ID(ctx_id->ptr.type)); - - ID *id = ctx_id->ptr.data; - if (!id->asset_data) { - continue; - } - - if (ED_asset_clear_id(id)) { - r_stats->tot_removed++; - r_stats->last_id = id; - } - } -} - -static bool asset_clear_result_report(const struct AssetClearResultStats *stats, - ReportList *reports) - -{ - if (stats->tot_removed < 1) { - BKE_report(reports, RPT_ERROR, "No asset data-blocks selected/focused"); - return false; - } - - if (stats->tot_removed == 1) { - /* If only one data-block: Give more useful message by printing asset name. */ - BKE_reportf( - reports, RPT_INFO, "Data-block '%s' is no asset anymore", stats->last_id->name + 2); - } - else { - BKE_reportf(reports, RPT_INFO, "%i data-blocks are no assets anymore", stats->tot_removed); - } - - return true; -} - -static int asset_clear_exec(bContext *C, wmOperator *op) -{ - ListBase ids = asset_operation_get_ids_from_context(C); - - struct AssetClearResultStats stats; - asset_clear_from_idptr_list(&ids, &stats); - BLI_freelistN(&ids); - - if (!asset_clear_result_report(&stats, op->reports)) { - return OPERATOR_CANCELLED; - } - - WM_main_add_notifier(NC_ID | NA_EDITED, NULL); - WM_main_add_notifier(NC_ASSET | NA_REMOVED, NULL); - - return OPERATOR_FINISHED; -} - -static void ASSET_OT_clear(wmOperatorType *ot) -{ - ot->name = "Clear Asset"; - ot->description = - "Delete all asset metadata and turn the selected asset data-blocks back into normal " - "data-blocks"; - ot->idname = "ASSET_OT_clear"; - - ot->exec = asset_clear_exec; - ot->poll = asset_ops_poll; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* -------------------------------------------------------------------- */ - -void ED_operatortypes_asset(void) -{ - WM_operatortype_append(ASSET_OT_mark); - WM_operatortype_append(ASSET_OT_clear); -} diff --git a/source/blender/editors/asset/asset_ops.cc b/source/blender/editors/asset/asset_ops.cc new file mode 100644 index 00000000000..8ca1b488a1d --- /dev/null +++ b/source/blender/editors/asset/asset_ops.cc @@ -0,0 +1,259 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup edasset + */ + +#include "BKE_context.h" +#include "BKE_report.h" + +#include "BLI_vector.hh" + +#include "ED_asset.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +/* -------------------------------------------------------------------- */ + +using PointerRNAVec = blender::Vector<PointerRNA>; + +static bool asset_operation_poll(bContext * /*C*/) +{ + return U.experimental.use_asset_browser; +} + +/** + * Return the IDs to operate on as PointerRNA vector. Either a single one ("id" context member) or + * multiple ones ("selected_ids" context member). + */ +static PointerRNAVec asset_operation_get_ids_from_context(const bContext *C) +{ + PointerRNAVec ids; + + PointerRNA idptr = CTX_data_pointer_get_type(C, "id", &RNA_ID); + if (idptr.data) { + /* Single ID. */ + ids.append(idptr); + } + else { + ListBase list; + CTX_data_selected_ids(C, &list); + LISTBASE_FOREACH (CollectionPointerLink *, link, &list) { + ids.append(link->ptr); + } + BLI_freelistN(&list); + } + + return ids; +} + +/* -------------------------------------------------------------------- */ + +class AssetMarkHelper { + public: + void operator()(const bContext &C, PointerRNAVec &ids); + + void reportResults(ReportList &reports) const; + bool wasSuccessful() const; + + private: + struct Stats { + int tot_created = 0; + int tot_already_asset = 0; + ID *last_id = nullptr; + }; + + Stats stats; +}; + +void AssetMarkHelper::operator()(const bContext &C, PointerRNAVec &ids) +{ + for (PointerRNA &ptr : ids) { + BLI_assert(RNA_struct_is_ID(ptr.type)); + + ID *id = static_cast<ID *>(ptr.data); + if (id->asset_data) { + stats.tot_already_asset++; + continue; + } + + if (ED_asset_mark_id(&C, id)) { + stats.last_id = id; + stats.tot_created++; + } + } +} + +bool AssetMarkHelper::wasSuccessful() const +{ + return stats.tot_created > 0; +} + +void AssetMarkHelper::reportResults(ReportList &reports) const +{ + /* User feedback on failure. */ + if (!wasSuccessful()) { + if ((stats.tot_already_asset > 0)) { + BKE_report(&reports, + RPT_ERROR, + "Selected data-blocks are already assets (or do not support use as assets)"); + } + else { + BKE_report(&reports, + RPT_ERROR, + "No data-blocks to create assets for found (or do not support use as assets)"); + } + } + /* User feedback on success. */ + else if (stats.tot_created == 1) { + /* If only one data-block: Give more useful message by printing asset name. */ + BKE_reportf(&reports, RPT_INFO, "Data-block '%s' is now an asset", stats.last_id->name + 2); + } + else { + BKE_reportf(&reports, RPT_INFO, "%i data-blocks are now assets", stats.tot_created); + } +} + +static int asset_mark_exec(bContext *C, wmOperator *op) +{ + PointerRNAVec ids = asset_operation_get_ids_from_context(C); + + AssetMarkHelper mark_helper; + mark_helper(*C, ids); + mark_helper.reportResults(*op->reports); + + if (!mark_helper.wasSuccessful()) { + return OPERATOR_CANCELLED; + } + + WM_main_add_notifier(NC_ID | NA_EDITED, nullptr); + WM_main_add_notifier(NC_ASSET | NA_ADDED, nullptr); + + return OPERATOR_FINISHED; +} + +static void ASSET_OT_mark(wmOperatorType *ot) +{ + ot->name = "Mark Asset"; + ot->description = + "Enable easier reuse of selected data-blocks through the Asset Browser, with the help of " + "customizable metadata (like previews, descriptions and tags)"; + ot->idname = "ASSET_OT_mark"; + + ot->exec = asset_mark_exec; + ot->poll = asset_operation_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* -------------------------------------------------------------------- */ + +class AssetClearHelper { + public: + void operator()(PointerRNAVec &ids); + + void reportResults(ReportList &reports) const; + bool wasSuccessful() const; + + private: + struct Stats { + int tot_cleared = 0; + ID *last_id = nullptr; + }; + + Stats stats; +}; + +void AssetClearHelper::operator()(PointerRNAVec &ids) +{ + for (PointerRNA &ptr : ids) { + BLI_assert(RNA_struct_is_ID(ptr.type)); + + ID *id = static_cast<ID *>(ptr.data); + if (!id->asset_data) { + continue; + } + + if (ED_asset_clear_id(id)) { + stats.tot_cleared++; + stats.last_id = id; + } + } +} + +void AssetClearHelper::reportResults(ReportList &reports) const +{ + if (!wasSuccessful()) { + BKE_report(&reports, RPT_ERROR, "No asset data-blocks selected/focused"); + } + else if (stats.tot_cleared == 1) { + /* If only one data-block: Give more useful message by printing asset name. */ + BKE_reportf( + &reports, RPT_INFO, "Data-block '%s' is no asset anymore", stats.last_id->name + 2); + } + else { + BKE_reportf(&reports, RPT_INFO, "%i data-blocks are no assets anymore", stats.tot_cleared); + } +} + +bool AssetClearHelper::wasSuccessful() const +{ + return stats.tot_cleared > 0; +} + +static int asset_clear_exec(bContext *C, wmOperator *op) +{ + PointerRNAVec ids = asset_operation_get_ids_from_context(C); + + AssetClearHelper clear_helper; + clear_helper(ids); + clear_helper.reportResults(*op->reports); + + if (!clear_helper.wasSuccessful()) { + return OPERATOR_CANCELLED; + } + + WM_main_add_notifier(NC_ID | NA_EDITED, nullptr); + WM_main_add_notifier(NC_ASSET | NA_REMOVED, nullptr); + + return OPERATOR_FINISHED; +} + +static void ASSET_OT_clear(wmOperatorType *ot) +{ + ot->name = "Clear Asset"; + ot->description = + "Delete all asset metadata and turn the selected asset data-blocks back into normal " + "data-blocks"; + ot->idname = "ASSET_OT_clear"; + + ot->exec = asset_clear_exec; + ot->poll = asset_operation_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* -------------------------------------------------------------------- */ + +void ED_operatortypes_asset(void) +{ + WM_operatortype_append(ASSET_OT_mark); + WM_operatortype_append(ASSET_OT_clear); +} diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index e9ceedf7ce2..8ebc2077619 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -2419,7 +2419,7 @@ static void adduplicateflagNurb( memcpy(newnu->bp, &nu->bp[a], newu * newv * sizeof(BPoint)); memcpy(&newnu->bp[newu * newv], nu->bp, newu * cyclicv * sizeof(BPoint)); - /* check for actvert in cylicv selection */ + /* check for actvert in cyclicv selection */ if (cu->actnu == i) { calc_duplicate_actvert( editnurb, newnurb, cu, cu->actvert, a, (newu * newv) + cu->actvert); @@ -6102,7 +6102,7 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) } if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) { - /* start and points copied if connecting segment was deleted and not cylic spline */ + /* start and points copied if connecting segment was deleted and not cyclic spline */ bezt1 = nu->bezt; bezt2 = &nu->bezt[1]; @@ -6232,7 +6232,7 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) } if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) { - /* start and points copied if connecting segment was deleted and not cylic spline */ + /* start and points copied if connecting segment was deleted and not cyclic spline */ bp1 = nu->bp; bp2 = &nu->bp[1]; @@ -6352,7 +6352,7 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) } if (!split && cut != -1 && nu->pntsv > 2 && !(nu->flagv & CU_NURB_CYCLIC)) { - /* start and points copied if connecting segment was deleted and not cylic spline */ + /* start and points copied if connecting segment was deleted and not cyclic spline */ bp1 = nu->bp; bp2 = &nu->bp[nu->pntsu]; diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index 4097275a2b9..82f7b456284 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -1242,7 +1242,7 @@ static void curve_select_random(ListBase *editnurb, float randfac, int seed, boo static int curve_select_random_exec(bContext *C, wmOperator *op) { const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); ViewLayer *view_layer = CTX_data_view_layer(C); diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c index 534d29c0cc7..681f387e83e 100644 --- a/source/blender/editors/curve/editcurve_undo.c +++ b/source/blender/editors/curve/editcurve_undo.c @@ -238,8 +238,11 @@ static bool curve_undosys_step_encode(struct bContext *C, struct Main *bmain, Un return true; } -static void curve_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) +static void curve_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir UNUSED(dir), + bool UNUSED(is_final)) { CurveUndoStep *us = (CurveUndoStep *)us_p; diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c index 8559234b62f..07f062e7a53 100644 --- a/source/blender/editors/curve/editfont_undo.c +++ b/source/blender/editors/curve/editfont_undo.c @@ -356,8 +356,11 @@ static bool font_undosys_step_encode(struct bContext *C, struct Main *bmain, Und return true; } -static void font_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) +static void font_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir UNUSED(dir), + bool UNUSED(is_final)) { /* TODO(campbell): undo_system: use low-level API to set mode. */ ED_object_mode_set_ex(C, OB_MODE_EDIT, false, NULL); diff --git a/source/blender/editors/geometry/geometry_attributes.c b/source/blender/editors/geometry/geometry_attributes.c index 4106c03f17d..2807e7c4392 100644 --- a/source/blender/editors/geometry/geometry_attributes.c +++ b/source/blender/editors/geometry/geometry_attributes.c @@ -23,7 +23,6 @@ #include "BKE_attribute.h" #include "BKE_context.h" -#include "BKE_report.h" #include "RNA_access.h" #include "RNA_define.h" @@ -34,7 +33,6 @@ #include "WM_api.h" #include "WM_types.h" -#include "ED_geometry.h" #include "ED_object.h" #include "geometry_intern.h" diff --git a/source/blender/editors/gizmo_library/gizmo_library_presets.c b/source/blender/editors/gizmo_library/gizmo_library_presets.c index 9039851da01..4e56ceb9fd4 100644 --- a/source/blender/editors/gizmo_library/gizmo_library_presets.c +++ b/source/blender/editors/gizmo_library/gizmo_library_presets.c @@ -22,12 +22,9 @@ * \brief Preset shapes that can be drawn from any gizmo type. */ -#include "MEM_guardedalloc.h" - #include "BLI_math.h" #include "DNA_object_types.h" -#include "DNA_view3d_types.h" #include "BKE_context.h" @@ -36,12 +33,8 @@ #include "DEG_depsgraph.h" -#include "RNA_access.h" - -#include "WM_api.h" #include "WM_types.h" -#include "ED_screen.h" #include "ED_view3d.h" /* own includes */ diff --git a/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c index 5617b6e125e..1b1f1151053 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c @@ -28,14 +28,11 @@ #include "BKE_context.h" #include "ED_gizmo_library.h" -#include "ED_view3d.h" #include "WM_api.h" #include "WM_types.h" /* own includes */ -#include "../gizmo_geometry.h" -#include "../gizmo_library_intern.h" static void gizmo_blank_draw(const bContext *UNUSED(C), wmGizmo *UNUSED(gz)) { diff --git a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c index eb40500d011..cbca230da7e 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c @@ -320,6 +320,16 @@ static int gizmo_button2d_cursor_get(wmGizmo *gz) return WM_CURSOR_DEFAULT; } +static void gizmo_button2d_bounds(bContext *C, wmGizmo *gz, rcti *r_bounding_box) +{ + ScrArea *area = CTX_wm_area(C); + float rad = CIRCLE_RESOLUTION * U.dpi_fac / 2.0f; + r_bounding_box->xmin = gz->matrix_basis[3][0] + area->totrct.xmin - rad; + r_bounding_box->ymin = gz->matrix_basis[3][1] + area->totrct.ymin - rad; + r_bounding_box->xmax = r_bounding_box->xmin + rad; + r_bounding_box->ymax = r_bounding_box->ymin + rad; +} + static void gizmo_button2d_free(wmGizmo *gz) { ButtonGizmo2D *shape = (ButtonGizmo2D *)gz; @@ -346,6 +356,7 @@ static void GIZMO_GT_button_2d(wmGizmoType *gzt) gzt->draw_select = gizmo_button2d_draw_select; gzt->test_select = gizmo_button2d_test_select; gzt->cursor_get = gizmo_button2d_cursor_get; + gzt->screen_bounds_get = gizmo_button2d_bounds; gzt->free = gizmo_button2d_free; gzt->struct_size = sizeof(ButtonGizmo2D); diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 4e2951c3571..751f8333aaa 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -171,7 +171,8 @@ static void gpencil_draw_stroke_3d(tGPDdraw *tgpw, int totpoints = tgpw->gps->totpoints; const float viewport[2] = {(float)tgpw->winx, (float)tgpw->winy}; - float curpressure = points[0].pressure; + const float min_thickness = 0.05f; + float fpt[3]; /* if cyclic needs more vertex */ @@ -205,7 +206,6 @@ static void gpencil_draw_stroke_3d(tGPDdraw *tgpw, immUniform1i("fill_stroke", (int)tgpw->is_fill_stroke); /* draw stroke curve */ - GPU_line_width(max_ff(curpressure * thickness, 1.0f)); immBeginAtMost(GPU_PRIM_LINE_STRIP_ADJ, totpoints + cyclic_add + 2); const bGPDspoint *pt = points; @@ -215,18 +215,19 @@ static void gpencil_draw_stroke_3d(tGPDdraw *tgpw, gpencil_set_point_varying_color(points, ink, attr_id.color, (bool)tgpw->is_fill_stroke); if ((cyclic) && (totpoints > 2)) { - immAttr1f(attr_id.thickness, max_ff((points + totpoints - 1)->pressure * thickness, 1.0f)); + immAttr1f(attr_id.thickness, + max_ff((points + totpoints - 1)->pressure * thickness, min_thickness)); mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + totpoints - 1)->x); } else { - immAttr1f(attr_id.thickness, max_ff((points + 1)->pressure * thickness, 1.0f)); + immAttr1f(attr_id.thickness, max_ff((points + 1)->pressure * thickness, min_thickness)); mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + 1)->x); } immVertex3fv(attr_id.pos, fpt); } /* set point */ gpencil_set_point_varying_color(pt, ink, attr_id.color, (bool)tgpw->is_fill_stroke); - immAttr1f(attr_id.thickness, max_ff(pt->pressure * thickness, 1.0f)); + immAttr1f(attr_id.thickness, max_ff(pt->pressure * thickness, min_thickness)); mul_v3_m4v3(fpt, tgpw->diff_mat, &pt->x); immVertex3fv(attr_id.pos, fpt); } diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index aae31b11025..166111c582c 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -276,7 +276,7 @@ void ED_gpencil_layer_frames_duplicate(bGPDlayer *gpl) bGPDframe *gpfd; /* duplicate frame, and deselect self */ - gpfd = BKE_gpencil_frame_duplicate(gpf); + gpfd = BKE_gpencil_frame_duplicate(gpf, true); gpf->flag &= ~GP_FRAME_SELECT; BLI_insertlinkafter(&gpl->frames, gpf, gpfd); @@ -361,7 +361,7 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac) /* if frame is selected, make duplicate it and its strokes */ if (gpf->flag & GP_FRAME_SELECT) { /* make a copy of this frame */ - bGPDframe *new_frame = BKE_gpencil_frame_duplicate(gpf); + bGPDframe *new_frame = BKE_gpencil_frame_duplicate(gpf, true); BLI_addtail(&copied_frames, new_frame); /* extend extents for keyframes encountered */ diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c index 65141442237..d86bad7ef3c 100644 --- a/source/blender/editors/gpencil/gpencil_add_monkey.c +++ b/source/blender/editors/gpencil/gpencil_add_monkey.c @@ -29,16 +29,13 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BKE_brush.h" #include "BKE_context.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" -#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "ED_gpencil.h" diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c index 0c8cc621a3b..1e1a70f9c1d 100644 --- a/source/blender/editors/gpencil/gpencil_add_stroke.c +++ b/source/blender/editors/gpencil/gpencil_add_stroke.c @@ -29,16 +29,13 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BKE_brush.h" #include "BKE_context.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" -#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "ED_gpencil.h" diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c index 5cc5e7ecdcd..3271096c433 100644 --- a/source/blender/editors/gpencil/gpencil_armature.c +++ b/source/blender/editors/gpencil/gpencil_armature.c @@ -31,12 +31,9 @@ #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLT_translation.h" - #include "DNA_armature_types.h" #include "DNA_gpencil_types.h" #include "DNA_meshdata_types.h" diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 09b57029350..ac75ae44c8a 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -178,7 +178,7 @@ static void gpencil_strokepoint_convertcoords(bContext *C, /* apply parent transform */ float fpt[3]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); mul_v3_m4v3(fpt, diff_mat, &source_pt->x); copy_v3_v3(&pt->x, fpt); @@ -370,7 +370,7 @@ static int gpencil_find_end_of_stroke_idx(tGpTimingData *gtd, static void gpencil_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rng, int *nbr_gaps, - float *tot_gaps_time) + float *r_tot_gaps_time) { float delta_time = 0.0f; @@ -387,10 +387,10 @@ static void gpencil_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, } gtd->tot_time -= delta_time; - *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration; - gtd->tot_time += *tot_gaps_time; + *r_tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration; + gtd->tot_time += *r_tot_gaps_time; if (G.debug & G_DEBUG) { - printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps); + printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *r_tot_gaps_time, *nbr_gaps); } if (gtd->gap_randomness > 0.0f) { BLI_rng_srandom(rng, gtd->seed); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index ad9b72b713e..3be913f342d 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -449,21 +449,32 @@ void GPENCIL_OT_layer_annotation_move(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", ""); } /* ********************* Duplicate Layer ************************** */ +enum { + GP_LAYER_DUPLICATE_ALL = 0, + GP_LAYER_DUPLICATE_EMPTY = 1, +}; -static int gpencil_layer_copy_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_layer_copy_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); bGPDlayer *new_layer; - + const int mode = RNA_enum_get(op->ptr, "mode"); + const bool dup_strokes = (bool)(mode == GP_LAYER_DUPLICATE_ALL); /* sanity checks */ if (ELEM(NULL, gpd, gpl)) { return OPERATOR_CANCELLED; } - /* make copy of layer, and add it immediately after the existing layer */ - new_layer = BKE_gpencil_layer_duplicate(gpl); - BLI_insertlinkafter(&gpd->layers, gpl, new_layer); + /* Make copy of layer, and add it immediately after or before the existing layer. */ + new_layer = BKE_gpencil_layer_duplicate(gpl, true, dup_strokes); + if (dup_strokes) { + BLI_insertlinkafter(&gpd->layers, gpl, new_layer); + } + else { + /* For empty strokes is better add below. */ + BLI_insertlinkbefore(&gpd->layers, gpl, new_layer); + } /* ensure new layer has a unique name, and is now the active layer */ BLI_uniquename(&gpd->layers, @@ -484,6 +495,12 @@ static int gpencil_layer_copy_exec(bContext *C, wmOperator *UNUSED(op)) void GPENCIL_OT_layer_duplicate(wmOperatorType *ot) { + static const EnumPropertyItem copy_mode[] = { + {GP_LAYER_DUPLICATE_ALL, "ALL", 0, "All Data", ""}, + {GP_LAYER_DUPLICATE_EMPTY, "EMPTY", 0, "Empty Keyframes", ""}, + {0, NULL, 0, NULL, NULL}, + }; + /* identifiers */ ot->name = "Duplicate Layer"; ot->idname = "GPENCIL_OT_layer_duplicate"; @@ -495,6 +512,8 @@ void GPENCIL_OT_layer_duplicate(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "mode", copy_mode, GP_LAYER_DUPLICATE_ALL, "Mode", ""); } /* ********************* Duplicate Layer in a new object ************************** */ @@ -1560,7 +1579,7 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* some stroke is already at front*/ @@ -1725,7 +1744,7 @@ static int gpencil_stroke_change_color_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } @@ -2849,12 +2868,12 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) mul_v3_m3v3(offset_local, imat, offset_global); LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) { - bGPDlayer *gpl_new = BKE_gpencil_layer_duplicate(gpl_src); + bGPDlayer *gpl_new = BKE_gpencil_layer_duplicate(gpl_src, true, true); float diff_mat[4][4]; float inverse_diff_mat[4][4]; /* recalculate all stroke points */ - BKE_gpencil_parent_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat); invert_m4_m4_safe_ortho(inverse_diff_mat, diff_mat); Material *ma_src = NULL; @@ -3388,7 +3407,7 @@ static int gpencil_material_select_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index d1c8eca1be0..aeff2acb04d 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -1867,7 +1867,7 @@ static int gpencil_move_to_layer_exec(bContext *C, wmOperator *op) } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } @@ -2610,7 +2610,7 @@ static int gpencil_delete_selected_points(bContext *C) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } @@ -2800,7 +2800,7 @@ static int gpencil_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) float diff_mat[4][4]; /* calculate difference matrix object */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { /* skip strokes that are invalid for current view */ @@ -2808,7 +2808,7 @@ static int gpencil_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } @@ -2935,7 +2935,7 @@ static int gpencil_snap_to_cursor(bContext *C, wmOperator *op) float diff_mat[4][4]; /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { bGPDspoint *pt; @@ -2946,7 +2946,7 @@ static int gpencil_snap_to_cursor(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* only continue if this stroke is selected (editable doesn't guarantee this)... */ @@ -3039,7 +3039,7 @@ static bool gpencil_stroke_points_centroid(Depsgraph *depsgraph, float diff_mat[4][4]; /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { bGPDspoint *pt; @@ -3050,7 +3050,7 @@ static bool gpencil_stroke_points_centroid(Depsgraph *depsgraph, continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* only continue if this stroke is selected (editable doesn't guarantee this)... */ @@ -3565,7 +3565,7 @@ static int gpencil_stroke_join_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable. */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } elem = &strokes_list[tot_strokes]; @@ -3697,7 +3697,7 @@ static int gpencil_stroke_flip_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } @@ -4516,7 +4516,7 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* Separate selected strokes. */ @@ -4717,7 +4717,7 @@ static int gpencil_stroke_split_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* Split selected strokes. */ @@ -4948,11 +4948,14 @@ static int gpencil_cutter_lasso_select(bContext *C, GPencilTestFn is_inside_fn, void *user_data) { + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Object *obact = CTX_data_active_object(C); bGPdata *gpd = ED_gpencil_data_get_active(C); ScrArea *area = CTX_wm_area(C); ToolSettings *ts = CTX_data_tool_settings(C); const float scale = ts->gp_sculpt.isect_threshold; const bool flat_caps = RNA_boolean_get(op->ptr, "flat_caps"); + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); bGPDspoint *pt; GP_SpaceConversion gsc = {NULL}; @@ -4979,57 +4982,87 @@ static int gpencil_cutter_lasso_select(bContext *C, } CTX_DATA_END; - /* select points */ - GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { - int tot_inside = 0; - const int oldtot = gps->totpoints; - for (int i = 0; i < gps->totpoints; i++) { - pt = &gps->points[i]; - if ((pt->flag & GP_SPOINT_SELECT) || (pt->flag & GP_SPOINT_TAG)) { - continue; - } - /* convert point coords to screen-space */ - const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data); - if (is_inside) { - tot_inside++; - changed = true; - pt->flag |= GP_SPOINT_SELECT; - gps->flag |= GP_STROKE_SELECT; - float r_hita[3], r_hitb[3]; - if (gps->totpoints > 1) { - ED_gpencil_select_stroke_segment(gpd, gpl, gps, pt, true, true, scale, r_hita, r_hitb); + /* Select points */ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + if ((gpl->flag & GP_LAYER_LOCKED) || ((gpl->flag & GP_LAYER_HIDE))) { + continue; + } + + float diff_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; + } + + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; + } /* check if the color is editable */ + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { + continue; + } + int tot_inside = 0; + const int oldtot = gps->totpoints; + for (int i = 0; i < gps->totpoints; i++) { + pt = &gps->points[i]; + if ((pt->flag & GP_SPOINT_SELECT) || (pt->flag & GP_SPOINT_TAG)) { + continue; + } + /* convert point coords to screen-space */ + const bool is_inside = is_inside_fn(gps, pt, &gsc, diff_mat, user_data); + if (is_inside) { + tot_inside++; + changed = true; + pt->flag |= GP_SPOINT_SELECT; + gps->flag |= GP_STROKE_SELECT; + float r_hita[3], r_hitb[3]; + if (gps->totpoints > 1) { + ED_gpencil_select_stroke_segment( + gpd, gpl, gps, pt, true, true, scale, r_hita, r_hitb); + } + /* avoid infinite loops */ + if (gps->totpoints > oldtot) { + break; + } + } + } + /* if mark all points inside lasso set to remove all stroke */ + if ((tot_inside == oldtot) || ((tot_inside == 1) && (oldtot == 2))) { + for (int i = 0; i < gps->totpoints; i++) { + pt = &gps->points[i]; + pt->flag |= GP_SPOINT_SELECT; + } + } } - /* avoid infinite loops */ - if (gps->totpoints > oldtot) { + /* if not multiedit, exit loop. */ + if (!is_multiedit) { break; } } } - /* if mark all points inside lasso set to remove all stroke */ - if ((tot_inside == oldtot) || ((tot_inside == 1) && (oldtot == 2))) { - for (int i = 0; i < gps->totpoints; i++) { - pt = &gps->points[i]; - pt->flag |= GP_SPOINT_SELECT; - } - } } - GP_EDITABLE_STROKES_END(gpstroke_iter); - /* dissolve selected points */ + /* Dissolve selected points. */ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - if (gpl->flag & GP_LAYER_LOCKED) { - continue; - } - - bGPDframe *gpf = gpl->actframe; - if (gpf == NULL) { - continue; - } - LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { - if (gps->flag & GP_STROKE_SELECT) { - gpencil_cutter_dissolve(gpd, gpl, gps, flat_caps); + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; + bGPDframe *gpf_act = gpl->actframe; + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + gpl->actframe = gpf; + LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { + if (gps->flag & GP_STROKE_SELECT) { + gpencil_cutter_dissolve(gpd, gpl, gps, flat_caps); + } + } + /* if not multiedit, exit loop. */ + if (!is_multiedit) { + break; } } + gpl->actframe = gpf_act; } /* updates */ diff --git a/source/blender/editors/gpencil/gpencil_edit_curve.c b/source/blender/editors/gpencil/gpencil_edit_curve.c index 60d1d2169b4..031bbd61173 100644 --- a/source/blender/editors/gpencil/gpencil_edit_curve.c +++ b/source/blender/editors/gpencil/gpencil_edit_curve.c @@ -28,13 +28,10 @@ #include <stdlib.h> #include <string.h> -#include "MEM_guardedalloc.h" - #include "DNA_gpencil_types.h" #include "DNA_view3d_types.h" #include "BKE_context.h" -#include "BKE_curve.h" #include "BKE_gpencil.h" #include "BKE_gpencil_curve.h" #include "BKE_gpencil_geom.h" diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 8bd0b2f86de..832191c8321 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -26,6 +26,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BLI_math.h" #include "BLI_stack.h" #include "BLI_utildefines.h" @@ -81,8 +82,18 @@ #define LEAK_HORZ 0 #define LEAK_VERT 1 +#define MIN_WINDOW_SIZE 128 -/* Temporary fill operation data (op->customdata) */ +/* Set to 1 to debug filling internal image. By default, the value must be 0. */ +#define FILL_DEBUG 0 + +/* Duplicated: etempFlags */ +enum { + GP_DRAWFILLS_NOSTATUS = (1 << 0), /* don't draw status info */ + GP_DRAWFILLS_ONLY3D = (1 << 1), /* only draw 3d-strokes */ +}; + +/* Temporary fill operation data `op->customdata`. */ typedef struct tGPDfill { bContext *C; struct Main *bmain; @@ -101,7 +112,7 @@ typedef struct tGPDfill { struct View3D *v3d; /** region where painting originated */ struct ARegion *region; - /** current GP datablock */ + /** Current GP data-block. */ struct bGPdata *gpd; /** current material */ struct Material *mat; @@ -111,6 +122,8 @@ typedef struct tGPDfill { struct bGPDlayer *gpl; /** frame */ struct bGPDframe *gpf; + /** Temp mouse position stroke. */ + struct bGPDstroke *gps_mouse; /** flags */ short flag; @@ -118,9 +131,12 @@ typedef struct tGPDfill { short oldkey; /** send to back stroke */ bool on_back; - + /** Flag for render mode */ + bool is_render; + /** Flag to check something was done. */ + bool done; /** mouse fill center position */ - int center[2]; + int mouse[2]; /** windows width */ int sizex; /** window height */ @@ -137,7 +153,7 @@ typedef struct tGPDfill { /** boundary limits drawing mode */ int fill_draw_mode; /* scaling factor */ - short fill_factor; + float fill_factor; /* Frame to use. */ int active_cfra; @@ -156,14 +172,184 @@ typedef struct tGPDfill { /** handle for drawing strokes while operator is running 3d stuff */ void *draw_handle_3d; - /* tmp size x */ + /* Temporary size x. */ int bwinx; - /* tmp size y */ + /* Temporary size y. */ int bwiny; rcti brect; + /* Space Conversion Data */ + GP_SpaceConversion gsc; + + /** Zoom factor. */ + float zoom; + + /** Factor of extension. */ + float fill_extend_fac; + } tGPDfill; +bool skip_layer_check(short fill_layer_mode, int gpl_active_index, int gpl_index); +static void gpencil_draw_boundary_lines(const struct bContext *UNUSED(C), struct tGPDfill *tgpf); + +/* Delete any temporary stroke. */ +static void gpencil_delete_temp_stroke_extension(tGPDfill *tgpf, const bool all_frames) +{ + LISTBASE_FOREACH (bGPDlayer *, gpl, &tgpf->gpd->layers) { + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + + bGPDframe *init_gpf = (all_frames) ? gpl->frames.first : + BKE_gpencil_layer_frame_get( + gpl, tgpf->active_cfra, GP_GETFRAME_USE_PREV); + if (init_gpf == NULL) { + continue; + } + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { + /* free stroke */ + if ((gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG)) { + BLI_remlink(&gpf->strokes, gps); + BKE_gpencil_free_stroke(gps); + } + } + if (!all_frames) { + break; + } + } + } +} + +static void extrapolate_points_by_length(bGPDspoint *a, + bGPDspoint *b, + float length, + float r_point[3]) +{ + float ab[3]; + sub_v3_v3v3(ab, &b->x, &a->x); + normalize_v3(ab); + mul_v3_fl(ab, length); + add_v3_v3v3(r_point, &b->x, ab); +} + +/* Loop all layers create stroke extensions. */ +static void gpencil_create_extensions(tGPDfill *tgpf) +{ + Object *ob = tgpf->ob; + bGPdata *gpd = tgpf->gpd; + Brush *brush = tgpf->brush; + BrushGpencilSettings *brush_settings = brush->gpencil_settings; + + bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd); + BLI_assert(gpl_active != NULL); + + const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active); + BLI_assert(gpl_active_index >= 0); + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + + /* Decide if the strokes of layers are included or not depending on the layer mode. */ + const int gpl_index = BLI_findindex(&gpd->layers, gpl); + bool skip = skip_layer_check(brush_settings->fill_layer_mode, gpl_active_index, gpl_index); + if (skip) { + continue; + } + + bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, GP_GETFRAME_USE_PREV); + if (gpf == NULL) { + continue; + } + + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* Check if stroke can be drawn. */ + if ((gps->points == NULL) || (gps->totpoints < 2)) { + continue; + } + if (gps->flag & (GP_STROKE_NOFILL | GP_STROKE_TAG)) { + continue; + } + /* Check if the color is visible. */ + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); + if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE)) { + continue; + } + + /* Extend start. */ + bGPDspoint *pt0 = &gps->points[1]; + bGPDspoint *pt1 = &gps->points[0]; + bGPDstroke *gps_new = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness); + gps_new->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG; + BLI_addtail(&gpf->strokes, gps_new); + + bGPDspoint *pt = &gps_new->points[0]; + copy_v3_v3(&pt->x, &pt1->x); + pt->strength = 1.0f; + pt->pressure = 1.0f; + + pt = &gps_new->points[1]; + pt->strength = 1.0f; + pt->pressure = 1.0f; + extrapolate_points_by_length(pt0, pt1, tgpf->fill_extend_fac * 0.1f, &pt->x); + + /* Extend end. */ + pt0 = &gps->points[gps->totpoints - 2]; + pt1 = &gps->points[gps->totpoints - 1]; + gps_new = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness); + gps_new->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG; + BLI_addtail(&gpf->strokes, gps_new); + + pt = &gps_new->points[0]; + copy_v3_v3(&pt->x, &pt1->x); + pt->strength = 1.0f; + pt->pressure = 1.0f; + + pt = &gps_new->points[1]; + pt->strength = 1.0f; + pt->pressure = 1.0f; + extrapolate_points_by_length(pt0, pt1, tgpf->fill_extend_fac * 0.1f, &pt->x); + } + } +} + +static void gpencil_update_extend(tGPDfill *tgpf) +{ + gpencil_delete_temp_stroke_extension(tgpf, false); + + if (tgpf->fill_extend_fac > 0.0f) { + gpencil_create_extensions(tgpf); + } + WM_event_add_notifier(tgpf->C, NC_GPENCIL | NA_EDITED, NULL); +} + +static bool gpencil_stroke_is_drawable(tGPDfill *tgpf, bGPDstroke *gps) +{ + if (tgpf->is_render) { + return true; + } + + const bool show_help = (tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) != 0; + const bool show_extend = (tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES) != 0; + const bool is_extend = (gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG); + + if ((!show_help) && (show_extend)) { + if (!is_extend) { + return false; + } + } + + if ((show_help) && (!show_extend)) { + if (is_extend) { + return false; + } + } + + return true; +} + /* draw a given stroke using same thickness and color for all points */ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, bGPDstroke *gps, @@ -171,7 +357,8 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, const bool cyclic, const float ink[4], const int flag, - const float thershold) + const float thershold, + const float thickness) { bGPDspoint *points = gps->points; @@ -181,9 +368,19 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, int totpoints = gps->totpoints; float fpt[3]; float col[4]; + const float extend_col[4] = {0.0f, 1.0f, 1.0f, 1.0f}; + const bool is_extend = (gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG); - copy_v4_v4(col, ink); + if (!gpencil_stroke_is_drawable(tgpf, gps)) { + return; + } + if ((is_extend) && (!tgpf->is_render)) { + copy_v4_v4(col, extend_col); + } + else { + copy_v4_v4(col, ink); + } /* if cyclic needs more vertex */ int cyclic_add = (cyclic) ? 1 : 0; @@ -194,7 +391,7 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); /* draw stroke curve */ - GPU_line_width(1.0f); + GPU_line_width((!is_extend) ? thickness : thickness * 2.0f); immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add); const bGPDspoint *pt = points; @@ -225,15 +422,77 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, immUnbindProgram(); } -/* loop all layers */ -static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) +static void draw_mouse_position(tGPDfill *tgpf) { - /* duplicated: etempFlags */ - enum { - GP_DRAWFILLS_NOSTATUS = (1 << 0), /* don't draw status info */ - GP_DRAWFILLS_ONLY3D = (1 << 1), /* only draw 3d-strokes */ - }; + if (tgpf->gps_mouse == NULL) { + return; + } + uchar mouse_color[4] = {0, 0, 255, 255}; + bGPDspoint *pt = &tgpf->gps_mouse->points[0]; + float point_size = (tgpf->zoom == 1.0f) ? 4.0f * tgpf->fill_factor : + (0.5f * tgpf->zoom) + tgpf->fill_factor; + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + + /* Draw mouse click position in Blue. */ + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); + GPU_point_size(point_size); + immBegin(GPU_PRIM_POINTS, 1); + immAttr4ubv(col, mouse_color); + immVertex3fv(pos, &pt->x); + immEnd(); + immUnbindProgram(); +} + +/* Helper: Check if must skip the layer */ +bool skip_layer_check(short fill_layer_mode, int gpl_active_index, int gpl_index) +{ + bool skip = false; + + switch (fill_layer_mode) { + case GP_FILL_GPLMODE_ACTIVE: { + if (gpl_index != gpl_active_index) { + skip = true; + } + break; + } + case GP_FILL_GPLMODE_ABOVE: { + if (gpl_index != gpl_active_index + 1) { + skip = true; + } + break; + } + case GP_FILL_GPLMODE_BELOW: { + if (gpl_index != gpl_active_index - 1) { + skip = true; + } + break; + } + case GP_FILL_GPLMODE_ALL_ABOVE: { + if (gpl_index <= gpl_active_index) { + skip = true; + } + break; + } + case GP_FILL_GPLMODE_ALL_BELOW: { + if (gpl_index >= gpl_active_index) { + skip = true; + } + break; + } + case GP_FILL_GPLMODE_VISIBLE: + default: + break; + } + + return skip; +} + +/* Loop all layers to draw strokes. */ +static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) +{ Object *ob = tgpf->ob; bGPdata *gpd = tgpf->gpd; Brush *brush = tgpf->brush; @@ -247,8 +506,8 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) tgpw.gpd = gpd; tgpw.offsx = 0; tgpw.offsy = 0; - tgpw.winx = tgpf->region->winx; - tgpw.winy = tgpf->region->winy; + tgpw.winx = tgpf->sizex; + tgpw.winy = tgpf->sizey; tgpw.dflag = 0; tgpw.disable_fill = 1; tgpw.dflag |= (GP_DRAWFILLS_ONLY3D | GP_DRAWFILLS_NOSTATUS); @@ -261,54 +520,22 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active); BLI_assert(gpl_active_index >= 0); - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* calculate parent position */ - BKE_gpencil_parent_matrix_get(tgpw.depsgraph, ob, gpl, tgpw.diff_mat); + /* Draw blue point where click with mouse. */ + draw_mouse_position(tgpf); + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { /* do not draw layer if hidden */ if (gpl->flag & GP_LAYER_HIDE) { continue; } + /* calculate parent position */ + BKE_gpencil_layer_transform_matrix_get(tgpw.depsgraph, ob, gpl, tgpw.diff_mat); + /* Decide if the strokes of layers are included or not depending on the layer mode. * Cannot skip the layer because it can use boundary strokes and must be used. */ - bool skip = false; const int gpl_index = BLI_findindex(&gpd->layers, gpl); - switch (brush_settings->fill_layer_mode) { - case GP_FILL_GPLMODE_ACTIVE: { - if (gpl_index != gpl_active_index) { - skip = true; - } - break; - } - case GP_FILL_GPLMODE_ABOVE: { - if (gpl_index != gpl_active_index + 1) { - skip = true; - } - break; - } - case GP_FILL_GPLMODE_BELOW: { - if (gpl_index != gpl_active_index - 1) { - skip = true; - } - break; - } - case GP_FILL_GPLMODE_ALL_ABOVE: { - if (gpl_index <= gpl_active_index) { - skip = true; - } - break; - } - case GP_FILL_GPLMODE_ALL_BELOW: { - if (gpl_index >= gpl_active_index) { - skip = true; - } - break; - } - case GP_FILL_GPLMODE_VISIBLE: - default: - break; - } + bool skip = skip_layer_check(brush_settings->fill_layer_mode, gpl_active_index, gpl_index); /* if active layer and no keyframe, create a new one */ if (gpl == tgpf->gpl) { @@ -351,17 +578,19 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) tgpw.gpf = gpf; tgpw.t_gpf = gpf; - /* reduce thickness to avoid gaps */ tgpw.is_fill_stroke = (tgpf->fill_draw_mode == GP_FILL_DMODE_CONTROL) ? false : true; + /* Reduce thickness to avoid gaps. */ tgpw.lthick = gpl->line_change; tgpw.opacity = 1.0; copy_v4_v4(tgpw.tintcolor, ink); tgpw.onion = true; tgpw.custonion = true; - /* normal strokes */ + /* Normal strokes. */ if (ELEM(tgpf->fill_draw_mode, GP_FILL_DMODE_STROKE, GP_FILL_DMODE_BOTH)) { - ED_gpencil_draw_fill(&tgpw); + if (gpencil_stroke_is_drawable(tgpf, gps) && ((gps->flag & GP_STROKE_TAG) == 0)) { + ED_gpencil_draw_fill(&tgpw); + } } /* 3D Lines with basic shapes and invisible lines */ @@ -372,7 +601,8 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) gps->flag & GP_STROKE_CYCLIC, ink, tgpf->flag, - tgpf->fill_threshold); + tgpf->fill_threshold, + 1.0f); } } } @@ -380,7 +610,7 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) GPU_blend(GPU_BLEND_NONE); } -/* draw strokes in offscreen buffer */ +/* Draw strokes in off-screen buffer. */ static bool gpencil_render_offscreen(tGPDfill *tgpf) { bool is_ortho = false; @@ -391,15 +621,15 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) } /* set temporary new size */ - tgpf->bwinx = tgpf->region->winx; - tgpf->bwiny = tgpf->region->winy; + tgpf->bwinx = tgpf->region->sizex; + tgpf->bwiny = tgpf->region->sizey; tgpf->brect = tgpf->region->winrct; /* resize region */ tgpf->region->winrct.xmin = 0; tgpf->region->winrct.ymin = 0; - tgpf->region->winrct.xmax = (int)tgpf->region->winx * tgpf->fill_factor; - tgpf->region->winrct.ymax = (int)tgpf->region->winy * tgpf->fill_factor; + tgpf->region->winrct.xmax = max_ii((int)tgpf->region->winx * tgpf->fill_factor, MIN_WINDOW_SIZE); + tgpf->region->winrct.ymax = max_ii((int)tgpf->region->winy * tgpf->fill_factor, MIN_WINDOW_SIZE); tgpf->region->winx = (short)abs(tgpf->region->winrct.xmax - tgpf->region->winrct.xmin); tgpf->region->winy = (short)abs(tgpf->region->winrct.ymax - tgpf->region->winrct.ymin); @@ -407,12 +637,6 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) tgpf->sizex = (int)tgpf->region->winx; tgpf->sizey = (int)tgpf->region->winy; - /* adjust center */ - float center[2]; - center[0] = (float)tgpf->center[0] * ((float)tgpf->region->winx / (float)tgpf->bwinx); - center[1] = (float)tgpf->center[1] * ((float)tgpf->region->winy / (float)tgpf->bwiny); - round_v2i_v2fl(tgpf->center, center); - char err_out[256] = "unknown"; GPUOffScreen *offscreen = GPU_offscreen_create(tgpf->sizex, tgpf->sizey, true, false, err_out); if (offscreen == NULL) { @@ -421,7 +645,7 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) } GPU_offscreen_bind(offscreen, true); - uint flag = IB_rect | IB_rectfloat; + uint flag = IB_rectfloat; ImBuf *ibuf = IMB_allocImBuf(tgpf->sizex, tgpf->sizey, 32, flag); rctf viewplane; @@ -436,6 +660,21 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) &clip_start, &clip_end, NULL); + + /* Rescale `viewplane` to fit all strokes. */ + float width = viewplane.xmax - viewplane.xmin; + float height = viewplane.ymax - viewplane.ymin; + + float width_new = width * tgpf->zoom; + float height_new = height * tgpf->zoom; + float scale_x = (width_new - width) / 2.0f; + float scale_y = (height_new - height) / 2.0f; + + viewplane.xmin -= scale_x; + viewplane.xmax += scale_x; + viewplane.ymin -= scale_y; + viewplane.ymax += scale_y; + if (is_ortho) { orthographic_m4(winmat, viewplane.xmin, @@ -456,7 +695,7 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) } GPU_matrix_push_projection(); - GPU_matrix_identity_set(); + GPU_matrix_identity_projection_set(); GPU_matrix_push(); GPU_matrix_identity_set(); @@ -495,45 +734,33 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) BKE_image_release_ibuf(tgpf->ima, ibuf, NULL); - /* switch back to window-system-provided framebuffer */ + /* Switch back to window-system-provided frame-buffer. */ GPU_offscreen_unbind(offscreen, true); GPU_offscreen_free(offscreen); return true; } -/* return pixel data (rgba) at index */ +/* Return pixel data (RGBA) at index. */ static void get_pixel(const ImBuf *ibuf, const int idx, float r_col[4]) { - if (ibuf->rect_float) { - const float *frgba = &ibuf->rect_float[idx * 4]; - copy_v4_v4(r_col, frgba); - } - else { - /* XXX: This case probably doesn't happen, as we only write to the float buffer, - * but we get compiler warnings about uninitialized vars otherwise - */ - BLI_assert(!"gpencil_fill.c - get_pixel() non-float case is used!"); - zero_v4(r_col); - } + BLI_assert(ibuf->rect_float != NULL); + memcpy(r_col, &ibuf->rect_float[idx * 4], sizeof(float[4])); } -/* set pixel data (rgba) at index */ +/* Set pixel data (RGBA) at index. */ static void set_pixel(ImBuf *ibuf, int idx, const float col[4]) { - // BLI_assert(idx <= ibuf->x * ibuf->y); - if (ibuf->rect) { - uint *rrect = &ibuf->rect[idx]; - uchar ccol[4]; - - rgba_float_to_uchar(ccol, col); - *rrect = *((uint *)ccol); - } + BLI_assert(ibuf->rect_float != NULL); + float *rrectf = &ibuf->rect_float[idx * 4]; + copy_v4_v4(rrectf, col); +} - if (ibuf->rect_float) { - float *rrectf = &ibuf->rect_float[idx * 4]; - copy_v4_v4(rrectf, col); - } +/* Helper: Check if one image row is empty. */ +static bool is_row_filled(const ImBuf *ibuf, const int row_index) +{ + float *row = &ibuf->rect_float[ibuf->x * 4 * row_index]; + return (row[0] == 0.0f && memcmp(row, row + 1, ((ibuf->x * 4) - 1) * sizeof(float)) != 0); } /** @@ -541,6 +768,9 @@ static void set_pixel(ImBuf *ibuf, int idx, const float col[4]) * this is used for strokes with small gaps between them to get a full fill * and do not get a full screen fill. * + * This function assumes that if the furthest pixel is occupied, + * the other pixels are occupied. + * * \param ibuf: Image pixel data. * \param maxpixel: Maximum index. * \param limit: Limit of pixels to analyze. @@ -550,10 +780,10 @@ static void set_pixel(ImBuf *ibuf, int idx, const float col[4]) static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index, int type) { float rgba[4]; - int i; int pt; bool t_a = false; bool t_b = false; + const int extreme = limit - 1; /* Horizontal leak (check vertical pixels) * X @@ -564,37 +794,29 @@ static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index */ if (type == LEAK_HORZ) { /* pixels on top */ - for (i = 1; i <= limit; i++) { - pt = index + (ibuf->x * i); - if (pt <= maxpixel) { - get_pixel(ibuf, pt, rgba); - if (rgba[0] == 1.0f) { - t_a = true; - break; - } - } - else { - /* edge of image*/ + pt = index + (ibuf->x * extreme); + if (pt <= maxpixel) { + get_pixel(ibuf, pt, rgba); + if (rgba[0] == 1.0f) { t_a = true; - break; } } + else { + /* edge of image*/ + t_a = true; + } /* pixels on bottom */ - for (i = 1; i <= limit; i++) { - pt = index - (ibuf->x * i); - if (pt >= 0) { - get_pixel(ibuf, pt, rgba); - if (rgba[0] == 1.0f) { - t_b = true; - break; - } - } - else { - /* edge of image*/ + pt = index - (ibuf->x * extreme); + if (pt >= 0) { + get_pixel(ibuf, pt, rgba); + if (rgba[0] == 1.0f) { t_b = true; - break; } } + else { + /* edge of image*/ + t_b = true; + } } /* Vertical leak (check horizontal pixels) @@ -608,35 +830,27 @@ static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index int higpix = lowpix + ibuf->x - 1; /* pixels to right */ - for (i = 0; i < limit; i++) { - pt = index - (limit - i); - if (pt >= lowpix) { - get_pixel(ibuf, pt, rgba); - if (rgba[0] == 1.0f) { - t_a = true; - break; - } - } - else { - t_a = true; /* edge of image*/ - break; + pt = index - extreme; + if (pt >= lowpix) { + get_pixel(ibuf, pt, rgba); + if (rgba[0] == 1.0f) { + t_a = true; } } + else { + t_a = true; /* edge of image*/ + } /* pixels to left */ - for (i = 0; i < limit; i++) { - pt = index + (limit - i); - if (pt <= higpix) { - get_pixel(ibuf, pt, rgba); - if (rgba[0] == 1.0f) { - t_b = true; - break; - } - } - else { - t_b = true; /* edge of image */ - break; + pt = index + extreme; + if (pt <= higpix) { + get_pixel(ibuf, pt, rgba); + if (rgba[0] == 1.0f) { + t_b = true; } } + else { + t_b = true; /* edge of image */ + } } return (bool)(t_a && t_b); } @@ -659,23 +873,37 @@ static void gpencil_boundaryfill_area(tGPDfill *tgpf) BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__); - /* calculate index of the seed point using the position of the mouse */ - int index = (tgpf->sizex * tgpf->center[1]) + tgpf->center[0]; + /* Calculate index of the seed point using the position of the mouse looking + * for a blue pixel. */ + int index = -1; + for (int i = 0; i < maxpixel; i++) { + get_pixel(ibuf, i, rgba); + if (rgba[2] == 1.0f) { + index = i; + break; + } + } + if ((index >= 0) && (index <= maxpixel)) { - BLI_stack_push(stack, &index); + if (!FILL_DEBUG) { + BLI_stack_push(stack, &index); + } } - /* the fill use a stack to save the pixel list instead of the common recursive + /** + * The fill use a stack to save the pixel list instead of the common recursive * 4-contact point method. * The problem with recursive calls is that for big fill areas, we can get max limit * of recursive calls and STACK_OVERFLOW error. * * The 4-contact point analyze the pixels to the left, right, bottom and top - * ----------- - * | X | - * | XoX | - * | X | - * ----------- + * <pre> + * ----------- + * | X | + * | XoX | + * | X | + * ----------- + * </pre> */ while (!BLI_stack_is_empty(stack)) { int v; @@ -763,7 +991,7 @@ static void gpencil_set_borders(tGPDfill *tgpf, const bool transparent) tgpf->ima->id.tag |= LIB_TAG_DOIT; } -/* Invert image to paint invese area. */ +/* Invert image to paint inverse area. */ static void gpencil_invert_image(tGPDfill *tgpf) { ImBuf *ibuf; @@ -773,18 +1001,24 @@ static void gpencil_invert_image(tGPDfill *tgpf) ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock); const int maxpixel = (ibuf->x * ibuf->y) - 1; + const int center = ibuf->x / 2; for (int v = maxpixel; v != 0; v--) { float color[4]; get_pixel(ibuf, v, color); - /* Green. */ + /* Green->Red. */ if (color[1] == 1.0f) { set_pixel(ibuf, v, fill_col[0]); } + /* Red->Green */ else if (color[0] == 1.0f) { set_pixel(ibuf, v, fill_col[1]); + /* Add thickness of 2 pixels to avoid too thin lines. */ + int offset = (v % ibuf->x < center) ? 1 : -1; + set_pixel(ibuf, v + offset, fill_col[1]); } else { + /* Set to Transparent. */ set_pixel(ibuf, v, fill_col[2]); } } @@ -821,21 +1055,37 @@ static void gpencil_erase_processed_area(tGPDfill *tgpf) float rgba[4]; for (int idy = 0; idy < ibuf->y; idy++) { - bool clear = false; + int init = -1; + int end = -1; for (int idx = 0; idx < ibuf->x; idx++) { int image_idx = ibuf->x * idy + idx; get_pixel(ibuf, image_idx, rgba); /* Blue. */ if (rgba[2] == 1.0f) { - clear = true; + if (init < 0) { + init = image_idx; + } + else { + end = image_idx; + } } /* Red. */ else if (rgba[0] == 1.0f) { - clear = false; + if (init > -1) { + for (int i = init; i <= max_ii(init, end); i++) { + set_pixel(ibuf, i, clear_col); + } + init = -1; + end = -1; + } } - if (clear) { - set_pixel(ibuf, image_idx, clear_col); + } + /* Check last segment. */ + if (init > -1) { + for (int i = init; i <= max_ii(init, end); i++) { + set_pixel(ibuf, i, clear_col); } + set_pixel(ibuf, init, clear_col); } } @@ -845,98 +1095,112 @@ static void gpencil_erase_processed_area(tGPDfill *tgpf) tgpf->ima->id.tag |= LIB_TAG_DOIT; } -/* Naive dilate +/** + * Naive dilate * * Expand green areas into enclosing red areas. * Using stack prevents creep when replacing colors directly. + * <pre> * ----------- * XXXXXXX * XoooooX * XXooXXX * XXXX * ----------- + * </pre> */ -static void dilate_shape(ImBuf *ibuf) +static bool dilate_shape(ImBuf *ibuf) { + bool done = false; + BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__); const float green[4] = {0.0f, 1.0f, 0.0f, 1.0f}; - const int maxpixel = (ibuf->x * ibuf->y) - 1; + // const int maxpixel = (ibuf->x * ibuf->y) - 1; /* detect pixels and expand into red areas */ - for (int v = maxpixel; v != 0; v--) { - float color[4]; - int index; - int tp = 0; - int bm = 0; - int lt = 0; - int rt = 0; - get_pixel(ibuf, v, color); - if (color[1] == 1.0f) { - /* pixel left */ - if (v - 1 >= 0) { - index = v - 1; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); - lt = index; + for (int row = 0; row < ibuf->y; row++) { + if (!is_row_filled(ibuf, row)) { + continue; + } + int maxpixel = (ibuf->x * (row + 1)) - 1; + int minpixel = ibuf->x * row; + + for (int v = maxpixel; v != minpixel; v--) { + float color[4]; + int index; + get_pixel(ibuf, v, color); + if (color[1] == 1.0f) { + int tp = 0; + int bm = 0; + int lt = 0; + int rt = 0; + + /* pixel left */ + if (v - 1 >= 0) { + index = v - 1; + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + lt = index; + } } - } - /* pixel right */ - if (v + 1 <= maxpixel) { - index = v + 1; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); - rt = index; + /* pixel right */ + if (v + 1 <= maxpixel) { + index = v + 1; + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + rt = index; + } } - } - /* pixel top */ - if (v + ibuf->x <= maxpixel) { - index = v + ibuf->x; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); - tp = index; + /* pixel top */ + if (v + (ibuf->x * 1) <= maxpixel) { + index = v + (ibuf->x * 1); + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + tp = index; + } } - } - /* pixel bottom */ - if (v - ibuf->x >= 0) { - index = v - ibuf->x; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); - bm = index; + /* pixel bottom */ + if (v - (ibuf->x * 1) >= 0) { + index = v - (ibuf->x * 1); + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + bm = index; + } } - } - /* pixel top-left */ - if (tp && lt) { - index = tp - 1; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); + /* pixel top-left */ + if (tp && lt) { + index = tp - 1; + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + } } - } - /* pixel top-right */ - if (tp && rt) { - index = tp + 1; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); + /* pixel top-right */ + if (tp && rt) { + index = tp + 1; + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + } } - } - /* pixel bottom-left */ - if (bm && lt) { - index = bm - 1; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); + /* pixel bottom-left */ + if (bm && lt) { + index = bm - 1; + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + } } - } - /* pixel bottom-right */ - if (bm && rt) { - index = bm + 1; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); + /* pixel bottom-right */ + if (bm && rt) { + index = bm + 1; + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + } } } } @@ -946,8 +1210,11 @@ static void dilate_shape(ImBuf *ibuf) int v; BLI_stack_pop(stack, &v); set_pixel(ibuf, v, green); + done = true; } BLI_stack_free(stack); + + return done; } /* Get the outline points of a shape using Moore Neighborhood algorithm @@ -963,11 +1230,12 @@ static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate) int v[2]; int boundary_co[2]; int start_co[2]; + int first_co[2] = {-1, -1}; int backtracked_co[2]; int current_check_co[2]; int prev_check_co[2]; int backtracked_offset[1][2] = {{0, 0}}; - // bool boundary_found = false; + bool first_pixel = false; bool start_found = false; const int NEIGHBOR_COUNT = 8; @@ -992,7 +1260,6 @@ static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate) dilate_shape(ibuf); } - /* find the initial point to start outline analysis */ for (int idx = imagesize - 1; idx != 0; idx--) { get_pixel(ibuf, idx, rgba); if (rgba[1] == 1.0f) { @@ -1015,7 +1282,7 @@ static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate) int cur_back_offset = -1; for (int i = 0; i < NEIGHBOR_COUNT; i++) { if (backtracked_offset[0][0] == offset[i][0] && backtracked_offset[0][1] == offset[i][1]) { - /* Finding the bracktracked pixel offset index */ + /* Finding the back-tracked pixel offset index */ cur_back_offset = i; break; } @@ -1045,19 +1312,24 @@ static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate) cur_back_offset++; loop++; } - /* current pixel is equal to starting pixel */ - if (boundary_co[0] == start_co[0] && boundary_co[1] == start_co[1]) { + /* Current pixel is equal to starting or first pixel. */ + if ((boundary_co[0] == start_co[0] && boundary_co[1] == start_co[1]) || + (boundary_co[0] == first_co[0] && boundary_co[1] == first_co[1])) { BLI_stack_pop(tgpf->stack, &v); - // boundary_found = true; break; } + + if (!first_pixel) { + first_pixel = true; + copy_v2_v2_int(first_co, boundary_co); + } } /* release ibuf */ BKE_image_release_ibuf(tgpf->ima, ibuf, lock); } -/* get z-depth array to reproject on surface */ +/* Get z-depth array to reproject on surface. */ static void gpencil_get_depth_array(tGPDfill *tgpf) { tGPspoint *ptc; @@ -1108,7 +1380,7 @@ static void gpencil_get_depth_array(tGPDfill *tgpf) } if (found_depth == false) { - /* eeh... not much we can do.. :/, ignore depth in this case */ + /* Sigh! not much we can do here. Ignore depth in this case. */ for (i = totpoints - 1; i >= 0; i--) { tgpf->depth_arr[i] = 0.9999f; } @@ -1171,6 +1443,9 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) return; } + /* Set as done. */ + tgpf->done = true; + /* Get frame or create a new one. */ tgpf->gpf = BKE_gpencil_layer_frame_get(tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW); @@ -1275,7 +1550,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) float origin[3]; ED_gpencil_drawing_reference_get(tgpf->scene, tgpf->ob, ts->gpencil_v3d_align, origin); ED_gpencil_project_stroke_to_plane( - tgpf->scene, tgpf->ob, tgpf->rv3d, gps, origin, tgpf->lock_axis - 1); + tgpf->scene, tgpf->ob, tgpf->rv3d, tgpf->gpl, gps, origin, tgpf->lock_axis - 1); } /* if parented change position relative to parent object */ @@ -1326,7 +1601,6 @@ static void gpencil_fill_draw_3d(const bContext *C, ARegion *UNUSED(region), voi if (region != tgpf->region) { return; } - gpencil_draw_boundary_lines(C, tgpf); } @@ -1377,6 +1651,10 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *UNUSED(op)) tgpf->win = CTX_wm_window(C); tgpf->active_cfra = CFRA; + /* Setup space conversions. */ + gpencil_point_conversion_init(C, &tgpf->gsc); + tgpf->zoom = 1.0f; + /* set GP datablock */ tgpf->gpd = gpd; tgpf->gpl = BKE_gpencil_layer_active_get(gpd); @@ -1387,6 +1665,7 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *UNUSED(op)) tgpf->lock_axis = ts->gp_sculpt.lock_axis; tgpf->oldkey = -1; + tgpf->is_render = false; tgpf->sbuffer_used = 0; tgpf->sbuffer = NULL; tgpf->depth_arr = NULL; @@ -1395,11 +1674,13 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *UNUSED(op)) Brush *brush = BKE_paint_brush(&ts->gp_paint->paint); tgpf->brush = brush; tgpf->flag = brush->gpencil_settings->flag; - tgpf->fill_leak = brush->gpencil_settings->fill_leak; tgpf->fill_threshold = brush->gpencil_settings->fill_threshold; tgpf->fill_simplylvl = brush->gpencil_settings->fill_simplylvl; tgpf->fill_draw_mode = brush->gpencil_settings->fill_draw_mode; - tgpf->fill_factor = (short)max_ii(1, min_ii((int)brush->gpencil_settings->fill_factor, 8)); + tgpf->fill_extend_fac = brush->gpencil_settings->fill_extend_fac; + tgpf->fill_factor = max_ff(GPENCIL_MIN_FILL_FAC, + min_ff(brush->gpencil_settings->fill_factor, GPENCIL_MAX_FILL_FAC)); + tgpf->fill_leak = (int)ceil((float)brush->gpencil_settings->fill_leak * tgpf->fill_factor); int totcol = tgpf->ob->totcol; @@ -1424,7 +1705,6 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *UNUSED(op)) /* end operator */ static void gpencil_fill_exit(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); Object *ob = CTX_data_active_object(C); /* clear undo stack */ @@ -1443,16 +1723,14 @@ static void gpencil_fill_exit(bContext *C, wmOperator *op) MEM_SAFE_FREE(tgpf->sbuffer); MEM_SAFE_FREE(tgpf->depth_arr); + /* Remove any temp stroke. */ + gpencil_delete_temp_stroke_extension(tgpf, true); + /* remove drawing handler */ if (tgpf->draw_handle_3d) { ED_region_draw_cb_exit(tgpf->region->type, tgpf->draw_handle_3d); } - /* Delete temp image. */ - if (tgpf->ima) { - BKE_id_free(bmain, tgpf->ima); - } - /* finally, free memory used by temp data */ MEM_freeN(tgpf); } @@ -1536,7 +1814,11 @@ static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE tgpf = op->customdata; /* Enable custom drawing handlers to show help lines */ - if (tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) { + const bool do_extend = (tgpf->fill_extend_fac > 0.0f); + const bool help_lines = ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) || + ((tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES) && (do_extend))); + + if (help_lines) { tgpf->draw_handle_3d = ED_region_draw_cb_activate( tgpf->region->type, gpencil_fill_draw_3d, tgpf, REGION_DRAW_POST_VIEW); } @@ -1554,17 +1836,210 @@ static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE return OPERATOR_RUNNING_MODAL; } +/* Helper: Calc the maximum bounding box size of strokes to get the zoom level of the viewport. + * For each stroke, the 2D projected bounding box is calculated and using this data, the total + * object bounding box (all strokes) is calculated. */ +static void gpencil_zoom_level_set(tGPDfill *tgpf) +{ + Brush *brush = tgpf->brush; + if (brush->gpencil_settings->flag & GP_BRUSH_FILL_FIT_DISABLE) { + tgpf->zoom = 1.0f; + return; + } + + Object *ob = tgpf->ob; + bGPdata *gpd = tgpf->gpd; + BrushGpencilSettings *brush_settings = tgpf->brush->gpencil_settings; + bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd); + BLI_assert(gpl_active != NULL); + + const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active); + BLI_assert(gpl_active_index >= 0); + + /* Init maximum boundbox size. */ + rctf rect_max; + const float winx_half = tgpf->region->winx / 2.0f; + const float winy_half = tgpf->region->winy / 2.0f; + BLI_rctf_init(&rect_max, + 0.0f - winx_half, + tgpf->region->winx + winx_half, + 0.0f - winy_half, + tgpf->region->winy + winy_half); + + float objectbox_min[2], objectbox_max[2]; + INIT_MINMAX2(objectbox_min, objectbox_max); + rctf rect_bound; + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + float diff_mat[4][4]; + /* calculate parent matrix */ + BKE_gpencil_layer_transform_matrix_get(tgpf->depsgraph, ob, gpl, diff_mat); + + /* Decide if the strokes of layers are included or not depending on the layer mode. + * Cannot skip the layer because it can use boundary strokes and must be used. */ + const int gpl_index = BLI_findindex(&gpd->layers, gpl); + bool skip = skip_layer_check(brush_settings->fill_layer_mode, gpl_active_index, gpl_index); + + /* Get frame to check. */ + bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, GP_GETFRAME_USE_PREV); + if (gpf == NULL) { + continue; + } + + /* Read all strokes. */ + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* check if stroke can be drawn */ + if ((gps->points == NULL) || (gps->totpoints < 2)) { + continue; + } + /* check if the color is visible */ + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); + if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE)) { + continue; + } + + /* If the layer must be skipped, but the stroke is not boundary, skip stroke. */ + if ((skip) && ((gps->flag & GP_STROKE_NOFILL) == 0)) { + continue; + } + + float boundbox_min[2]; + float boundbox_max[2]; + ED_gpencil_projected_2d_bound_box(&tgpf->gsc, gps, diff_mat, boundbox_min, boundbox_max); + minmax_v2v2_v2(objectbox_min, objectbox_max, boundbox_min); + minmax_v2v2_v2(objectbox_min, objectbox_max, boundbox_max); + } + } + /* Clamp max bound box. */ + BLI_rctf_init( + &rect_bound, objectbox_min[0], objectbox_max[0], objectbox_min[1], objectbox_max[1]); + float r_xy[2]; + BLI_rctf_clamp(&rect_bound, &rect_max, r_xy); + + /* Calculate total width used. */ + float width = tgpf->region->winx; + if (rect_bound.xmin < 0.0f) { + width -= rect_bound.xmin; + } + if (rect_bound.xmax > tgpf->region->winx) { + width += rect_bound.xmax - tgpf->region->winx; + } + /* Calculate total height used. */ + float height = tgpf->region->winy; + if (rect_bound.ymin < 0.0f) { + height -= rect_bound.ymin; + } + if (rect_bound.ymax > tgpf->region->winy) { + height += rect_bound.ymax - tgpf->region->winy; + } + + width = ceilf(width); + height = ceilf(height); + + float zoomx = (width > tgpf->region->winx) ? width / (float)tgpf->region->winx : 1.0f; + float zoomy = (height > tgpf->region->winy) ? height / (float)tgpf->region->winy : 1.0f; + if ((zoomx != 1.0f) || (zoomy != 1.0f)) { + tgpf->zoom = min_ff(max_ff(zoomx, zoomy) * 1.5f, 5.0f); + } +} + +static bool gpencil_do_frame_fill(tGPDfill *tgpf, const bool is_inverted) +{ + wmWindow *win = CTX_wm_window(tgpf->C); + + /* render screen to temp image */ + int totpoints = 1; + if (gpencil_render_offscreen(tgpf)) { + + /* Set red borders to create a external limit. */ + gpencil_set_borders(tgpf, true); + + /* apply boundary fill */ + gpencil_boundaryfill_area(tgpf); + + /* Invert direction if press Ctrl. */ + if (is_inverted) { + gpencil_invert_image(tgpf); + } + + /* Clean borders to avoid infinite loops. */ + gpencil_set_borders(tgpf, false); + WM_cursor_time(win, 50); + int totpoints_prv = 0; + int loop_limit = 0; + while (totpoints > 0) { + /* analyze outline */ + gpencil_get_outline_points(tgpf, (totpoints == 1) ? true : false); + + /* create array of points from stack */ + totpoints = gpencil_points_from_stack(tgpf); + + /* create z-depth array for reproject */ + gpencil_get_depth_array(tgpf); + + /* create stroke and reproject */ + gpencil_stroke_from_buffer(tgpf); + + if (is_inverted) { + gpencil_erase_processed_area(tgpf); + } + else { + /* Exit of the loop. */ + totpoints = 0; + } + + /* free temp stack data */ + if (tgpf->stack) { + BLI_stack_free(tgpf->stack); + } + WM_cursor_time(win, 100); + + /* Free memory. */ + MEM_SAFE_FREE(tgpf->sbuffer); + MEM_SAFE_FREE(tgpf->depth_arr); + + /* Limit very small areas. */ + if (totpoints < 3) { + break; + } + /* Limit infinite loops is some corner cases. */ + if (totpoints_prv == totpoints) { + loop_limit++; + if (loop_limit > 3) { + break; + } + } + totpoints_prv = totpoints; + } + + /* Delete temp image. */ + if ((tgpf->ima) && (!FILL_DEBUG)) { + BKE_id_free(tgpf->bmain, tgpf->ima); + } + + return true; + } + + return false; +} + /* events handling during interactive part of operator */ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) { tGPDfill *tgpf = op->customdata; - Scene *scene = tgpf->scene; Brush *brush = tgpf->brush; BrushGpencilSettings *brush_settings = brush->gpencil_settings; + 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); - - int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through */ + 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) || + ((tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES) && (do_extend))); + int estate = OPERATOR_RUNNING_MODAL; switch (event->type) { case EVT_ESCKEY: @@ -1572,82 +2047,104 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) estate = OPERATOR_CANCELLED; break; case LEFTMOUSE: - tgpf->on_back = RNA_boolean_get(op->ptr, "on_back"); /* first time the event is not enabled to show help lines. */ - if ((tgpf->oldkey != -1) || ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) == 0)) { + if ((tgpf->oldkey != -1) || (!help_lines)) { ARegion *region = BKE_area_find_region_xy( CTX_wm_area(C), RGN_TYPE_ANY, event->x, event->y); if (region) { bool in_bounds = false; - /* Perform bounds check */ in_bounds = BLI_rcti_isect_pt(®ion->winrct, event->x, event->y); if ((in_bounds) && (region->regiontype == RGN_TYPE_WINDOW)) { - tgpf->center[0] = event->mval[0]; - tgpf->center[1] = event->mval[1]; - - /* Set active frame as current for filling. */ - tgpf->active_cfra = CFRA; + tgpf->mouse[0] = event->mval[0]; + tgpf->mouse[1] = event->mval[1]; + tgpf->is_render = true; + /* Define Zoom level. */ + gpencil_zoom_level_set(tgpf); + + /* Create Temp stroke. */ + tgpf->gps_mouse = BKE_gpencil_stroke_new(0, 1, 10.0f); + tGPspoint point2D; + bGPDspoint *pt = &tgpf->gps_mouse->points[0]; + copy_v2fl_v2i(&point2D.x, tgpf->mouse); + gpencil_stroke_convertcoords_tpoint( + tgpf->scene, tgpf->region, tgpf->ob, &point2D, NULL, &pt->x); + + /* If not multiframe and there is no frame in CFRA for the active layer, create + * a new frame before to make the hash function can find something. */ + if (!is_multiedit) { + tgpf->gpf = BKE_gpencil_layer_frame_get( + tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW); + tgpf->gpf->flag |= GP_FRAME_SELECT; + } - /* render screen to temp image */ - int totpoints = 1; - if (gpencil_render_offscreen(tgpf)) { + /* Hash of selected frames.*/ + GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64); + BKE_gpencil_frame_selected_hash(tgpf->gpd, frame_list); - /* Set red borders to create a external limit. */ - gpencil_set_borders(tgpf, true); + /* Loop all frames. */ + wmWindow *win = CTX_wm_window(C); - /* apply boundary fill */ - gpencil_boundaryfill_area(tgpf); + GHashIterator gh_iter; + int total = BLI_ghash_len(frame_list); + int i = 1; + GHASH_ITER (gh_iter, frame_list) { + /* Set active frame as current for filling. */ + tgpf->active_cfra = POINTER_AS_INT(BLI_ghashIterator_getKey(&gh_iter)); + int step = ((float)i / (float)total) * 100.0f; + WM_cursor_time(win, step); - /* Invert direction if press Ctrl. */ - if (is_inverted) { - gpencil_invert_image(tgpf); + if (do_extend) { + gpencil_update_extend(tgpf); } - /* Clean borders to avoid infinite loops. */ - gpencil_set_borders(tgpf, false); - - while (totpoints > 0) { - /* analyze outline */ - gpencil_get_outline_points(tgpf, (totpoints == 1) ? true : false); - - /* create array of points from stack */ - totpoints = gpencil_points_from_stack(tgpf); - - /* create z-depth array for reproject */ - gpencil_get_depth_array(tgpf); - - /* create stroke and reproject */ - gpencil_stroke_from_buffer(tgpf); - - if (is_inverted) { - gpencil_erase_processed_area(tgpf); - } - else { - /* Exit of the loop. */ - totpoints = 0; - } - - /* free temp stack data */ - if (tgpf->stack) { - BLI_stack_free(tgpf->stack); + /* Repeat loop until get something. */ + tgpf->done = false; + int loop_limit = 0; + while ((!tgpf->done) && (loop_limit < 2)) { + WM_cursor_time(win, loop_limit + 1); + /* Render screen to temp image and do fill. */ + gpencil_do_frame_fill(tgpf, is_inverted); + + /* restore size */ + tgpf->region->winx = (short)tgpf->bwinx; + tgpf->region->winy = (short)tgpf->bwiny; + tgpf->region->winrct = tgpf->brect; + if (!tgpf->done) { + /* If the zoom was not set before, avoid a loop. */ + if (tgpf->zoom == 1.0f) { + loop_limit++; + } + else { + tgpf->zoom = 1.0f; + tgpf->fill_factor = max_ff( + GPENCIL_MIN_FILL_FAC, + min_ff(brush->gpencil_settings->fill_factor, GPENCIL_MAX_FILL_FAC)); + } } + loop_limit++; + } - /* Free memory. */ - MEM_SAFE_FREE(tgpf->sbuffer); - MEM_SAFE_FREE(tgpf->depth_arr); + if (do_extend) { + gpencil_delete_temp_stroke_extension(tgpf, true); } + + i++; } + WM_cursor_modal_restore(win); + /* Free hash table. */ + BLI_ghash_free(frame_list, NULL, NULL); - /* restore size */ - tgpf->region->winx = (short)tgpf->bwinx; - tgpf->region->winy = (short)tgpf->bwiny; - tgpf->region->winrct = tgpf->brect; + /* Free temp stroke. */ + BKE_gpencil_free_stroke(tgpf->gps_mouse); /* push undo data */ gpencil_undo_push(tgpf->gpd); + /* Save extend value for next operation. */ + brush_settings->fill_extend_fac = tgpf->fill_extend_fac; + estate = OPERATOR_FINISHED; } else { @@ -1658,8 +2155,29 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) estate = OPERATOR_CANCELLED; } } + else if (do_extend) { + gpencil_update_extend(tgpf); + } tgpf->oldkey = event->type; break; + case EVT_PAGEUPKEY: + case WHEELUPMOUSE: + if (tgpf->oldkey == 1) { + tgpf->fill_extend_fac -= (event->shift) ? 0.01f : 0.1f; + CLAMP_MIN(tgpf->fill_extend_fac, 0.0f); + gpencil_update_extend(tgpf); + } + break; + case EVT_PAGEDOWNKEY: + case WHEELDOWNMOUSE: + if (tgpf->oldkey == 1) { + tgpf->fill_extend_fac += (event->shift) ? 0.01f : 0.1f; + CLAMP_MAX(tgpf->fill_extend_fac, 100.0f); + gpencil_update_extend(tgpf); + } + break; + default: + break; } /* process last operations before exiting */ switch (estate) { @@ -1672,7 +2190,7 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) gpencil_fill_exit(C, op); break; - case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH: + default: break; } diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 4a908eff92e..5fea46626d5 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -667,7 +667,8 @@ struct GP_EditableStrokes_Iter { bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ - BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ + BKE_gpencil_layer_transform_matrix_get( \ + depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ /* loop over strokes */ \ bGPDstroke *gpsn_; \ @@ -678,7 +679,7 @@ struct GP_EditableStrokes_Iter { continue; \ } \ /* check if the color is editable */ \ - if (ED_gpencil_stroke_color_use(obact_, gpl, gps) == false) { \ + if (ED_gpencil_stroke_material_editable(obact_, gpl, gps) == false) { \ continue; \ } \ /* ... Do Stuff With Strokes ... */ @@ -718,7 +719,8 @@ struct GP_EditableStrokes_Iter { bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ - BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ + BKE_gpencil_layer_transform_matrix_get( \ + depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ /* loop over strokes */ \ bGPDstroke *gpsn_; \ @@ -767,8 +769,10 @@ struct GP_EditableStrokes_Iter { bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ - BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ - invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ + BKE_gpencil_layer_transform_matrix_get( \ + depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ + /* Undo layer transform. */ \ + mul_m4_m4m4(gpstroke_iter.diff_mat, gpstroke_iter.diff_mat, gpl->layer_invmat); \ /* loop over strokes */ \ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf_->strokes) { \ /* skip strokes that are invalid for current view */ \ @@ -776,7 +780,7 @@ struct GP_EditableStrokes_Iter { continue; \ } \ /* check if the color is editable */ \ - if (ED_gpencil_stroke_color_use(obact_, gpl, gps) == false) { \ + if (ED_gpencil_stroke_material_editable(obact_, gpl, gps) == false) { \ continue; \ } \ /* ... Do Stuff With Strokes ... */ diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index c666fcb67b7..ecd243ed595 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -48,31 +48,22 @@ #include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" #include "BKE_report.h" #include "UI_interface.h" -#include "UI_resources.h" #include "WM_api.h" #include "WM_types.h" #include "RNA_access.h" #include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "UI_view2d.h" #include "ED_gpencil.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_space_api.h" -#include "ED_view3d.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "gpencil_intern.h" @@ -229,7 +220,7 @@ static bool gpencil_interpolate_check_todo(bContext *C, bGPdata *gpd) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps_from) == false) { continue; } @@ -283,8 +274,8 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer"); tgpil->gpl = gpl; - tgpil->prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe); - tgpil->nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next); + tgpil->prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe, true); + tgpil->nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next, true); BLI_addtail(&tgpi->ilayers, tgpil); @@ -315,7 +306,7 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, tgpil->gpl, gps_from) == false) { + if (ED_gpencil_stroke_material_editable(ob, tgpil->gpl, gps_from) == false) { valid = false; } @@ -734,7 +725,7 @@ void GPENCIL_OT_interpolate(wmOperatorType *ot) ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; /* properties */ - RNA_def_float_percentage( + RNA_def_float_factor( ot->srna, "shift", 0.0f, @@ -1008,8 +999,8 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) } /* store extremes */ - prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe); - nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next); + prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe, true); + nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next, true); /* Loop over intermediary frames and create the interpolation */ for (cframe = prevFrame->framenum + step; cframe < nextFrame->framenum; cframe += step) { @@ -1048,7 +1039,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps_from) == false) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c index 272dff56291..435bff34998 100644 --- a/source/blender/editors/gpencil/gpencil_merge.c +++ b/source/blender/editors/gpencil/gpencil_merge.c @@ -48,12 +48,9 @@ #include "RNA_define.h" #include "ED_gpencil.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_view3d.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "gpencil_intern.h" diff --git a/source/blender/editors/gpencil/gpencil_mesh.c b/source/blender/editors/gpencil/gpencil_mesh.c index 53beaeaa6a0..ffe676f0520 100644 --- a/source/blender/editors/gpencil/gpencil_mesh.c +++ b/source/blender/editors/gpencil/gpencil_mesh.c @@ -36,8 +36,6 @@ #include "BKE_anim_data.h" #include "BKE_context.h" #include "BKE_duplilist.h" -#include "BKE_global.h" -#include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" #include "BKE_layer.h" #include "BKE_main.h" diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 0a29b83bc4f..1a6cb5670c4 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -27,9 +27,7 @@ #include "BLI_sys_types.h" -#include "BKE_brush.h" #include "BKE_context.h" -#include "BKE_gpencil.h" #include "BKE_paint.h" #include "DNA_brush_types.h" @@ -45,9 +43,6 @@ #include "RNA_access.h" #include "ED_gpencil.h" -#include "ED_object.h" -#include "ED_select_utils.h" -#include "ED_transform.h" #include "gpencil_intern.h" diff --git a/source/blender/editors/gpencil/gpencil_ops_versioning.c b/source/blender/editors/gpencil/gpencil_ops_versioning.c index 815bbbaa254..45842c28dff 100644 --- a/source/blender/editors/gpencil/gpencil_ops_versioning.c +++ b/source/blender/editors/gpencil/gpencil_ops_versioning.c @@ -34,16 +34,12 @@ #include "DNA_gpencil_types.h" #include "DNA_material_types.h" -#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BKE_brush.h" #include "BKE_context.h" -#include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_main.h" -#include "BKE_material.h" #include "BKE_object.h" #include "WM_api.h" @@ -53,7 +49,6 @@ #include "RNA_define.h" #include "ED_gpencil.h" -#include "ED_object.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index ed56f004ca4..b833125cf34 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -426,7 +426,7 @@ static void gpencil_reproject_toplane(tGPsdata *p, bGPDstroke *gps) /* get drawing origin */ gpencil_get_3d_reference(p, origin); - ED_gpencil_project_stroke_to_plane(p->scene, obact, rv3d, gps, origin, p->lock_axis - 1); + ED_gpencil_project_stroke_to_plane(p->scene, obact, rv3d, p->gpl, gps, origin, p->lock_axis - 1); } /* convert screen-coordinates to buffer-coordinates */ @@ -887,11 +887,13 @@ static short gpencil_stroke_addpoint(tGPsdata *p, gpencil_get_3d_reference(p, origin); /* reproject current */ ED_gpencil_tpoint_to_point(p->region, origin, pt, &spt); - ED_gpencil_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt); + ED_gpencil_project_point_to_plane( + p->scene, obact, p->gpl, rv3d, origin, p->lock_axis - 1, &spt); /* reproject previous */ ED_gpencil_tpoint_to_point(p->region, origin, ptb, &spt2); - ED_gpencil_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt2); + ED_gpencil_project_point_to_plane( + p->scene, obact, p->gpl, rv3d, origin, p->lock_axis - 1, &spt2); p->totpixlen += len_v3v3(&spt.x, &spt2.x); pt->uv_fac = p->totpixlen; } @@ -1304,6 +1306,12 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) /* Calc geometry data. */ BKE_gpencil_stroke_geometry_update(gpd, gps); + /* In Multiframe mode, duplicate the stroke in other frames. */ + if (GPENCIL_MULTIEDIT_SESSIONS_ON(p->gpd)) { + const bool tail = (ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK); + BKE_gpencil_stroke_copy_to_keyframes(gpd, gpl, p->gpf, gps, tail); + } + gpencil_stroke_added_enable(p); } @@ -1321,10 +1329,8 @@ static float view3d_point_depth(const RegionView3D *rv3d, const float co[3]) } /* only erase stroke points that are visible */ -static bool gpencil_stroke_eraser_is_occluded(tGPsdata *p, - const bGPDspoint *pt, - const int x, - const int y) +static bool gpencil_stroke_eraser_is_occluded( + tGPsdata *p, bGPDlayer *gpl, const bGPDspoint *pt, const int x, const int y) { Object *obact = (Object *)p->ownerPtr.data; Brush *brush = p->brush; @@ -1341,7 +1347,6 @@ static bool gpencil_stroke_eraser_is_occluded(tGPsdata *p, if ((gp_settings != NULL) && (p->area->spacetype == SPACE_VIEW3D) && (gp_settings->flag & GP_BRUSH_OCCLUDE_ERASER)) { RegionView3D *rv3d = p->region->regiondata; - bGPDlayer *gpl = p->gpl; const int mval_i[2] = {x, y}; float mval_3d[3]; @@ -1349,7 +1354,7 @@ static bool gpencil_stroke_eraser_is_occluded(tGPsdata *p, float diff_mat[4][4]; /* calculate difference matrix if parent object */ - BKE_gpencil_parent_matrix_get(p->depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(p->depsgraph, obact, gpl, diff_mat); if (ED_view3d_autodist_simple(p->region, mval_i, mval_3d, 0, NULL)) { const float depth_mval = view3d_point_depth(rv3d, mval_3d); @@ -1452,6 +1457,7 @@ static void gpencil_stroke_soft_refine(bGPDstroke *gps) /* eraser tool - evaluation per stroke */ static void gpencil_stroke_eraser_dostroke(tGPsdata *p, + bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, const float mval[2], @@ -1577,9 +1583,9 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p, * - this assumes that linewidth is irrelevant */ if (gpencil_stroke_inside_circle(mval, radius, pc0[0], pc0[1], pc2[0], pc2[1])) { - if ((gpencil_stroke_eraser_is_occluded(p, pt0, pc0[0], pc0[1]) == false) || - (gpencil_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) || - (gpencil_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false)) { + if ((gpencil_stroke_eraser_is_occluded(p, gpl, pt0, pc0[0], pc0[1]) == false) || + (gpencil_stroke_eraser_is_occluded(p, gpl, pt1, pc1[0], pc1[1]) == false) || + (gpencil_stroke_eraser_is_occluded(p, gpl, pt2, pc2[0], pc2[1]) == false)) { /* Point is affected: */ /* Adjust thickness * - Influence of eraser falls off with distance from the middle of the eraser @@ -1681,6 +1687,8 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p, /* erase strokes which fall under the eraser strokes */ static void gpencil_stroke_doeraser(tGPsdata *p) { + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(p->gpd); + rcti rect; Brush *brush = p->brush; Brush *eraser = p->eraser; @@ -1721,40 +1729,53 @@ static void gpencil_stroke_doeraser(tGPsdata *p) * on multiple layers... */ LISTBASE_FOREACH (bGPDlayer *, gpl, &p->gpd->layers) { - bGPDframe *gpf = gpl->actframe; - /* only affect layer if it's editable (and visible) */ if (BKE_gpencil_layer_is_editable(gpl) == false) { continue; } - if (gpf == NULL) { + + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; + if (init_gpf == NULL) { continue; } - /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(p->depsgraph, p->ob, gpl, p->diff_mat); - /* loop over strokes, checking segments for intersections */ - LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { - /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(p->ob, gpl, gps) == false) { - continue; - } + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; + } + /* calculate difference matrix */ + BKE_gpencil_layer_transform_matrix_get(p->depsgraph, p->ob, gpl, p->diff_mat); + + /* loop over strokes, checking segments for intersections */ + LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { + /* check if the color is editable */ + if (ED_gpencil_stroke_material_editable(p->ob, gpl, gps) == false) { + continue; + } - /* Check if the stroke collide with mouse. */ - if (!ED_gpencil_stroke_check_collision(&p->gsc, gps, p->mval, calc_radius, p->diff_mat)) { - continue; - } + /* Check if the stroke collide with mouse. */ + if (!ED_gpencil_stroke_check_collision( + &p->gsc, gps, p->mval, calc_radius, p->diff_mat)) { + continue; + } - /* Not all strokes in the datablock may be valid in the current editor/context - * (e.g. 2D space strokes in the 3D view, if the same datablock is shared) - */ - if (ED_gpencil_stroke_can_use_direct(p->area, gps)) { - gpencil_stroke_eraser_dostroke(p, gpf, gps, p->mval, calc_radius, &rect); + /* Not all strokes in the datablock may be valid in the current editor/context + * (e.g. 2D space strokes in the 3D view, if the same datablock is shared) + */ + if (ED_gpencil_stroke_can_use_direct(p->area, gps)) { + gpencil_stroke_eraser_dostroke(p, gpl, gpf, gps, p->mval, calc_radius, &rect); + } + } + + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; + } } } } } - /* ******************************************* */ /* Sketching Operator */ @@ -2103,6 +2124,11 @@ static void gpencil_paint_initstroke(tGPsdata *p, copy_v3_v3(p->gpl->color, p->custom_color); } } + + /* Recalculate layer transform matrix to avoid problems if props are animated. */ + loc_eul_size_to_mat4(p->gpl->layer_mat, p->gpl->location, p->gpl->rotation, p->gpl->scale); + invert_m4_m4(p->gpl->layer_invmat, p->gpl->layer_mat); + if ((paintmode != GP_PAINTMODE_ERASER) && (p->gpl->flag & GP_LAYER_LOCKED)) { p->status = GP_STATUS_ERROR; if (G.debug & G_DEBUG) { diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 53e0043df37..bcdde49b93d 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -317,6 +317,10 @@ static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) } tgpi->gpl = gpl; + /* Recalculate layer transform matrix to avoid problems if props are animated. */ + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + /* create a new temporary frame */ tgpi->gpf = MEM_callocN(sizeof(bGPDframe), "Temp bGPDframe"); tgpi->gpf->framenum = tgpi->cframe = cfra; @@ -1004,12 +1008,12 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) /* reproject current */ ED_gpencil_tpoint_to_point(tgpi->region, origin, tpt, &spt); ED_gpencil_project_point_to_plane( - tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt); + tgpi->scene, tgpi->ob, tgpi->gpl, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt); /* reproject previous */ ED_gpencil_tpoint_to_point(tgpi->region, origin, tptb, &spt2); ED_gpencil_project_point_to_plane( - tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2); + tgpi->scene, tgpi->ob, tgpi->gpl, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2); tgpi->totpixlen += len_v3v3(&spt.x, &spt2.x); tpt->uv_fac = tgpi->totpixlen; } @@ -1068,7 +1072,7 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) float origin[3]; ED_gpencil_drawing_reference_get(tgpi->scene, tgpi->ob, ts->gpencil_v3d_align, origin); ED_gpencil_project_stroke_to_plane( - tgpi->scene, tgpi->ob, tgpi->rv3d, gps, origin, ts->gp_sculpt.lock_axis - 1); + tgpi->scene, tgpi->ob, tgpi->rv3d, tgpi->gpl, gps, origin, ts->gp_sculpt.lock_axis - 1); } /* if parented change position relative to parent object */ @@ -1373,6 +1377,12 @@ static void gpencil_primitive_interaction_end(bContext *C, BKE_gpencil_stroke_geometry_update(tgpi->gpd, gps); } + /* In Multiframe mode, duplicate the stroke in other frames. */ + if (GPENCIL_MULTIEDIT_SESSIONS_ON(tgpi->gpd)) { + const bool tail = (ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK); + BKE_gpencil_stroke_copy_to_keyframes(tgpi->gpd, tgpi->gpl, gpf, gps, tail); + } + DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE); DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index bb9dd8cac5d..0d3ab9011d6 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -1441,11 +1441,6 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso, bool changed = false; float rot_eval = 0.0f; - /* Check if the stroke collide with brush. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) { - return false; - } - if (gps->totpoints == 1) { bGPDspoint pt_temp; pt = &gps->points[0]; @@ -1577,6 +1572,13 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C, Object *ob = gso->object; bGPdata *gpd = ob->data; char tool = gso->brush->gpencil_sculpt_tool; + GP_SpaceConversion *gsc = &gso->gsc; + Brush *brush = gso->brush; + const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure : + gso->brush->size; + /* Calc bound box matrix. */ + float bound_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(gso->depsgraph, gso->object, gpl, bound_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { /* skip strokes that are invalid for current view */ @@ -1584,7 +1586,12 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C, continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { + continue; + } + + /* Check if the stroke collide with brush. */ + if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) { continue; } @@ -1742,7 +1749,8 @@ static bool gpencil_sculpt_brush_apply_standard(bContext *C, tGP_BrushEditData * /* calculate difference matrix */ float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_invmat); /* Active Frame or MultiFrame? */ if (gso->is_multiframe) { diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 281ab8c5adc..a00d21bf88a 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -2473,7 +2473,7 @@ static void gpencil_selected_hue_table(bContext *C, if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } if ((gps->flag & GP_STROKE_SELECT) == 0) { diff --git a/source/blender/editors/gpencil/gpencil_trace_ops.c b/source/blender/editors/gpencil/gpencil_trace_ops.c index 0be9d74278e..0f344909692 100644 --- a/source/blender/editors/gpencil/gpencil_trace_ops.c +++ b/source/blender/editors/gpencil/gpencil_trace_ops.c @@ -23,7 +23,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" #include "BLI_math.h" #include "BLT_translation.h" @@ -31,34 +30,26 @@ #include "DNA_gpencil_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" -#include "DNA_space_types.h" #include "BKE_context.h" -#include "BKE_duplilist.h" #include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_image.h" #include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" -#include "BKE_material.h" #include "BKE_object.h" #include "BKE_report.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" -#include "UI_interface.h" -#include "UI_resources.h" - #include "WM_api.h" #include "WM_types.h" #include "RNA_access.h" #include "RNA_define.h" -#include "RNA_enum_types.h" -#include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "ED_gpencil.h" @@ -66,7 +57,6 @@ #include "gpencil_intern.h" #include "gpencil_trace.h" -#include "potracelib.h" typedef struct TraceJob { /* from wmJob */ @@ -87,6 +77,7 @@ typedef struct TraceJob { bGPDlayer *gpl; bool was_ob_created; + bool use_current_frame; int32_t frame_target; float threshold; @@ -228,15 +219,17 @@ static void trace_start_job(void *customdata, short *stop, short *do_update, flo trace_job->do_update = do_update; trace_job->progress = progress; trace_job->was_canceled = false; + const int init_frame = max_ii((trace_job->use_current_frame) ? trace_job->frame_target : 0, 0); G.is_break = false; /* Single Image. */ - if ((trace_job->image->source == IMA_SRC_FILE) || (trace_job->mode == GPENCIL_TRACE_MODE_SINGLE)) { void *lock; - ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job->image, NULL, &lock); + ImageUser *iuser = trace_job->ob_active->iuser; + iuser->framenr = init_frame; + ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job->image, iuser, &lock); if (ibuf) { /* Create frame. */ bGPDframe *gpf = BKE_gpencil_layer_frame_get( @@ -249,7 +242,7 @@ static void trace_start_job(void *customdata, short *stop, short *do_update, flo /* Image sequence. */ else if (trace_job->image->type == IMA_TYPE_IMAGE) { ImageUser *iuser = trace_job->ob_active->iuser; - for (int i = 0; i < iuser->frames; i++) { + for (int i = init_frame; i < iuser->frames; i++) { if (G.is_break) { trace_job->was_canceled = true; break; @@ -320,6 +313,7 @@ static int gpencil_trace_image_exec(bContext *C, wmOperator *op) job->ob_active = job->base_active->object; job->image = (Image *)job->ob_active->data; job->frame_target = CFRA; + job->use_current_frame = RNA_boolean_get(op->ptr, "use_current_frame"); /* Create a new grease pencil object or reuse selected. */ eGP_TargetObjectMode target = RNA_enum_get(op->ptr, "target"); @@ -493,4 +487,9 @@ void GPENCIL_OT_trace_image(wmOperatorType *ot) GPENCIL_TRACE_MODE_SINGLE, "Mode", "Determines if trace simple image or full sequence"); + RNA_def_boolean(ot->srna, + "use_current_frame", + true, + "Start At Current Frame", + "Trace Image starting in current image frame"); } diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c index c2504ce329e..4e172104ce7 100644 --- a/source/blender/editors/gpencil/gpencil_undo.c +++ b/source/blender/editors/gpencil/gpencil_undo.c @@ -36,6 +36,7 @@ #include "BKE_blender_undo.h" #include "BKE_context.h" #include "BKE_gpencil.h" +#include "BKE_undo_system.h" #include "ED_gpencil.h" @@ -61,28 +62,22 @@ int ED_gpencil_session_active(void) return (BLI_listbase_is_empty(&undo_nodes) == false); } -int ED_undo_gpencil_step(bContext *C, int step, const char *name) +int ED_undo_gpencil_step(bContext *C, const eUndoStepDir step) { bGPdata **gpd_ptr = NULL, *new_gpd = NULL; gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); - if (step == 1) { /* undo */ - // printf("\t\tGP - undo step\n"); + if (step == STEP_UNDO) { if (cur_node->prev) { - if (!name || STREQ(cur_node->name, name)) { - cur_node = cur_node->prev; - new_gpd = cur_node->gpd; - } + cur_node = cur_node->prev; + new_gpd = cur_node->gpd; } } - else if (step == -1) { - // printf("\t\tGP - redo step\n"); + else if (step == STEP_REDO) { if (cur_node->next) { - if (!name || STREQ(cur_node->name, name)) { - cur_node = cur_node->next; - new_gpd = cur_node->gpd; - } + cur_node = cur_node->next; + new_gpd = cur_node->gpd; } } @@ -99,7 +94,7 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name) LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { /* make a copy of source layer and its data */ - gpld = BKE_gpencil_layer_duplicate(gpl); + gpld = BKE_gpencil_layer_duplicate(gpl, true, true); BLI_addtail(&gpd->layers, gpld); } } diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 7c796f7b7a1..9b12772bc9b 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -579,7 +579,7 @@ bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps) } /* Check whether given stroke can be edited for the current color */ -bool ED_gpencil_stroke_color_use(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps) +bool ED_gpencil_stroke_material_editable(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps) { /* check if the color is editable */ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); @@ -674,7 +674,7 @@ void gpencil_apply_parent(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, b float inverse_diff_mat[4][4]; float fpt[3]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); for (i = 0; i < gps->totpoints; i++) { @@ -697,10 +697,11 @@ void gpencil_apply_parent_point(Depsgraph *depsgraph, float inverse_diff_mat[4][4]; float fpt[3]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x); + copy_v3_v3(&pt->x, fpt); } @@ -997,6 +998,12 @@ void ED_gpencil_drawing_reference_get(const Scene *scene, else { /* use object location */ copy_v3_v3(r_vec, ob->obmat[3]); + /* Apply layer offset. */ + bGPdata *gpd = ob->data; + bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); + if (gpl != NULL) { + add_v3_v3(r_vec, gpl->layer_mat[3]); + } } } } @@ -1021,7 +1028,7 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke * /* init space conversion stuff */ gpencil_point_conversion_init(C, &gsc); - BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); /* Adjust each point */ @@ -1046,6 +1053,7 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke * void ED_gpencil_project_stroke_to_plane(const Scene *scene, const Object *ob, const RegionView3D *rv3d, + bGPDlayer *gpl, bGPDstroke *gps, const float origin[3], const int axis) @@ -1058,6 +1066,10 @@ void ED_gpencil_project_stroke_to_plane(const Scene *scene, float ray[3]; float rpoint[3]; + /* Recalculate layer transform matrix. */ + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + /* normal vector for a plane locked to axis */ zero_v3(plane_normal); if (axis < 0) { @@ -1074,24 +1086,27 @@ void ED_gpencil_project_stroke_to_plane(const Scene *scene, copy_m4_m4(mat, ob->obmat); /* move origin to cursor */ + if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + if (gpl != NULL) { + add_v3_v3(mat[3], gpl->location); + } + } if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { copy_v3_v3(mat[3], cursor->location); } mul_mat3_m4_v3(mat, plane_normal); } + + if ((gpl != NULL) && (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR)) { + mul_mat3_m4_v3(gpl->layer_mat, plane_normal); + } } else { const float scale[3] = {1.0f, 1.0f, 1.0f}; plane_normal[2] = 1.0f; float mat[4][4]; loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale); - - /* move origin to object */ - if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { - copy_v3_v3(mat[3], ob->obmat[3]); - } - mul_mat3_m4_v3(mat, plane_normal); } @@ -1127,8 +1142,12 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, ARegion *region = gsc->region; RegionView3D *rv3d = region->regiondata; + /* Recalculate layer transform matrix. */ + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + float diff_mat[4][4], inverse_diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, gsc->ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, gsc->ob, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); float origin[3]; @@ -1194,7 +1213,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, } } - ED_gpencil_project_point_to_plane(gsc->scene, gsc->ob, rv3d, origin, axis, &pt2); + ED_gpencil_project_point_to_plane(gsc->scene, gsc->ob, gpl, rv3d, origin, axis, &pt2); copy_v3_v3(&pt->x, &pt2.x); @@ -1250,6 +1269,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, */ void ED_gpencil_project_point_to_plane(const Scene *scene, const Object *ob, + bGPDlayer *gpl, const RegionView3D *rv3d, const float origin[3], const int axis, @@ -1277,6 +1297,11 @@ void ED_gpencil_project_point_to_plane(const Scene *scene, if (ob && (ob->type == OB_GPENCIL)) { float mat[4][4]; copy_m4_m4(mat, ob->obmat); + if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + if (gpl != NULL) { + add_v3_v3(mat[3], gpl->location); + } + } /* move origin to cursor */ if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { @@ -1284,6 +1309,10 @@ void ED_gpencil_project_point_to_plane(const Scene *scene, } mul_mat3_m4_v3(mat, plane_normal); + /* Apply layer rotation (local transform). */ + if ((gpl != NULL) && (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR)) { + mul_mat3_m4_v3(gpl->layer_mat, plane_normal); + } } } else { @@ -1449,7 +1478,7 @@ void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata /* only redo if any change */ if (!equals_m4m4(gpl->inverse, cur_mat)) { /* first apply current transformation to all strokes */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); /* undo local object */ sub_v3_v3(diff_mat[3], gpl_loc); @@ -2144,7 +2173,7 @@ void ED_gpencil_update_color_uv(Main *bmain, Material *mat) LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { /* check if it is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } gps_ma = BKE_gpencil_material(ob, gps->mat_nr + 1); @@ -3003,12 +3032,12 @@ void ED_gpencil_sbuffer_vertex_color_set(Depsgraph *depsgraph, } } -/* Helper to get the bigger 2D bound box points. */ -static void gpencil_projected_2d_bound_box(GP_SpaceConversion *gsc, - bGPDstroke *gps, - const float diff_mat[4][4], - float r_min[2], - float r_max[2]) +/* Get the bigger 2D bound box points. */ +void ED_gpencil_projected_2d_bound_box(GP_SpaceConversion *gsc, + bGPDstroke *gps, + const float diff_mat[4][4], + float r_min[2], + float r_max[2]) { float bounds[8][2]; BoundBox bb; @@ -3053,7 +3082,7 @@ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc, BKE_gpencil_stroke_boundingbox_calc(gps); } - gpencil_projected_2d_bound_box(gsc, gps, diff_mat, boundbox_min, boundbox_max); + ED_gpencil_projected_2d_bound_box(gsc, gps, diff_mat, boundbox_min, boundbox_max); rcti rect_stroke = {boundbox_min[0], boundbox_max[0], boundbox_min[1], boundbox_max[1]}; @@ -3126,7 +3155,7 @@ bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C, /* calculate difference matrix object */ float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); /* Calculate the extremes of the stroke in 2D. */ bGPDspoint pt_parent; @@ -3144,15 +3173,13 @@ bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C, float dist_min = FLT_MAX; LISTBASE_FOREACH (bGPDstroke *, gps_target, &gpf->strokes) { /* Check if the color is editable. */ - if ((gps_target == gps) || (ED_gpencil_stroke_color_use(ob, gpl, gps) == false)) { + if ((gps_target == gps) || (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false)) { continue; } /* Check if one of the ends is inside target stroke bounding box. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, pt2d_start, radius, diff_mat)) { - continue; - } - if (!ED_gpencil_stroke_check_collision(gsc, gps, pt2d_end, radius, diff_mat)) { + if ((!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_start, radius, diff_mat)) && + (!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_end, radius, diff_mat))) { continue; } /* Check the distance of the ends with the ends of target stroke to avoid middle contact. diff --git a/source/blender/editors/gpencil/gpencil_uv.c b/source/blender/editors/gpencil/gpencil_uv.c index ec2ccabddfe..677451eaabc 100644 --- a/source/blender/editors/gpencil/gpencil_uv.c +++ b/source/blender/editors/gpencil/gpencil_uv.c @@ -31,7 +31,6 @@ #include "BKE_context.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" -#include "BKE_unit.h" #include "RNA_access.h" #include "RNA_define.h" diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c index b212872b607..bf46fa2544f 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_ops.c +++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c @@ -28,16 +28,11 @@ #include "BLI_ghash.h" #include "BLI_math.h" -#include "BLT_translation.h" - #include "DNA_brush_types.h" #include "DNA_gpencil_types.h" #include "DNA_material_types.h" -#include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_gpencil.h" -#include "BKE_gpencil_modifier.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_paint.h" @@ -48,16 +43,11 @@ #include "RNA_access.h" #include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "UI_view2d.h" #include "ED_gpencil.h" #include "ED_screen.h" -#include "ED_view3d.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "gpencil_intern.h" @@ -674,7 +664,7 @@ static bool gpencil_extract_palette_from_vertex(bContext *C, if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); @@ -859,7 +849,7 @@ static int gpencil_material_to_vertex_exec(bContext *C, wmOperator *op) if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index e2c81d53fba..a05cc3c4dbd 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -151,7 +151,7 @@ typedef struct tGP_BrushVertexpaintData { tGP_Grid *grid; /** Total number of rows/cols. */ int grid_size; - /** Total number of cells elments in the grid array. */ + /** Total number of cells elements in the grid array. */ int grid_len; /** Grid sample position (used to determine distance of falloff) */ int grid_sample[2]; @@ -825,7 +825,8 @@ static void gpencil_save_selected_point(tGP_BrushVertexpaintData *gso, static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, bGPDstroke *gps, const char tool, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { GP_SpaceConversion *gsc = &gso->gsc; rcti *rect = &gso->brush_rect; @@ -853,7 +854,7 @@ static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, } /* Check if the stroke collide with brush. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) { + if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) { return false; } @@ -998,7 +999,8 @@ static bool gpencil_vertexpaint_brush_do_frame(bContext *C, tGP_BrushVertexpaintData *gso, bGPDlayer *gpl, bGPDframe *gpf, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { Object *ob = CTX_data_active_object(C); const char tool = ob->mode == OB_MODE_VERTEX_GPENCIL ? gso->brush->gpencil_vertex_tool : @@ -1020,12 +1022,12 @@ static bool gpencil_vertexpaint_brush_do_frame(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* Check points below the brush. */ - bool hit = gpencil_vertexpaint_select_stroke(gso, gps, tool, diff_mat); + bool hit = gpencil_vertexpaint_select_stroke(gso, gps, tool, diff_mat, bound_mat); /* If stroke was hit and has an editcurve the curve needs an update. */ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; @@ -1130,9 +1132,11 @@ static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVert continue; } - /* calculate difference matrix */ - float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + /* Calculate transform matrix. */ + float diff_mat[4][4], bound_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + copy_m4_m4(bound_mat, diff_mat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_invmat); /* Active Frame or MultiFrame? */ if (gso->is_multiframe) { @@ -1159,7 +1163,7 @@ static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVert } /* affect strokes in this frame */ - changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat); + changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat, bound_mat); } } } @@ -1167,7 +1171,8 @@ static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVert /* Apply to active frame's strokes */ if (gpl->actframe != NULL) { gso->mf_falloff = 1.0f; - changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); + changed |= gpencil_vertexpaint_brush_do_frame( + C, gso, gpl, gpl->actframe, diff_mat, bound_mat); } } } diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c index 7fa71fcce3c..a3e5ece5862 100644 --- a/source/blender/editors/gpencil/gpencil_weight_paint.c +++ b/source/blender/editors/gpencil/gpencil_weight_paint.c @@ -383,7 +383,8 @@ static void gpencil_save_selected_point(tGP_BrushWeightpaintData *gso, /* Select points in this stroke and add to an array to be used later. */ static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, bGPDstroke *gps, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { GP_SpaceConversion *gsc = &gso->gsc; rcti *rect = &gso->brush_rect; @@ -402,7 +403,7 @@ static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, bool include_last = false; /* Check if the stroke collide with brush. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) { + if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) { return; } @@ -505,7 +506,8 @@ static bool gpencil_weightpaint_brush_do_frame(bContext *C, tGP_BrushWeightpaintData *gso, bGPDlayer *gpl, bGPDframe *gpf, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { Object *ob = CTX_data_active_object(C); char tool = gso->brush->gpencil_weight_tool; @@ -526,12 +528,12 @@ static bool gpencil_weightpaint_brush_do_frame(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* Check points below the brush. */ - gpencil_weightpaint_select_stroke(gso, gps, diff_mat); + gpencil_weightpaint_select_stroke(gso, gps, diff_mat, bound_mat); } /*--------------------------------------------------------------------- @@ -578,9 +580,11 @@ static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeig continue; } - /* calculate difference matrix */ - float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + /* Calculate transform matrix. */ + float diff_mat[4][4], bound_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + copy_m4_m4(bound_mat, diff_mat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_invmat); /* Active Frame or MultiFrame? */ if (gso->is_multiframe) { @@ -608,7 +612,7 @@ static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeig } /* affect strokes in this frame */ - changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat); + changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat, bound_mat); } } } @@ -616,7 +620,8 @@ static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeig if (gpl->actframe != NULL) { /* Apply to active frame's strokes */ gso->mf_falloff = 1.0f; - changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); + changed |= gpencil_weightpaint_brush_do_frame( + C, gso, gpl, gpl->actframe, diff_mat, bound_mat); } } } diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 0a66c439f79..56494f87bfe 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -99,6 +99,30 @@ void ED_space_clip_set_clip(struct bContext *C, struct Mask *ED_space_clip_get_mask(struct SpaceClip *sc); void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mask *mask); +/* Locked state is used to preserve current clip editor viewport upon changes. Example usage: + * + * ... + * + * ClipViewLockState lock_state; + * ED_clip_view_lock_state_store(C, &lock_state); + * + * <change selection> + * + * ED_clip_view_lock_state_restore_no_jump(C, &lock_state); + * + * These function are to be used from space clip editor context only. Otherwise debug builds will + * assert, release builds will crash. */ + +typedef struct ClipViewLockState { + float offset_x, offset_y; + float lock_offset_x, lock_offset_y; + float zoom; +} ClipViewLockState; + +void ED_clip_view_lock_state_store(const struct bContext *C, ClipViewLockState *state); +void ED_clip_view_lock_state_restore_no_jump(const struct bContext *C, + const ClipViewLockState *state); + /* ** clip_ops.c ** */ void ED_operatormacros_clip(void); diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index d12882f0e29..7538dac1354 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -194,7 +194,7 @@ typedef enum FSMenuInsert { FS_INSERT_SAVE = (1 << 1), /** moves the item to the front of the list when its not already there */ FS_INSERT_FIRST = (1 << 2), - /** just append to preseve delivered order */ + /** just append to preserve delivered order */ FS_INSERT_LAST = (1 << 3), } FSMenuInsert; diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 1b7caf27ecf..12aef6e9464 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -62,6 +62,8 @@ struct bAnimContext; struct wmKeyConfig; struct wmOperator; +enum eUndoStepDir; + #define GPENCIL_MINIMUM_JOIN_DIST 20.0f /* Reproject stroke modes. */ @@ -147,9 +149,9 @@ bool ED_gpencil_has_keyframe_v3d(struct Scene *scene, struct Object *ob, int cfr bool ED_gpencil_stroke_can_use_direct(const struct ScrArea *area, const struct bGPDstroke *gps); bool ED_gpencil_stroke_can_use(const struct bContext *C, const struct bGPDstroke *gps); -bool ED_gpencil_stroke_color_use(struct Object *ob, - const struct bGPDlayer *gpl, - const struct bGPDstroke *gps); +bool ED_gpencil_stroke_material_editable(struct Object *ob, + const struct bGPDlayer *gpl, + const struct bGPDstroke *gps); /* ----------- Grease Pencil Operators ----------------- */ @@ -213,7 +215,7 @@ bool ED_gpencil_anim_copybuf_paste(struct bAnimContext *ac, const short copy_mod /* ------------ Grease-Pencil Undo System ------------------ */ int ED_gpencil_session_active(void); -int ED_undo_gpencil_step(struct bContext *C, int step, const char *name); +int ED_undo_gpencil_step(struct bContext *C, const enum eUndoStepDir step); /* ------------ Grease-Pencil Armature ------------------ */ bool ED_gpencil_add_armature(const struct bContext *C, @@ -263,11 +265,13 @@ bool ED_object_gpencil_exit(struct Main *bmain, struct Object *ob); void ED_gpencil_project_stroke_to_plane(const struct Scene *scene, const struct Object *ob, const struct RegionView3D *rv3d, + struct bGPDlayer *gpl, struct bGPDstroke *gps, const float origin[3], const int axis); void ED_gpencil_project_point_to_plane(const struct Scene *scene, const struct Object *ob, + struct bGPDlayer *gpl, const struct RegionView3D *rv3d, const float origin[3], const int axis, @@ -366,6 +370,11 @@ bool ED_gpencil_stroke_point_is_inside(struct bGPDstroke *gps, struct GP_SpaceConversion *gsc, int mouse[2], const float diff_mat[4][4]); +void ED_gpencil_projected_2d_bound_box(struct GP_SpaceConversion *gsc, + struct bGPDstroke *gps, + const float diff_mat[4][4], + float r_min[2], + float r_max[2]); struct bGPDstroke *ED_gpencil_stroke_nearest_to_ends(struct bContext *C, struct GP_SpaceConversion *gsc, diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index 3cc77887b1a..2f8faf1b2bd 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -95,6 +95,8 @@ typedef enum eActKeyBlock_Hold { ACTKEYBLOCK_FLAG_ANY_HOLD = (1 << 2), /* The curve segment uses non-bezier interpolation */ ACTKEYBLOCK_FLAG_NON_BEZIER = (1 << 3), + /* The block is grease pencil */ + ACTKEYBLOCK_FLAG_GPENCIL = (1 << 4), } eActKeyBlock_Flag; /* *********************** Keyframe Drawing ****************************** */ diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index b08ab57545f..63f124798aa 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -118,7 +118,7 @@ typedef struct KeyframeEdit_CircleData { } KeyframeEdit_CircleData; /* ************************************************ */ -/* Non-Destuctive Editing API (keyframes_edit.c) */ +/* Non-Destructive Editing API (keyframes_edit.c) */ /* --- Defines for 'OK' polls + KeyframeEditData Flags --------- */ diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index bcf52da3f69..247911bdc55 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -63,7 +63,10 @@ void ED_mask_point_pos__reverse( struct ScrArea *area, struct ARegion *region, float x, float y, float *xr, float *yr); void ED_mask_cursor_location_get(struct ScrArea *area, float cursor[2]); -bool ED_mask_selected_minmax(const struct bContext *C, float min[2], float max[2]); +bool ED_mask_selected_minmax(const struct bContext *C, + float min[2], + float max[2], + bool handles_as_control_point); /* mask_draw.c */ void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type); diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 417cae800ea..78f354a300d 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -51,6 +51,10 @@ typedef enum { #define NODE_GRID_STEPS 5 /* space_node.c */ + +void ED_node_cursor_location_get(const struct SpaceNode *snode, float value[2]); +void ED_node_cursor_location_set(struct SpaceNode *snode, const float value[2]); + int ED_node_tree_path_length(struct SpaceNode *snode); void ED_node_tree_path_get(struct SpaceNode *snode, char *value); void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index bd1a4a0c63f..73326a2d5f2 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -159,7 +159,7 @@ extern struct EnumPropertyItem prop_clear_parent_types[]; extern struct EnumPropertyItem prop_make_parent_types[]; #endif -/* Set the object's parent, return true iff successful. */ +/* Set the object's parent, return true if successful. */ bool ED_object_parent_set(struct ReportList *reports, const struct bContext *C, struct Scene *scene, diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 20417634020..deb6b7502c7 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -57,15 +57,14 @@ struct wmMsgSubscribeKey; struct wmMsgSubscribeValue; struct wmNotifier; struct wmOperatorType; +struct wmRegionListenerParams; +struct wmRegionMessageSubscribeParams; +struct wmSpaceTypeListenerParams; struct wmWindow; struct wmWindowManager; /* regions */ -void ED_region_do_listen(struct wmWindow *win, - struct ScrArea *area, - struct ARegion *region, - struct wmNotifier *note, - const Scene *scene); +void ED_region_do_listen(struct wmRegionListenerParams *params); void ED_region_do_layout(struct bContext *C, struct ARegion *region); void ED_region_do_draw(struct bContext *C, struct ARegion *region); void ED_region_exit(struct bContext *C, struct ARegion *region); @@ -144,29 +143,11 @@ void ED_area_do_msg_notify_tag_refresh(struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val); -void ED_area_do_mgs_subscribe_for_tool_header(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); -void ED_area_do_mgs_subscribe_for_tool_ui(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); +void ED_area_do_mgs_subscribe_for_tool_header(const struct wmRegionMessageSubscribeParams *params); +void ED_area_do_mgs_subscribe_for_tool_ui(const struct wmRegionMessageSubscribeParams *params); /* message bus */ -void ED_region_message_subscribe(struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); +void ED_region_message_subscribe(struct wmRegionMessageSubscribeParams *params); /* spaces */ void ED_spacetypes_keymap(struct wmKeyConfig *keyconf); @@ -178,7 +159,7 @@ void ED_area_exit(struct bContext *C, struct ScrArea *area); int ED_screen_area_active(const struct bContext *C); void ED_screen_global_areas_refresh(struct wmWindow *win); void ED_screen_global_areas_sync(struct wmWindow *win); -void ED_area_do_listen(struct wmWindow *win, ScrArea *area, struct wmNotifier *note, Scene *scene); +void ED_area_do_listen(struct wmSpaceTypeListenerParams *params); void ED_area_tag_redraw(ScrArea *area); void ED_area_tag_redraw_no_rebuild(ScrArea *area); void ED_area_tag_redraw_regiontype(ScrArea *area, int type); @@ -427,13 +408,8 @@ void ED_region_cache_draw_cached_segments(struct ARegion *region, const int efra); /* area_utils.c */ -void ED_region_generic_tools_region_message_subscribe(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); +void ED_region_generic_tools_region_message_subscribe( + const struct wmRegionMessageSubscribeParams *params); int ED_region_generic_tools_region_snap_size(const struct ARegion *region, int size, int axis); /* area_query.c */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index ca3e351a052..8f1be847e2b 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -40,7 +40,7 @@ void transform_operatortypes(void); /* ******************** Macros & Prototypes *********************** */ /* MODE AND NUMINPUT FLAGS */ -enum TfmMode { +typedef enum { TFM_INIT = -1, TFM_DUMMY, TFM_TRANSLATION, @@ -77,29 +77,11 @@ enum TfmMode { TFM_BONE_ENVELOPE_DIST, TFM_NORMAL_ROTATION, TFM_GPENCIL_OPACITY, -}; - -/* TRANSFORM CONTEXTS */ -#define CTX_NONE 0 -#define CTX_TEXTURE (1 << 0) -#define CTX_EDGE (1 << 1) -#define CTX_NO_PET (1 << 2) -#define CTX_NO_MIRROR (1 << 3) -#define CTX_AUTOCONFIRM (1 << 4) -#define CTX_MOVIECLIP (1 << 6) -#define CTX_MASK (1 << 7) -#define CTX_PAINT_CURVE (1 << 8) -#define CTX_GPENCIL_STROKES (1 << 9) -#define CTX_CURSOR (1 << 10) -/** When transforming object's, adjust the object data so it stays in the same place. */ -#define CTX_OBMODE_XFORM_OBDATA (1 << 11) -/** Transform object parents without moving their children. */ -#define CTX_OBMODE_XFORM_SKIP_CHILDREN (1 << 12) +} eTfmMode; /* Standalone call to get the transformation center corresponding to the current situation * returns 1 if successful, 0 otherwise (usually means there's no selection) - * (if 0 is returns, *vec is unmodified) - * */ + * (if false is returns, `cent3d` is unmodified). */ bool calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 7bbb7225f14..066d262cc44 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -56,6 +56,7 @@ struct bNode; struct bNodeSocket; struct bNodeTree; struct bScreen; +struct rctf; struct rcti; struct uiButSearch; struct uiFontStyle; @@ -414,57 +415,38 @@ void UI_draw_anti_tria( void UI_draw_anti_fan(float tri_array[][2], unsigned int length, const float color[4]); void UI_draw_roundbox_corner_set(int type); -void UI_draw_roundbox_aa( - bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4]); -void UI_draw_roundbox_4fv( - bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4]); -void UI_draw_roundbox_3ub_alpha(bool filled, - float minx, - float miny, - float maxx, - float maxy, +void UI_draw_roundbox_aa(const struct rctf *rect, bool filled, float rad, const float color[4]); +void UI_draw_roundbox_4fv(const struct rctf *rect, bool filled, float rad, const float col[4]); +void UI_draw_roundbox_3ub_alpha(const struct rctf *rect, + bool filled, float rad, const unsigned char col[3], unsigned char alpha); -void UI_draw_roundbox_3fv_alpha(bool filled, - float minx, - float miny, - float maxx, - float maxy, - float rad, - const float col[3], - float alpha); -void UI_draw_roundbox_shade_x(bool filled, - float minx, - float miny, - float maxx, - float maxy, +void UI_draw_roundbox_3fv_alpha( + const struct rctf *rect, bool filled, float rad, const float col[3], float alpha); +void UI_draw_roundbox_shade_x(const struct rctf *rect, + bool filled, float rad, float shadetop, float shadedown, const float col[4]); +void UI_draw_roundbox_4fv_ex(const struct rctf *rect, + const float inner1[4], + const float inner2[4], + float shade_dir, + const float outline[4], + float outline_width, + float rad); #if 0 /* unused */ int UI_draw_roundbox_corner_get(void); -void UI_draw_roundbox_shade_y(bool filled, - float minx, - float miny, - float maxx, - float maxy, - float rad, - float shadeleft, - float shaderight, - const float col[4]); #endif -void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy); +void UI_draw_box_shadow(const struct rctf *rect, unsigned char alpha); void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4]); void UI_draw_safe_areas(uint pos, - float x1, - float x2, - float y1, - float y2, + const struct rctf *rect, const float title_aspect[2], const float action_aspect[2]); @@ -526,6 +508,7 @@ typedef bool (*uiButSearchContextMenuFn)(struct bContext *C, const struct wmEvent *event); typedef struct ARegion *(*uiButSearchTooltipFn)(struct bContext *C, struct ARegion *region, + const struct rcti *item_rect, void *arg, void *active); @@ -664,8 +647,7 @@ bool UI_popup_block_name_exists(const struct bScreen *screen, const char *name); * Begin/Define Buttons/End/Draw is the typical order in which these * function should be called, though for popup blocks Draw is left out. * Freeing blocks is done by the screen/ module automatically. - * - * */ + */ uiBlock *UI_block_begin(const struct bContext *C, struct ARegion *region, @@ -1431,6 +1413,8 @@ enum { int UI_icon_from_id(struct ID *id); int UI_icon_from_report_type(int type); +int UI_icon_colorid_from_report_type(int type); +int UI_text_colorid_from_report_type(int type); int UI_icon_from_event_type(short event_type, short event_value); int UI_icon_from_keymap_item(const struct wmKeyMapItem *kmi, int r_icon_mod[4]); @@ -2499,11 +2483,12 @@ void UI_context_active_but_prop_get_templateID(struct bContext *C, struct PropertyRNA **r_prop); struct ID *UI_context_active_but_get_tab_ID(struct bContext *C); -uiBut *UI_region_active_but_get(struct ARegion *region); +uiBut *UI_region_active_but_get(const struct ARegion *region); uiBut *UI_region_but_find_rect_over(const struct ARegion *region, const struct rcti *rect_px); uiBlock *UI_region_block_find_mouse_over(const struct ARegion *region, const int xy[2], bool only_clip); +struct ARegion *UI_region_searchbox_region_get(const struct ARegion *button_region); /* uiFontStyle.align */ typedef enum eFontStyle_Align { @@ -2583,6 +2568,21 @@ struct ARegion *UI_tooltip_create_from_button(struct bContext *C, struct ARegion *UI_tooltip_create_from_gizmo(struct bContext *C, struct wmGizmo *gz); void UI_tooltip_free(struct bContext *C, struct bScreen *screen, struct ARegion *region); +typedef struct { + /** A description for the item, e.g. what happens when selecting it. */ + char description[UI_MAX_DRAW_STR]; + /* The full name of the item, without prefixes or suffixes (e.g. hint with UI_SEP_CHARP). */ + const char *name; + /** Additional info about the item (e.g. library name of a linked data-block). */ + char hint[UI_MAX_DRAW_STR]; +} uiSearchItemTooltipData; + +struct ARegion *UI_tooltip_create_from_search_item_generic( + struct bContext *C, + const struct ARegion *searchbox_region, + const struct rcti *item_rect, + const uiSearchItemTooltipData *item_tooltip_data); + /* How long before a tool-tip shows. */ #define UI_TOOLTIP_DELAY 0.5 #define UI_TOOLTIP_DELAY_LABEL 0.2 diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index d77a87e7200..266a538b6c3 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -23,6 +23,9 @@ #pragma once +/* Required for #eIconSizes which can't be forward declared if this file is included in C++. */ +#include "DNA_ID_enums.h" + #ifdef __cplusplus extern "C" { #endif @@ -34,8 +37,6 @@ struct PreviewImage; struct Scene; struct bContext; -enum eIconSizes; - typedef struct IconFile { struct IconFile *next, *prev; char filename[256]; /* FILE_MAXFILE size */ diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index c09bf41e152..1820c2f133c 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -433,7 +433,7 @@ void UI_GetColorPtrBlendShade3ubv(const unsigned char cp1[3], * (for anything fancy use UI_GetThemeColor[Fancy] then BLF_color) */ void UI_FontThemeColor(int fontid, int colorid); -/* clear the framebuffer using the input colorid */ +/* Clear the frame-buffer using the input colorid. */ void UI_ThemeClearColor(int colorid); /* internal (blender) usage only, for init and set active */ diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 8df29e5b520..64f881052a1 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -231,7 +231,7 @@ struct View2D *UI_view2d_fromcontext(const struct bContext *C); struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C); void UI_view2d_scroller_size_get(const struct View2D *v2d, float *r_x, float *r_y); -void UI_view2d_scale_get(struct View2D *v2d, float *r_x, float *r_y); +void UI_view2d_scale_get(const struct View2D *v2d, float *r_x, float *r_y); float UI_view2d_scale_get_x(const struct View2D *v2d); float UI_view2d_scale_get_y(const struct View2D *v2d); void UI_view2d_scale_get_inverse(const struct View2D *v2d, float *r_x, float *r_y); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 319ae385ffc..10cbc2dc5fa 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1284,12 +1284,10 @@ static bool ui_but_event_property_operator_string(const bContext *C, char *buf, const size_t buf_len) { - /* context toggle operator names to check... */ + /* Context toggle operator names to check. */ /* This function could use a refactor to generalize button type to operator relationship - * as well as which operators use properties. - * - Campbell - * */ + * as well as which operators use properties. - Campbell */ const char *ctx_toggle_opnames[] = { "WM_OT_context_toggle", "WM_OT_context_toggle_enum", @@ -1424,10 +1422,10 @@ static bool ui_but_event_property_operator_string(const bContext *C, // printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(prop), data_path); } - /* we have a datapath! */ + /* We have a data-path! */ bool found = false; if (data_path || (prop_enum_value_ok && prop_enum_value_id)) { - /* create a property to host the "datapath" property we're sending to the operators */ + /* Create a property to host the "data_path" property we're sending to the operators. */ IDProperty *prop_path; const IDPropertyTemplate val = {0}; @@ -1947,7 +1945,7 @@ void ui_fontscale(short *points, float aspect) } } -/* project button or block (but==NULL) to pixels in regionspace */ +/* Project button or block (but==NULL) to pixels in region-space. */ static void ui_but_to_pixelrect(rcti *rect, const ARegion *region, uiBlock *block, uiBut *but) { rctf rectf; @@ -4026,7 +4024,7 @@ static uiBut *ui_def_but(uiBlock *block, but->emboss = block->emboss; but->pie_dir = UI_RADIAL_NONE; - but->block = block; /* pointer back, used for frontbuffer status, and picker */ + but->block = block; /* pointer back, used for front-buffer status, and picker. */ if ((block->flag & UI_BUT_ALIGN) && ui_but_can_align(but)) { but->alignnr = block->alignnr; @@ -4749,7 +4747,7 @@ static int findBitIndex(uint x) return idx; } -/* autocomplete helper functions */ +/* Auto-complete helper functions. */ struct AutoComplete { size_t maxlen; int matches; diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 85730d138ac..53a04ec9db5 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -953,7 +953,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) } } - /* If the button reprents an id, it can set the "id" context pointer. */ + /* If the button represents an id, it can set the "id" context pointer. */ if (U.experimental.use_asset_browser && ED_asset_can_make_single_from_context(C)) { ID *id = CTX_data_pointer_get_type(C, "id", &RNA_ID).data; diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 5bb6b0f21e7..d10cdc207c2 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -81,544 +81,116 @@ int UI_draw_roundbox_corner_get(void) } #endif -void UI_draw_roundbox_3ub_alpha(bool filled, - float minx, - float miny, - float maxx, - float maxy, - float rad, - const uchar col[3], - uchar alpha) +void UI_draw_roundbox_4fv_ex(const rctf *rect, + const float inner1[4], + const float inner2[4], + float shade_dir, + const float outline[4], + float outline_width, + float rad) { - float colv[4]; - colv[0] = ((float)col[0]) / 255; - colv[1] = ((float)col[1]) / 255; - colv[2] = ((float)col[2]) / 255; - colv[3] = ((float)alpha) / 255; - UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv); -} - -void UI_draw_roundbox_3fv_alpha(bool filled, - float minx, - float miny, - float maxx, - float maxy, - float rad, - const float col[3], - float alpha) -{ - float colv[4]; - colv[0] = col[0]; - colv[1] = col[1]; - colv[2] = col[2]; - colv[3] = alpha; - UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv); -} - -void UI_draw_roundbox_aa( - bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4]) -{ - uiWidgetBaseParameters widget_params = { - .recti.xmin = minx + U.pixelsize, - .recti.ymin = miny + U.pixelsize, - .recti.xmax = maxx - U.pixelsize, - .recti.ymax = maxy - U.pixelsize, - .rect.xmin = minx, - .rect.ymin = miny, - .rect.xmax = maxx, - .rect.ymax = maxy, - .radi = rad, - .rad = rad, - .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f, - .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f, - .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f, - .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f, - .color_inner1[0] = filled ? color[0] : 0.0f, - .color_inner1[1] = filled ? color[1] : 0.0f, - .color_inner1[2] = filled ? color[2] : 0.0f, - .color_inner1[3] = filled ? color[3] : 0.0f, - .color_inner2[0] = filled ? color[0] : 0.0f, - .color_inner2[1] = filled ? color[1] : 0.0f, - .color_inner2[2] = filled ? color[2] : 0.0f, - .color_inner2[3] = filled ? color[3] : 0.0f, - .color_outline[0] = color[0], - .color_outline[1] = color[1], - .color_outline[2] = color[2], - .color_outline[3] = color[3], - .alpha_discard = 1.0f, - }; - - /* XXX this is to emulate previous behavior of semitransparent fills but that's was a side effect - * of the previous AA method. Better fix the callers. */ - if (filled) { - widget_params.color_inner1[3] *= 0.65f; - widget_params.color_inner2[3] *= 0.65f; - widget_params.color_outline[3] *= 0.65f; - } - /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space. * If it has been scaled, then it's no longer valid. */ - - GPUBatch *batch = ui_batch_roundbox_widget_get(); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); - GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float(*)[4]) & widget_params); - - GPU_blend(GPU_BLEND_ALPHA); - - GPU_batch_draw(batch); - - GPU_blend(GPU_BLEND_NONE); -} - -void UI_draw_roundbox_4fv( - bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4]) -{ -#if 0 - float vec[7][2] = { - {0.195, 0.02}, - {0.383, 0.067}, - {0.55, 0.169}, - {0.707, 0.293}, - {0.831, 0.45}, - {0.924, 0.617}, - {0.98, 0.805}, - }; - int a; - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - /* mult */ - for (a = 0; a < 7; a++) { - mul_v2_fl(vec[a], rad); - } - - uint vert_len = 0; - vert_len += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; - vert_len += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; - vert_len += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; - vert_len += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor4fv(col); - - immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_len); - /* start with corner right-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - immVertex2f(pos, maxx - rad, miny); - for (a = 0; a < 7; a++) { - immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); - } - immVertex2f(pos, maxx, miny + rad); - } - else { - immVertex2f(pos, maxx, miny); - } - - /* corner right-top */ - if (roundboxtype & UI_CNR_TOP_RIGHT) { - immVertex2f(pos, maxx, maxy - rad); - for (a = 0; a < 7; a++) { - immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); - } - immVertex2f(pos, maxx - rad, maxy); - } - else { - immVertex2f(pos, maxx, maxy); - } - - /* corner left-top */ - if (roundboxtype & UI_CNR_TOP_LEFT) { - immVertex2f(pos, minx + rad, maxy); - for (a = 0; a < 7; a++) { - immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); - } - immVertex2f(pos, minx, maxy - rad); - } - else { - immVertex2f(pos, minx, maxy); - } - - /* corner left-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - immVertex2f(pos, minx, miny + rad); - for (a = 0; a < 7; a++) { - immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); - } - immVertex2f(pos, minx + rad, miny); - } - else { - immVertex2f(pos, minx, miny); - } - - immEnd(); - immUnbindProgram(); -#endif uiWidgetBaseParameters widget_params = { - .recti.xmin = minx + U.pixelsize, - .recti.ymin = miny + U.pixelsize, - .recti.xmax = maxx - U.pixelsize, - .recti.ymax = maxy - U.pixelsize, - .rect.xmin = minx, - .rect.ymin = miny, - .rect.xmax = maxx, - .rect.ymax = maxy, + .recti.xmin = rect->xmin + outline_width, + .recti.ymin = rect->ymin + outline_width, + .recti.xmax = rect->xmax - outline_width, + .recti.ymax = rect->ymax - outline_width, + .rect = *rect, .radi = rad, .rad = rad, .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f, .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f, .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f, .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f, - .color_inner1[0] = filled ? col[0] : 0.0f, - .color_inner1[1] = filled ? col[1] : 0.0f, - .color_inner1[2] = filled ? col[2] : 0.0f, - .color_inner1[3] = filled ? col[3] : 0.0f, - .color_inner2[0] = filled ? col[0] : 0.0f, - .color_inner2[1] = filled ? col[1] : 0.0f, - .color_inner2[2] = filled ? col[2] : 0.0f, - .color_inner2[3] = filled ? col[3] : 0.0f, - .color_outline[0] = col[0], - .color_outline[1] = col[1], - .color_outline[2] = col[2], - .color_outline[3] = col[3], + .color_inner1[0] = inner1 ? inner1[0] : 0.0f, + .color_inner1[1] = inner1 ? inner1[1] : 0.0f, + .color_inner1[2] = inner1 ? inner1[2] : 0.0f, + .color_inner1[3] = inner1 ? inner1[3] : 0.0f, + .color_inner2[0] = inner2 ? inner2[0] : inner1 ? inner1[0] : 0.0f, + .color_inner2[1] = inner2 ? inner2[1] : inner1 ? inner1[1] : 0.0f, + .color_inner2[2] = inner2 ? inner2[2] : inner1 ? inner1[2] : 0.0f, + .color_inner2[3] = inner2 ? inner2[3] : inner1 ? inner1[3] : 0.0f, + .color_outline[0] = outline ? outline[0] : inner1 ? inner1[0] : 0.0f, + .color_outline[1] = outline ? outline[1] : inner1 ? inner1[1] : 0.0f, + .color_outline[2] = outline ? outline[2] : inner1 ? inner1[2] : 0.0f, + .color_outline[3] = outline ? outline[3] : inner1 ? inner1[3] : 0.0f, + .shade_dir = shade_dir, .alpha_discard = 1.0f, }; - /* Exactly the same as UI_draw_roundbox_aa but does not do the legacy transparency. */ - - /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space. - * If it has been scaled, then it's no longer valid. */ - GPUBatch *batch = ui_batch_roundbox_widget_get(); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float(*)[4]) & widget_params); - GPU_blend(GPU_BLEND_ALPHA); - GPU_batch_draw(batch); - GPU_blend(GPU_BLEND_NONE); } -#if 0 -static void round_box_shade_col(uint attr, - const float col1[3], - float const col2[3], - const float fac) +void UI_draw_roundbox_3ub_alpha( + const rctf *rect, bool filled, float rad, const uchar col[3], uchar alpha) { - float col[4] = { - fac * col1[0] + (1.0f - fac) * col2[0], - fac * col1[1] + (1.0f - fac) * col2[1], - fac * col1[2] + (1.0f - fac) * col2[2], - 1.0f, + float colv[4] = { + ((float)col[0]) / 255, + ((float)col[1]) / 255, + ((float)col[2]) / 255, + ((float)alpha) / 255, }; - immAttr4fv(attr, col); + UI_draw_roundbox_4fv_ex(rect, (filled) ? colv : NULL, NULL, 1.0f, colv, U.pixelsize, rad); } -#endif -/* linear horizontal shade within button or in outline */ -/* view2d scrollers use it */ -void UI_draw_roundbox_shade_x(bool filled, - float minx, - float miny, - float maxx, - float maxy, - float rad, - float shadetop, - float shadedown, - const float col[4]) +void UI_draw_roundbox_3fv_alpha( + const rctf *rect, bool filled, float rad, const float col[3], float alpha) { -#if 0 - float vec[7][2] = { - {0.195, 0.02}, - {0.383, 0.067}, - {0.55, 0.169}, - {0.707, 0.293}, - {0.831, 0.45}, - {0.924, 0.617}, - {0.98, 0.805}, - }; - const float div = maxy - miny; - const float idiv = 1.0f / div; - float coltop[3], coldown[3]; - int vert_count = 0; - int a; - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); - - /* mult */ - for (a = 0; a < 7; a++) { - mul_v2_fl(vec[a], rad); - } - - /* 'shade' defines strength of shading */ - coltop[0] = min_ff(1.0f, col[0] + shadetop); - coltop[1] = min_ff(1.0f, col[1] + shadetop); - coltop[2] = min_ff(1.0f, col[2] + shadetop); - coldown[0] = max_ff(0.0f, col[0] + shadedown); - coldown[1] = max_ff(0.0f, col[1] + shadedown); - coldown[2] = max_ff(0.0f, col[2] + shadedown); - - vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; - vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; - vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; - vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; - - immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_count); - - /* start with corner right-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - - round_box_shade_col(color, coltop, coldown, 0.0); - immVertex2f(pos, maxx - rad, miny); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, coltop, coldown, vec[a][1] * idiv); - immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); - } - - round_box_shade_col(color, coltop, coldown, rad * idiv); - immVertex2f(pos, maxx, miny + rad); - } - else { - round_box_shade_col(color, coltop, coldown, 0.0); - immVertex2f(pos, maxx, miny); - } - - /* corner right-top */ - if (roundboxtype & UI_CNR_TOP_RIGHT) { - - round_box_shade_col(color, coltop, coldown, (div - rad) * idiv); - immVertex2f(pos, maxx, maxy - rad); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, coltop, coldown, (div - rad + vec[a][1]) * idiv); - immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); - } - round_box_shade_col(color, coltop, coldown, 1.0); - immVertex2f(pos, maxx - rad, maxy); - } - else { - round_box_shade_col(color, coltop, coldown, 1.0); - immVertex2f(pos, maxx, maxy); - } - - /* corner left-top */ - if (roundboxtype & UI_CNR_TOP_LEFT) { - - round_box_shade_col(color, coltop, coldown, 1.0); - immVertex2f(pos, minx + rad, maxy); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, coltop, coldown, (div - vec[a][1]) * idiv); - immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); - } - - round_box_shade_col(color, coltop, coldown, (div - rad) * idiv); - immVertex2f(pos, minx, maxy - rad); - } - else { - round_box_shade_col(color, coltop, coldown, 1.0); - immVertex2f(pos, minx, maxy); - } - - /* corner left-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - - round_box_shade_col(color, coltop, coldown, rad * idiv); - immVertex2f(pos, minx, miny + rad); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, coltop, coldown, (rad - vec[a][1]) * idiv); - immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); - } + float colv[4] = {col[0], col[1], col[2], alpha}; + UI_draw_roundbox_4fv_ex(rect, (filled) ? colv : NULL, NULL, 1.0f, colv, U.pixelsize, rad); +} - round_box_shade_col(color, coltop, coldown, 0.0); - immVertex2f(pos, minx + rad, miny); - } - else { - round_box_shade_col(color, coltop, coldown, 0.0); - immVertex2f(pos, minx, miny); +void UI_draw_roundbox_aa(const rctf *rect, bool filled, float rad, const float color[4]) +{ + /* XXX this is to emulate previous behavior of semitransparent fills but that's was a side effect + * of the previous AA method. Better fix the callers. */ + float colv[4] = {color[0], color[1], color[2], color[3]}; + if (filled) { + colv[3] *= 0.65f; } - immEnd(); - immUnbindProgram(); -#endif - uiWidgetBaseParameters widget_params = { - .recti.xmin = minx + U.pixelsize, - .recti.ymin = miny + U.pixelsize, - .recti.xmax = maxx - U.pixelsize, - .recti.ymax = maxy - U.pixelsize, - .rect.xmin = minx, - .rect.ymin = miny, - .rect.xmax = maxx, - .rect.ymax = maxy, - .radi = rad, - .rad = rad, - .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f, - .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f, - .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f, - .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f, - .color_inner1[0] = !filled ? 0.0f : min_ff(1.0f, col[0] + shadetop), - .color_inner1[1] = !filled ? 0.0f : min_ff(1.0f, col[1] + shadetop), - .color_inner1[2] = !filled ? 0.0f : min_ff(1.0f, col[2] + shadetop), - .color_inner1[3] = !filled ? 0.0f : 1.0f, - .color_inner2[0] = !filled ? 0.0f : max_ff(0.0f, col[0] + shadedown), - .color_inner2[1] = !filled ? 0.0f : max_ff(0.0f, col[1] + shadedown), - .color_inner2[2] = !filled ? 0.0f : max_ff(0.0f, col[2] + shadedown), - .color_inner2[3] = !filled ? 0.0f : 1.0f, - /* TODO: non-filled box don't have gradients. Just use middle color. */ - .color_outline[0] = clamp_f(col[0] + shadetop + shadedown, 0.0f, 1.0f), - .color_outline[1] = clamp_f(col[1] + shadetop + shadedown, 0.0f, 1.0f), - .color_outline[2] = clamp_f(col[2] + shadetop + shadedown, 0.0f, 1.0f), - .color_outline[3] = clamp_f(col[3] + shadetop + shadedown, 0.0f, 1.0f), - .shade_dir = 1.0f, - .alpha_discard = 1.0f, - }; - - GPU_blend(GPU_BLEND_ALPHA); - - GPUBatch *batch = ui_batch_roundbox_widget_get(); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); - GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float(*)[4]) & widget_params); - GPU_batch_draw(batch); + UI_draw_roundbox_4fv_ex(rect, (filled) ? colv : NULL, NULL, 1.0f, colv, U.pixelsize, rad); +} - GPU_blend(GPU_BLEND_NONE); +void UI_draw_roundbox_4fv(const rctf *rect, bool filled, float rad, const float col[4]) +{ + /* Exactly the same as UI_draw_roundbox_aa but does not do the legacy transparency. */ + UI_draw_roundbox_4fv_ex(rect, (filled) ? col : NULL, NULL, 1.0f, col, U.pixelsize, rad); } -#if 0 /* unused */ -/* linear vertical shade within button or in outline */ +/* linear horizontal shade within button or in outline */ /* view2d scrollers use it */ -void UI_draw_roundbox_shade_y(bool filled, - float minx, - float miny, - float maxx, - float maxy, - float rad, - float shadeleft, - float shaderight, - const float col[4]) +void UI_draw_roundbox_shade_x( + const rctf *rect, bool filled, float rad, float shadetop, float shadedown, const float col[4]) { - float vec[7][2] = { - {0.195, 0.02}, - {0.383, 0.067}, - {0.55, 0.169}, - {0.707, 0.293}, - {0.831, 0.45}, - {0.924, 0.617}, - {0.98, 0.805}, - }; - const float div = maxx - minx; - const float idiv = 1.0f / div; - float colLeft[3], colRight[3]; - int vert_count = 0; - int a; - - /* mult */ - for (a = 0; a < 7; a++) { - mul_v2_fl(vec[a], rad); - } - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); - - /* 'shade' defines strength of shading */ - colLeft[0] = min_ff(1.0f, col[0] + shadeleft); - colLeft[1] = min_ff(1.0f, col[1] + shadeleft); - colLeft[2] = min_ff(1.0f, col[2] + shadeleft); - colRight[0] = max_ff(0.0f, col[0] + shaderight); - colRight[1] = max_ff(0.0f, col[1] + shaderight); - colRight[2] = max_ff(0.0f, col[2] + shaderight); - - vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; - vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; - vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; - vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; - - immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_count); + float inner1[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float inner2[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float outline[4]; - /* start with corner right-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - round_box_shade_col(color, colLeft, colRight, 0.0); - immVertex2f(pos, maxx - rad, miny); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, colLeft, colRight, vec[a][0] * idiv); - immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); - } - - round_box_shade_col(color, colLeft, colRight, rad * idiv); - immVertex2f(pos, maxx, miny + rad); - } - else { - round_box_shade_col(color, colLeft, colRight, 0.0); - immVertex2f(pos, maxx, miny); - } - - /* corner right-top */ - if (roundboxtype & UI_CNR_TOP_RIGHT) { - round_box_shade_col(color, colLeft, colRight, 0.0); - immVertex2f(pos, maxx, maxy - rad); - - for (a = 0; a < 7; a++) { - - round_box_shade_col(color, colLeft, colRight, (div - rad - vec[a][0]) * idiv); - immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); - } - round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv); - immVertex2f(pos, maxx - rad, maxy); - } - else { - round_box_shade_col(color, colLeft, colRight, 0.0); - immVertex2f(pos, maxx, maxy); - } - - /* corner left-top */ - if (roundboxtype & UI_CNR_TOP_LEFT) { - round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv); - immVertex2f(pos, minx + rad, maxy); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, colLeft, colRight, (div - rad + vec[a][0]) * idiv); - immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); - } - - round_box_shade_col(color, colLeft, colRight, 1.0); - immVertex2f(pos, minx, maxy - rad); - } - else { - round_box_shade_col(color, colLeft, colRight, 1.0); - immVertex2f(pos, minx, maxy); - } - - /* corner left-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - round_box_shade_col(color, colLeft, colRight, 1.0); - immVertex2f(pos, minx, miny + rad); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, colLeft, colRight, (vec[a][0]) * idiv); - immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); - } - - round_box_shade_col(color, colLeft, colRight, 1.0); - immVertex2f(pos, minx + rad, miny); - } - else { - round_box_shade_col(color, colLeft, colRight, 1.0); - immVertex2f(pos, minx, miny); - } - - immEnd(); - immUnbindProgram(); + if (filled) { + inner1[0] = min_ff(1.0f, col[0] + shadetop); + inner1[1] = min_ff(1.0f, col[1] + shadetop); + inner1[2] = min_ff(1.0f, col[2] + shadetop); + inner1[3] = 1.0f; + inner2[0] = max_ff(0.0f, col[0] + shadedown); + inner2[1] = max_ff(0.0f, col[1] + shadedown); + inner2[2] = max_ff(0.0f, col[2] + shadedown); + inner2[3] = 1.0f; + } + + /* TODO: non-filled box don't have gradients. Just use middle color. */ + outline[0] = clamp_f(col[0] + shadetop + shadedown, 0.0f, 1.0f); + outline[1] = clamp_f(col[1] + shadetop + shadedown, 0.0f, 1.0f); + outline[2] = clamp_f(col[2] + shadetop + shadedown, 0.0f, 1.0f); + outline[3] = clamp_f(col[3] + shadetop + shadedown, 0.0f, 1.0f); + + UI_draw_roundbox_4fv_ex(rect, inner1, inner2, 1.0f, outline, U.pixelsize, rad); } -#endif /* unused */ void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4]) { @@ -783,7 +355,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(region), GPU_blend(GPU_BLEND_NONE); # if 0 - /* restore scissortest */ + /* Restore scissor-test. */ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]); # endif @@ -799,15 +371,12 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(region), * \param x1, x2, y1, y2: The offsets for the view, not the zones. */ void UI_draw_safe_areas(uint pos, - float x1, - float x2, - float y1, - float y2, + const rctf *rect, const float title_aspect[2], const float action_aspect[2]) { - const float size_x_half = (x2 - x1) * 0.5f; - const float size_y_half = (y2 - y1) * 0.5f; + const float size_x_half = (rect->xmax - rect->xmin) * 0.5f; + const float size_y_half = (rect->ymax - rect->ymin) * 0.5f; const float *safe_areas[] = {title_aspect, action_aspect}; const int safe_len = ARRAY_SIZE(safe_areas); @@ -817,10 +386,10 @@ void UI_draw_safe_areas(uint pos, const float margin_x = safe_areas[i][0] * size_x_half; const float margin_y = safe_areas[i][1] * size_y_half; - const float minx = x1 + margin_x; - const float miny = y1 + margin_y; - const float maxx = x2 - margin_x; - const float maxy = y2 - margin_y; + const float minx = rect->xmin + margin_x; + const float miny = rect->ymin + margin_y; + const float maxx = rect->xmax - margin_x; + const float maxy = rect->ymax - margin_y; imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy); } @@ -835,7 +404,15 @@ static void draw_scope_end(const rctf *rect) UI_draw_roundbox_corner_set(UI_CNR_ALL); const float color[4] = {0.0f, 0.0f, 0.0f, 0.5f}; UI_draw_roundbox_4fv( - false, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect->xmin - 1, + .xmax = rect->xmax + 1, + .ymin = rect->ymin, + .ymax = rect->ymax + 1, + }, + false, + 3.0f, + color); } static void histogram_draw_one(float r, @@ -928,7 +505,15 @@ void ui_draw_but_HISTOGRAM(ARegion *UNUSED(region), UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_4fv( - true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect.xmin - 1, + .xmax = rect.xmax + 1, + .ymin = rect.ymin - 1, + .ymax = rect.ymax + 1, + }, + true, + 3.0f, + color); /* need scissor test, histogram can draw outside of boundary */ int scissor[4]; @@ -1070,7 +655,15 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(region), UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_4fv( - true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect.xmin - 1, + .xmax = rect.xmax + 1, + .ymin = rect.ymin - 1, + .ymax = rect.ymax + 1, + }, + true, + 3.0f, + color); /* need scissor test, waveform can draw outside of boundary */ GPU_scissor_get(scissor); @@ -1399,7 +992,15 @@ void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(region), UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_4fv( - true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect.xmin - 1, + .xmax = rect.xmax + 1, + .ymin = rect.ymin - 1, + .ymax = rect.ymax + 1, + }, + true, + 3.0f, + color); /* need scissor test, hvectorscope can draw outside of boundary */ int scissor[4]; @@ -1774,7 +1375,16 @@ void ui_draw_but_UNITVEC(uiBut *but, const uiWidgetColors *wcol, const rcti *rec /* backdrop */ UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_3ub_alpha( - true, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, wcol->inner, 255); + &(const rctf){ + .xmin = rect->xmin, + .xmax = rect->xmax, + .ymin = rect->ymin, + .ymax = rect->ymax, + }, + true, + 5.0f, + wcol->inner, + 255); GPU_face_culling(GPU_CULL_BACK); @@ -1800,7 +1410,7 @@ void ui_draw_but_UNITVEC(uiBut *but, const uiWidgetColors *wcol, const rcti *rec GPU_batch_uniform_3fv(sphere, "light", light); GPU_batch_draw(sphere); - /* restore */ + /* Restore. */ GPU_face_culling(GPU_CULL_NONE); /* AA circle */ @@ -2130,7 +1740,7 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, immEnd(); immUnbindProgram(); - /* restore scissortest */ + /* Restore scissor-test. */ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]); /* outline */ @@ -2420,7 +2030,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, } immUnbindProgram(); - /* restore scissortest */ + /* Restore scissor-test. */ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]); /* Outline */ @@ -2465,7 +2075,15 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), const float color[4] = {0.7f, 0.3f, 0.3f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_4fv( - true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect.xmin - 1, + .xmax = rect.xmax + 1, + .ymin = rect.ymin, + .ymax = rect.ymax + 1, + }, + true, + 3.0f, + color); ok = true; } @@ -2514,7 +2132,15 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), const float color[4] = {0.0f, 0.0f, 0.0f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_4fv( - true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect.xmin - 1, + .xmax = rect.xmax + 1, + .ymin = rect.ymin, + .ymax = rect.ymax + 1, + }, + true, + 3.0f, + color); } IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); @@ -2577,7 +2203,15 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), const float color[4] = {0.0f, 0.0f, 0.0f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_4fv( - true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect.xmin - 1, + .xmax = rect.xmax + 1, + .ymin = rect.ymin, + .ymax = rect.ymax + 1, + }, + true, + 3.0f, + color); } /* Restore scissor test. */ @@ -2594,14 +2228,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), * would replace / modify the following 3 functions - merwin */ -static void ui_shadowbox(uint pos, - uint color, - float minx, - float miny, - float maxx, - float maxy, - float shadsize, - uchar alpha) +static void ui_shadowbox(const rctf *rect, uint pos, uint color, float shadsize, uchar alpha) { /** * <pre> @@ -2616,16 +2243,16 @@ static void ui_shadowbox(uint pos, * v8______v6_- * </pre> */ - const float v1[2] = {maxx, maxy - 0.3f * shadsize}; - const float v2[2] = {maxx + shadsize, maxy - 0.75f * shadsize}; - const float v3[2] = {maxx, miny}; - const float v4[2] = {maxx + shadsize, miny}; + const float v1[2] = {rect->xmax, rect->ymax - 0.3f * shadsize}; + const float v2[2] = {rect->xmax + shadsize, rect->ymax - 0.75f * shadsize}; + const float v3[2] = {rect->xmax, rect->ymin}; + const float v4[2] = {rect->xmax + shadsize, rect->ymin}; - const float v5[2] = {maxx + 0.7f * shadsize, miny - 0.7f * shadsize}; + const float v5[2] = {rect->xmax + 0.7f * shadsize, rect->ymin - 0.7f * shadsize}; - const float v6[2] = {maxx, miny - shadsize}; - const float v7[2] = {minx + 0.3f * shadsize, miny}; - const float v8[2] = {minx + 0.5f * shadsize, miny - shadsize}; + const float v6[2] = {rect->xmax, rect->ymin - shadsize}; + const float v7[2] = {rect->xmin + 0.3f * shadsize, rect->ymin}; + const float v8[2] = {rect->xmin + 0.5f * shadsize, rect->ymin - shadsize}; /* right quad */ immAttr4ub(color, 0, 0, 0, alpha); @@ -2664,7 +2291,7 @@ static void ui_shadowbox(uint pos, immVertex2fv(pos, v3); } -void UI_draw_box_shadow(uchar alpha, float minx, float miny, float maxx, float maxy) +void UI_draw_box_shadow(const rctf *rect, uchar alpha) { GPU_blend(GPU_BLEND_ALPHA); @@ -2678,9 +2305,9 @@ void UI_draw_box_shadow(uchar alpha, float minx, float miny, float maxx, float m immBegin(GPU_PRIM_TRIS, 54); /* accumulated outline boxes to make shade not linear, is more pleasant */ - ui_shadowbox(pos, color, minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8); - ui_shadowbox(pos, color, minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8); - ui_shadowbox(pos, color, minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8); + ui_shadowbox(rect, pos, color, 11.0, (20 * alpha) >> 8); + ui_shadowbox(rect, pos, color, 7.0, (40 * alpha) >> 8); + ui_shadowbox(rect, pos, color, 5.0, (80 * alpha) >> 8); immEnd(); @@ -2755,13 +2382,16 @@ void ui_draw_dropshadow( /* outline emphasis */ const float color[4] = {0.0f, 0.0f, 0.0f, 0.4f}; - UI_draw_roundbox_4fv(false, - rct->xmin - 0.5f, - rct->ymin - 0.5f, - rct->xmax + 0.5f, - rct->ymax + 0.5f, - radius + 0.5f, - color); + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = rct->xmin - 0.5f, + .xmax = rct->xmax + 0.5f, + .ymin = rct->ymin - 0.5f, + .ymax = rct->ymax + 0.5f, + }, + false, + radius + 0.5f, + color); GPU_blend(GPU_BLEND_NONE); } diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index 4d0e1584156..de39484bc1e 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -24,8 +24,6 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" -#include "BLI_blenlib.h" - #include "BKE_context.h" #include "BKE_screen.h" diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c index ead65a62226..a4adbef0b94 100644 --- a/source/blender/editors/interface/interface_eyedropper_depth.c +++ b/source/blender/editors/interface/interface_eyedropper_depth.c @@ -41,8 +41,6 @@ #include "BKE_screen.h" #include "BKE_unit.h" -#include "DEG_depsgraph.h" - #include "RNA_access.h" #include "UI_interface.h" @@ -66,9 +64,9 @@ typedef struct DepthDropper { bool is_undo; bool is_set; - float init_depth; /* for resetting on cancel */ + float init_depth; /* For resetting on cancel. */ - bool accum_start; /* has mouse been presed */ + bool accum_start; /* Has mouse been pressed. */ float accum_depth; int accum_tot; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 97d9b225d3c..1bfd84a7046 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -349,7 +349,7 @@ typedef struct uiHandleButtonData { #endif ColorBand *coba; - /* tooltip */ + /* Tool-tip. */ uint tooltip_force : 1; /* auto open */ @@ -1617,7 +1617,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void static bool ui_but_is_drag_toggle(const uiBut *but) { return ((ui_drag_toggle_but_is_supported(but) == true) && - /* menu check is importnt so the button dragged over isn't removed instantly */ + /* Menu check is important so the button dragged over isn't removed instantly. */ (ui_block_is_menu(but->block) == false)); } @@ -3710,9 +3710,9 @@ static void ui_do_but_textedit( case EVT_AKEY: - /* Ctrl + A: Select all */ + /* Ctrl-A: Select all. */ #if defined(__APPLE__) - /* OSX uses cmd-a systemwide, so add it */ + /* 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))) #else @@ -3726,7 +3726,7 @@ static void ui_do_but_textedit( break; case EVT_TABKEY: - /* there is a key conflict here, we can't tab with autocomplete */ + /* There is a key conflict here, we can't tab with auto-complete. */ if (but->autocomplete_func || data->searchbox) { const int autocomplete = ui_textedit_autocomplete(C, but, data); changed = autocomplete != AUTOCOMPLETE_NO_MATCH; @@ -3735,13 +3735,14 @@ static void ui_do_but_textedit( button_activate_state(C, but, BUTTON_STATE_EXIT); } } - /* the hotkey here is not well defined, was G.qual so we check all */ - else if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) { - ui_textedit_prev_but(block, but, data); - button_activate_state(C, but, BUTTON_STATE_EXIT); - } - else { - ui_textedit_next_but(block, but, data); + else if (!IS_EVENT_MOD(event, ctrl, alt, oskey)) { + /* Use standard keys for cycling through buttons Tab, Shift-Tab to reverse. */ + if (event->shift) { + ui_textedit_prev_but(block, but, data); + } + else { + ui_textedit_next_but(block, but, data); + } button_activate_state(C, but, BUTTON_STATE_EXIT); } retval = WM_UI_HANDLER_BREAK; @@ -4575,7 +4576,7 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons return WM_UI_HANDLER_BREAK; } if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { - /* Support ctrl-wheel to cycle values on expanded enum rows. */ + /* Support Ctrl-Wheel to cycle values on expanded enum rows. */ if (but->type == UI_BTYPE_ROW) { int type = event->type; int val = event->val; @@ -5086,7 +5087,7 @@ static int ui_do_but_NUM( else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { if (data->dragchange) { #ifdef USE_DRAG_MULTINUM - /* if we started multibutton but didn't drag, then edit */ + /* If we started multi-button but didn't drag, then edit. */ if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) { click = 1; } @@ -5408,7 +5409,7 @@ static int ui_do_but_SLI( else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { if (data->dragchange) { #ifdef USE_DRAG_MULTINUM - /* if we started multibutton but didn't drag, then edit */ + /* If we started multi-button but didn't drag, then edit. */ if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) { click = 1; } @@ -6836,7 +6837,7 @@ static bool ui_numedit_but_CURVE(uiBlock *block, #ifdef USE_CONT_MOUSE_CORRECT /* note: using 'cmp_last' is weak since there may be multiple points selected, - * but in practice this isnt really an issue */ + * but in practice this isn't really an issue */ if (ui_but_is_cursor_warp(but)) { /* OK but can go outside bounds */ data->ungrab_mval[0] = but->rect.xmin + ((cmp_last->x - cumap->curr.xmin) * zoomx); @@ -7107,7 +7108,7 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, changed = true; #ifdef USE_CONT_MOUSE_CORRECT /* note: using 'cmp_last' is weak since there may be multiple points selected, - * but in practice this isnt really an issue */ + * but in practice this isn't really an issue */ if (ui_but_is_cursor_warp(but)) { /* OK but can go outside bounds */ data->ungrab_mval[0] = but->rect.xmin + ((last_x - profile->view_rect.xmin) * zoomx); @@ -7822,7 +7823,7 @@ static void ui_blocks_set_tooltips(ARegion *region, const bool enable) } /** - * Recreate tooltip (use to update dynamic tips) + * Recreate tool-tip (use to update dynamic tips) */ void UI_but_tooltip_refresh(bContext *C, uiBut *but) { @@ -7921,7 +7922,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s return; } - /* highlight has timers for tooltips and auto open */ + /* Highlight has timers for tool-tips and auto open. */ if (state == BUTTON_STATE_HIGHLIGHT) { but->flag &= ~UI_SELECT; @@ -8261,7 +8262,7 @@ static void button_activate_exit( } } - /* disable tooltips until mousemove + last active flag */ + /* Disable tool-tips until mouse-move + last active flag. */ LISTBASE_FOREACH (uiBlock *, block_iter, &data->region->uiblocks) { LISTBASE_FOREACH (uiBut *, bt, &block_iter->buttons) { bt->flag &= ~UI_BUT_LAST_ACTIVE; @@ -8325,7 +8326,7 @@ void ui_but_active_free(const bContext *C, uiBut *but) } /* returns the active button with an optional checking function */ -static uiBut *ui_context_button_active(ARegion *region, bool (*but_check_cb)(uiBut *)) +static uiBut *ui_context_button_active(const ARegion *region, bool (*but_check_cb)(const uiBut *)) { uiBut *but_found = NULL; @@ -8349,7 +8350,7 @@ static uiBut *ui_context_button_active(ARegion *region, bool (*but_check_cb)(uiB but_found = activebut; - /* recurse into opened menu, like colorpicker case */ + /* Recurse into opened menu, like color-picker case. */ if (data && data->menu && (region != data->menu->region)) { region = data->menu->region; } @@ -8366,7 +8367,7 @@ static uiBut *ui_context_button_active(ARegion *region, bool (*but_check_cb)(uiB return but_found; } -static bool ui_context_rna_button_active_test(uiBut *but) +static bool ui_context_rna_button_active_test(const uiBut *but) { return (but->rnapoin.data != NULL); } @@ -8391,7 +8392,7 @@ uiBut *UI_context_active_but_get_respect_menu(const bContext *C) return ui_context_button_active(region_menu ? region_menu : CTX_wm_region(C), NULL); } -uiBut *UI_region_active_but_get(ARegion *region) +uiBut *UI_region_active_but_get(const ARegion *region) { return ui_context_button_active(region, NULL); } @@ -8489,6 +8490,15 @@ wmOperator *UI_context_active_operator_get(const struct bContext *C) return NULL; } +/** + * Try to find a search-box region opened from a button in \a button_region. + */ +ARegion *UI_region_searchbox_region_get(const ARegion *button_region) +{ + uiBut *but = UI_region_active_but_get(button_region); + return (but != NULL) ? but->active->searchbox : NULL; +} + /* helper function for insert keyframe, reset to default, etc operators */ void UI_context_update_anim_flag(const bContext *C) { @@ -8522,7 +8532,7 @@ void UI_context_update_anim_flag(const bContext *C) } if (activebut) { - /* always recurse into opened menu, so all buttons update (like colorpicker) */ + /* Always recurse into opened menu, so all buttons update (like color-picker). */ uiHandleButtonData *data = activebut->active; if (data && data->menu) { region = data->menu->region; @@ -8564,7 +8574,8 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *reg button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER); if (event->alt && but->active) { - /* display tooltips if holding alt on mouseover when tooltips are off in prefs */ + /* Display tool-tips if holding Alt on mouse-over when tool-tips are disabled in the + * preferences. */ but->active->tooltip_force = true; } } @@ -8606,7 +8617,7 @@ void ui_but_activate_event(bContext *C, ARegion *region, uiBut *but) * Simulate moving the mouse over a button (or navigating to it with arrow keys). * * exported so menus can start with a highlighted button, - * even if the mouse isnt over it + * even if the mouse isn't over it */ void ui_but_activate_over(bContext *C, ARegion *region, uiBut *but) { @@ -8786,7 +8797,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->x != event->prevx || event->y != event->prevy) { - /* re-enable tooltip on mouse move */ + /* Re-enable tool-tip on mouse move. */ ui_blocks_set_tooltips(region, true); button_tooltip_timer_reset(C, but); } @@ -8810,7 +8821,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) break; } /* XXX hardcoded keymap check... but anyway, - * while view changes, tooltips should be removed */ + * while view changes, tool-tips should be removed */ case WHEELUPMOUSE: case WHEELDOWNMOUSE: case MIDDLEMOUSE: @@ -9513,7 +9524,7 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock /* pass, skip for dialogs */ } else if (!ui_region_contains_point_px(but->active->region, event->x, event->y)) { - /* pass, needed to click-exit outside of non-flaoting menus */ + /* Pass, needed to click-exit outside of non-floating menus. */ ui_region_auto_open_clear(but->active->region); } else if ((!ELEM(event->type, MOUSEMOVE, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN)) && @@ -10135,7 +10146,7 @@ static int ui_handle_menu_event(bContext *C, ui_mouse_motion_towards_check(block, menu, &event->x, is_parent_inside == false); - /* check for all parent rects, enables arrowkeys to be used */ + /* Check for all parent rects, enables arrow-keys to be used. */ for (saferct = block->saferct.first; saferct; saferct = saferct->next) { /* for mouse move we only check our own rect, for other * events we check all preceding block rects too to make @@ -10409,7 +10420,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle } } - /* check pie velociy here if gesture has ended */ + /* Check pie velocity here if gesture has ended. */ if (block->pie_data.flags & UI_PIE_GESTURE_END_WAIT) { float len_sq = 10; @@ -10735,7 +10746,7 @@ static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(use } } - /* re-enable tooltips */ + /* Re-enable tool-tips. */ if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) { ui_blocks_set_tooltips(region, true); } @@ -10832,7 +10843,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE } } - /* re-enable tooltips */ + /* Re-enable tool-tips. */ if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) { ui_blocks_set_tooltips(region, true); } @@ -10926,7 +10937,7 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata) WM_event_add_mousemove(win); } else { - /* re-enable tooltips */ + /* Re-enable tool-tips */ if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) { ui_blocks_set_tooltips(menu->region, true); } @@ -10936,7 +10947,7 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata) ui_apply_but_funcs_after(C); if (reset_pie) { - /* reaqcuire window in case pie invalidates it somehow */ + /* Reacquire window in case pie invalidates it somehow. */ wmWindow *win = CTX_wm_window(C); if (win) { diff --git a/source/blender/editors/interface/interface_icons_event.c b/source/blender/editors/interface/interface_icons_event.c index 223fcbfd45b..3962ff6a702 100644 --- a/source/blender/editors/interface/interface_icons_event.c +++ b/source/blender/editors/interface/interface_icons_event.c @@ -118,7 +118,15 @@ void icon_draw_rect_input(float x, UI_GetThemeColor4fv(TH_TEXT, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_aa( - false, (int)x - U.pixelsize, (int)y, (int)(x + w), (int)(y + h), 3.0f * U.pixelsize, color); + &(const rctf){ + .xmin = (int)x - U.pixelsize, + .xmax = (int)(x + w), + .ymin = (int)y, + .ymax = (int)(y + h), + }, + false, + 3.0f * U.pixelsize, + color); const enum { UNIX, diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index f4e68ca3909..6a921f3f541 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -525,7 +525,7 @@ struct uiBlock { /** for doing delayed */ int bounds, minbounds; - /** pulldowns, to detect outside, can differ per case how it is created */ + /** pull-downs, to detect outside, can differ per case how it is created. */ rctf safety; /** uiSafetyRct list */ ListBase saferct; @@ -659,7 +659,7 @@ void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]); /* interface_regions.c */ struct uiKeyNavLock { - /* set when we're using keyinput */ + /* Set when we're using key-input. */ bool is_keynav; /* only used to check if we've moved the cursor */ int event_xy[2]; @@ -756,7 +756,7 @@ uiBlock *ui_block_func_COLOR(struct bContext *C, uiPopupBlockHandle *handle, voi ColorPicker *ui_block_colorpicker_create(struct uiBlock *block); /* interface_region_search.c */ -/* Searchbox for string button */ +/* Search-box for string button. */ struct ARegion *ui_searchbox_create_generic(struct bContext *C, struct ARegion *butregion, uiButSearch *search_but); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 3281b8de920..fef243d7193 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2642,7 +2642,7 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname static void search_id_collection(StructRNA *ptype, PointerRNA *r_ptr, PropertyRNA **r_prop) { /* look for collection property in Main */ - /* Note: using global Main is OK-ish here, UI shall not access other Mains anyay... */ + /* NOTE: using global Main is OK-ish here, UI shall not access other Mains anyway. */ RNA_main_pointer_create(G_MAIN, r_ptr); *r_prop = NULL; @@ -2821,7 +2821,7 @@ void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt) UI_menutype_draw(C, mt, layout); - /* menus are created flipped (from event handling pov) */ + /* Menus are created flipped (from event handling point of view). */ layout->root->block->flag ^= UI_BLOCK_IS_FLIP; } diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index e5aa0665a16..05a2a6ef29b 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -901,7 +901,7 @@ bool UI_context_copy_to_selected_list(bContext *C, MEM_freeN(link); } else { - /* avoid prepending 'data' to the path */ + /* Avoid prepending 'data' to the path. */ RNA_id_pointer_create(id_data, &link->ptr); } diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index bf140eb1692..7343417137a 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -926,9 +926,9 @@ bool UI_panel_matches_search_filter(const Panel *panel) /** * Set the flag telling the panel to use its search result status for its expansion. */ -static void panel_set_expansion_from_seach_filter_recursive(const bContext *C, - Panel *panel, - const bool use_search_closed) +static void panel_set_expansion_from_search_filter_recursive(const bContext *C, + Panel *panel, + const bool use_search_closed) { /* This has to run on inactive panels that may not have a type, * but we can prevent running on header-less panels in some cases. */ @@ -939,21 +939,21 @@ static void panel_set_expansion_from_seach_filter_recursive(const bContext *C, LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { /* Don't check if the sub-panel is active, otherwise the * expansion won't be reset when the parent is closed. */ - panel_set_expansion_from_seach_filter_recursive(C, child_panel, use_search_closed); + panel_set_expansion_from_search_filter_recursive(C, child_panel, use_search_closed); } } /** * Set the flag telling every panel to override its expansion with its search result status. */ -static void region_panels_set_expansion_from_seach_filter(const bContext *C, - ARegion *region, - const bool use_search_closed) +static void region_panels_set_expansion_from_search_filter(const bContext *C, + ARegion *region, + const bool use_search_closed) { LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { /* Don't check if the panel is active, otherwise the expansion won't * be correct when switching back to tab after exiting search. */ - panel_set_expansion_from_seach_filter_recursive(C, panel, use_search_closed); + panel_set_expansion_from_search_filter_recursive(C, panel, use_search_closed); } set_panels_list_data_expand_flag(C, region); } @@ -1121,13 +1121,16 @@ static void panel_draw_highlight_border(const Panel *panel, float color[4]; UI_GetThemeColor4fv(TH_SELECT_ACTIVE, color); - UI_draw_roundbox_4fv(false, - rect->xmin, - UI_panel_is_closed(panel) ? header_rect->ymin : rect->ymin, - rect->xmax, - header_rect->ymax, - radius, - color); + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = rect->xmin, + .xmax = rect->xmax, + .ymin = UI_panel_is_closed(panel) ? header_rect->ymin : rect->ymin, + .ymax = header_rect->ymax, + }, + false, + radius, + color); } static void panel_draw_aligned_widgets(const uiStyle *style, @@ -1253,13 +1256,16 @@ static void panel_draw_aligned_backdrop(const Panel *panel, float color[4]; UI_GetThemeColor4fv(TH_PANEL_SUB_BACK, color); /* Change the width a little bit to line up with sides. */ - UI_draw_roundbox_aa(true, - rect->xmin + U.pixelsize, - rect->ymin + U.pixelsize, - rect->xmax - U.pixelsize, - rect->ymax, - box_wcol->roundness * U.widget_unit, - color); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = rect->xmin + U.pixelsize, + .xmax = rect->xmax - U.pixelsize, + .ymin = rect->ymin + U.pixelsize, + .ymax = rect->ymax, + }, + true, + box_wcol->roundness * U.widget_unit, + color); } else { immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); @@ -1333,7 +1339,7 @@ void ui_draw_aligned_panel(const uiStyle *style, { const Panel *panel = block->panel; - /* Add 0.001f to prevent flicker frpm float inaccuracy. */ + /* Add 0.001f to prevent flicker from float inaccuracy. */ const rcti header_rect = { rect->xmin, rect->xmax, @@ -1544,20 +1550,26 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) { /* Draw filled rectangle and outline for tab. */ UI_draw_roundbox_corner_set(roundboxtype); - UI_draw_roundbox_4fv(true, - rct->xmin, - rct->ymin, - rct->xmax, - rct->ymax, - tab_curve_radius, - is_active ? theme_col_tab_active : theme_col_tab_inactive); - UI_draw_roundbox_4fv(false, - rct->xmin, - rct->ymin, - rct->xmax, - rct->ymax, - tab_curve_radius, - theme_col_tab_outline); + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = rct->xmin, + .xmax = rct->xmax, + .ymin = rct->ymin, + .ymax = rct->ymax, + }, + true, + tab_curve_radius, + is_active ? theme_col_tab_active : theme_col_tab_inactive); + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = rct->xmin, + .xmax = rct->xmax, + .ymin = rct->ymin, + .ymax = rct->ymax, + }, + false, + tab_curve_radius, + theme_col_tab_outline); /* Disguise the outline on one side to join the tab to the panel. */ pos = GPU_vertformat_attr_add( @@ -1911,10 +1923,10 @@ void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y) const bool region_search_filter_active = region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE; if (properties_space_needs_realign(area, region)) { - region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active); + region_panels_set_expansion_from_search_filter(C, region, region_search_filter_active); } else if (region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) { - region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active); + region_panels_set_expansion_from_search_filter(C, region, region_search_filter_active); } if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) { @@ -2354,7 +2366,7 @@ static int ui_handle_panel_category_cycling(const wmEvent *event, PanelCategoryDyn *pc_dyn = UI_panel_category_find(region, category); if (LIKELY(pc_dyn)) { if (is_mousewheel) { - /* We can probably get rid of this and only allow ctrl-tabbing. */ + /* We can probably get rid of this and only allow Ctrl-Tabbing. */ pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev; } else { diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c index d047d5421d7..81c627816b9 100644 --- a/source/blender/editors/interface/interface_region_menu_pie.c +++ b/source/blender/editors/interface/interface_region_menu_pie.c @@ -392,7 +392,7 @@ void ui_pie_menu_level_create(uiBlock *block, EnumPropertyItem *remaining = MEM_mallocN(array_size + sizeof(EnumPropertyItem), "pie_level_item_array"); memcpy(remaining, items + totitem_parent, array_size); - /* a NULL terminating sentinal element is required */ + /* A NULL terminating sentinel element is required. */ memset(&remaining[totitem_remain], 0, sizeof(EnumPropertyItem)); /* yuk, static... issue is we can't reliably free this without doing dangerous changes */ diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index 93e3dbb2cc8..3228e9741bb 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -413,12 +413,11 @@ static void ui_block_region_draw(const bContext *C, ARegion *region) /** * Use to refresh centered popups on screen resizing (for splash). */ -static void ui_block_region_popup_window_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void ui_block_region_popup_window_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + switch (wmn->category) { case NC_WINDOW: { switch (wmn->action) { @@ -540,7 +539,7 @@ static void ui_popup_block_remove(bContext *C, uiPopupBlockHandle *handle) CTX_wm_window_set(C, win); ui_region_temp_remove(C, screen, handle->region); - /* Reset context (area and region were NULL'ed when chaning context window). */ + /* Reset context (area and region were NULL'ed when changing context window). */ CTX_wm_window_set(C, ctx_win); CTX_wm_area_set(C, ctx_area); CTX_wm_region_set(C, ctx_region); diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index 816162e9aa2..d1d4290bd11 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -289,7 +289,7 @@ int ui_searchbox_find_index(ARegion *region, const char *name) return UI_search_items_find_index(&data->items, name); } -/* x and y in screencoords */ +/* x and y in screen-coords. */ bool ui_searchbox_inside(ARegion *region, int x, int y) { uiSearchboxData *data = region->regiondata; @@ -347,9 +347,20 @@ static struct ARegion *wm_searchbox_tooltip_init(struct bContext *C, } uiButSearch *search_but = (uiButSearch *)but; - if (search_but->item_tooltip_fn) { - return search_but->item_tooltip_fn(C, region, search_but->arg, search_but->item_active); + if (!search_but->item_tooltip_fn) { + continue; } + + ARegion *searchbox_region = UI_region_searchbox_region_get(region); + uiSearchboxData *data = searchbox_region->regiondata; + + BLI_assert(data->items.pointers[data->active] == search_but->item_active); + + rcti rect; + ui_searchbox_butrect(&rect, data, data->active); + + return search_but->item_tooltip_fn( + C, region, &rect, search_but->arg, search_but->item_active); } } return NULL; @@ -452,8 +463,11 @@ static void ui_searchbox_update_fn(bContext *C, const char *str, uiSearchItems *items) { - wmWindow *win = CTX_wm_window(C); - WM_tooltip_clear(C, win); + /* While the button is in text editing mode (searchbox open), remove tooltips on every update. */ + if (search_but->but.editstr) { + wmWindow *win = CTX_wm_window(C); + WM_tooltip_clear(C, win); + } search_but->items_update_fn(C, search_but->arg, str, items); } @@ -1046,7 +1060,7 @@ void ui_but_search_refresh(uiButSearch *search_but) ui_searchbox_update_fn(but->block->evil_C, search_but, but->drawstr, items); - /* only redalert when we are sure of it, this can miss cases when >10 matches */ + /* Only red-alert when we are sure of it, this can miss cases when >10 matches. */ if (items->totitem == 0) { UI_but_flag_enable(but, UI_BUT_REDALERT); } diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index 2bf63955855..050a14cf574 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -1456,15 +1456,91 @@ ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz) { wmWindow *win = CTX_wm_window(C); const float aspect = 1.0f; - float init_position[2]; + float init_position[2] = {win->eventstate->x, win->eventstate->y}; uiTooltipData *data = ui_tooltip_data_from_gizmo(C, gz); if (data == NULL) { return NULL; } + /* TODO(harley): + * Julian preferred that the gizmo callback return the 3D bounding box + * which we then project to 2D here. Would make a nice improvement. + */ + if (gz->type->screen_bounds_get) { + rcti bounds; + gz->type->screen_bounds_get(C, gz, &bounds); + init_position[0] = bounds.xmin; + init_position[1] = bounds.ymin; + } + + return ui_tooltip_create_with_data(C, data, init_position, NULL, aspect); +} + +static uiTooltipData *ui_tooltip_data_from_search_item_tooltip_data( + const uiSearchItemTooltipData *item_tooltip_data) +{ + uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData"); + + if (item_tooltip_data->description[0]) { + uiTooltipField *field = text_field_add(data, + &(uiTooltipFormat){ + .style = UI_TIP_STYLE_HEADER, + .color_id = UI_TIP_LC_NORMAL, + .is_pad = true, + }); + field->text = BLI_strdup(item_tooltip_data->description); + } + + if (item_tooltip_data->name && item_tooltip_data->name[0]) { + uiTooltipField *field = text_field_add(data, + &(uiTooltipFormat){ + .style = UI_TIP_STYLE_NORMAL, + .color_id = UI_TIP_LC_VALUE, + .is_pad = true, + }); + field->text = BLI_strdup(item_tooltip_data->name); + } + if (item_tooltip_data->hint[0]) { + uiTooltipField *field = text_field_add(data, + &(uiTooltipFormat){ + .style = UI_TIP_STYLE_NORMAL, + .color_id = UI_TIP_LC_NORMAL, + .is_pad = true, + }); + field->text = BLI_strdup(item_tooltip_data->hint); + } + + if (data->fields_len == 0) { + MEM_freeN(data); + return NULL; + } + return data; +} + +/** + * Create a tooltip from search-item tooltip data \a item_tooltip data. + * To be called from a callback set with #UI_but_func_search_set_tooltip(). + * + * \param item_rect: Rectangle of the search item in search region space (#ui_searchbox_butrect()) + * which is passed to the tooltip callback. + */ +ARegion *UI_tooltip_create_from_search_item_generic( + bContext *C, + const ARegion *searchbox_region, + const rcti *item_rect, + const uiSearchItemTooltipData *item_tooltip_data) +{ + uiTooltipData *data = ui_tooltip_data_from_search_item_tooltip_data(item_tooltip_data); + if (data == NULL) { + return NULL; + } + + const float aspect = 1.0f; + const wmWindow *win = CTX_wm_window(C); + float init_position[2]; init_position[0] = win->eventstate->x; - init_position[1] = win->eventstate->y; + init_position[1] = item_rect->ymin + searchbox_region->winrct.ymin - (UI_POPUP_MARGIN / 2); return ui_tooltip_create_with_data(C, data, init_position, NULL, aspect); } diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index a37fb0dfde1..eaefc2c3736 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -341,13 +341,16 @@ void UI_fontstyle_draw_simple_backdrop(const uiFontStyle *fs, const float color[4] = {col_bg[0], col_bg[1], col_bg[2], 0.5f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, - x - margin, - (y + decent) - margin, - x + width + margin, - (y + decent) + height + margin, - margin, - color); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = x - margin, + .xmax = x + width + margin, + .ymin = (y + decent) - margin, + .ymax = (y + decent) + height + margin, + }, + true, + margin, + color); } BLF_position(fs->uifont_id, x, y, 0.0f); diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c index 9f4cd32588d..25cf2e12377 100644 --- a/source/blender/editors/interface/interface_template_search_menu.c +++ b/source/blender/editors/interface/interface_template_search_menu.c @@ -1069,6 +1069,7 @@ static bool ui_search_menu_create_context_menu(struct bContext *C, static struct ARegion *ui_search_menu_create_tooltip(struct bContext *C, struct ARegion *region, + const rcti *UNUSED(item_rect), void *arg, void *active) { diff --git a/source/blender/editors/interface/interface_template_search_operator.c b/source/blender/editors/interface/interface_template_search_operator.c index 21529a97c01..ff0f9a2e5cd 100644 --- a/source/blender/editors/interface/interface_template_search_operator.c +++ b/source/blender/editors/interface/interface_template_search_operator.c @@ -23,11 +23,8 @@ #include <string.h> -#include "DNA_gpencil_modifier_types.h" -#include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "DNA_shader_fx_types.h" #include "DNA_texture_types.h" #include "BLI_alloca.h" diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 003bb110baf..dad8253d101 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -208,6 +208,7 @@ static uiBlock *template_common_search_menu(const bContext *C, void *search_arg, uiButHandleFunc search_exec_fn, void *active_item, + uiButSearchTooltipFn item_tooltip_fn, const int preview_rows, const int preview_cols, float scale) @@ -284,6 +285,7 @@ static uiBlock *template_common_search_menu(const bContext *C, NULL, search_exec_fn, active_item); + UI_but_func_search_set_tooltip(but, item_tooltip_fn); UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); UI_block_direction_set(block, UI_DIR_DOWN); @@ -347,7 +349,7 @@ static bool id_search_allows_id(TemplateID *template_ui, const int flag, ID *id, } } - /* Hide dot-datablocks, but only if filter does not force them visible. */ + /* Hide dot prefixed data-blocks, but only if filter does not force them visible. */ if (U.uiflag & USER_HIDE_DOT) { if ((id->name[2] == '.') && (query[0] != '.')) { return false; @@ -485,6 +487,31 @@ static void id_search_cb_objects_from_scene(const bContext *C, id_search_cb_tagged(C, arg_template, str, items); } +static ARegion *template_ID_search_menu_item_tooltip( + bContext *C, ARegion *region, const rcti *item_rect, void *arg, void *active) +{ + TemplateID *template_ui = arg; + ID *active_id = active; + StructRNA *type = RNA_property_pointer_type(&template_ui->ptr, template_ui->prop); + + uiSearchItemTooltipData tooltip_data = {0}; + + tooltip_data.name = active_id->name + 2; + BLI_snprintf(tooltip_data.description, + sizeof(tooltip_data.description), + TIP_("Choose %s data-block to be assigned to this user"), + RNA_struct_ui_name(type)); + if (ID_IS_LINKED(active_id)) { + BLI_snprintf(tooltip_data.hint, + sizeof(tooltip_data.hint), + TIP_("Source library: %s\n%s"), + active_id->lib->id.name + 2, + active_id->lib->filepath); + } + + return UI_tooltip_create_from_search_item_generic(C, region, item_rect, &tooltip_data); +} + /* ID Search browse menu, open */ static uiBlock *id_search_menu(bContext *C, ARegion *region, void *arg_litem) { @@ -512,6 +539,7 @@ static uiBlock *id_search_menu(bContext *C, ARegion *region, void *arg_litem) &template_ui, template_ID_set_property_exec_fn, active_item_ptr.data, + template_ID_search_menu_item_tooltip, template_ui.prv_rows, template_ui.prv_cols, template_ui.scale); @@ -895,7 +923,7 @@ static void template_ID(const bContext *C, idfrom = template_ui->ptr.owner_id; // lb = template_ui->idlb; - /* Allow opertators to take the ID from context. */ + /* Allow operators to take the ID from context. */ uiLayoutSetContextPointer(layout, "id", &idptr); block = uiLayoutGetBlock(layout); @@ -906,7 +934,7 @@ static void template_ID(const bContext *C, } if (text) { - /* Add label resepecting the separated layout property split state. */ + /* Add label respecting the separated layout property split state. */ uiItemL_respect_property_split(layout, text, ICON_NONE); } @@ -1632,6 +1660,7 @@ static uiBlock *template_search_menu(bContext *C, ARegion *region, void *arg_tem &template_search, template_search_exec_fn, active_ptr.data, + NULL, template_search.preview_rows, template_search.preview_cols, 1.0f); @@ -6802,20 +6831,16 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) width = min_ii((int)(rti->widthfac * width), width); width = max_ii(width, 10 * UI_DPI_FAC); - /* make a box around the report to make it stand out */ UI_block_align_begin(block); - but = uiDefBut( - block, UI_BTYPE_ROUNDBOX, 0, "", 0, 0, UI_UNIT_X + 5, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); - /* set the report's bg color in but->col - UI_BTYPE_ROUNDBOX feature */ - rgba_float_to_uchar(but->col, rti->col); + /* Background for icon. */ but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", - UI_UNIT_X + 5, 0, - UI_UNIT_X + width, + 0, + UI_UNIT_X + (6 * UI_DPI_FAC), UI_UNIT_Y, NULL, 0.0f, @@ -6823,46 +6848,57 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) 0, 0, ""); - rgba_float_to_uchar(but->col, rti->col); + /* UI_BTYPE_ROUNDBOX's bg color is set in but->col. */ + UI_GetThemeColorType4ubv(UI_icon_colorid_from_report_type(report->type), SPACE_INFO, but->col); - UI_block_align_end(block); + /* Background for the rest of the message. */ + but = uiDefBut(block, + UI_BTYPE_ROUNDBOX, + 0, + "", + UI_UNIT_X + (6 * UI_DPI_FAC), + 0, + UI_UNIT_X + width, + UI_UNIT_Y, + NULL, + 0.0f, + 0.0f, + 0, + 0, + ""); - /* icon and report message on top */ - const int icon = UI_icon_from_report_type(report->type); + /* Use icon background at low opacity to highlight, but still contrasting with area TH_TEXT. */ + UI_GetThemeColorType4ubv(UI_icon_colorid_from_report_type(report->type), SPACE_INFO, but->col); + but->col[3] = 64; - /* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report - * to be shown instead of icon when appropriate... - */ + UI_block_align_end(block); UI_block_emboss_set(block, UI_EMBOSS_NONE); - if (reports->list.first != reports->list.last) { - uiDefIconButO(block, - UI_BTYPE_BUT, - "SCREEN_OT_info_log_show", - WM_OP_INVOKE_REGION_WIN, - icon, - 2, - 0, - UI_UNIT_X, - UI_UNIT_Y, - TIP_("Click to see the remaining reports in text block: 'Recent Reports'")); - } - else { - uiDefIconBut( - block, UI_BTYPE_LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); - } + /* The report icon itself. */ + but = uiDefIconButO(block, + UI_BTYPE_BUT, + "SCREEN_OT_info_log_show", + WM_OP_INVOKE_REGION_WIN, + UI_icon_from_report_type(report->type), + (3 * UI_DPI_FAC), + 0, + UI_UNIT_X, + UI_UNIT_Y, + TIP_("Click to see the remaining reports in text block: 'Recent Reports'")); + UI_GetThemeColorType4ubv(UI_text_colorid_from_report_type(report->type), SPACE_INFO, but->col); + but->col[3] = 255; /* This theme color is RBG only, so have to set alpha here. */ + /* The report message. */ but = uiDefButO(block, UI_BTYPE_BUT, "SCREEN_OT_info_log_show", WM_OP_INVOKE_REGION_WIN, report->message, - UI_UNIT_X + 5, + UI_UNIT_X, 0, - UI_UNIT_X + width, + width + UI_UNIT_X, UI_UNIT_Y, "Show in Info Log"); - rgba_float_to_uchar(but->col, rti->col); } void uiTemplateInputStatus(uiLayout *layout, struct bContext *C) diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 958a0bc03cd..f9eba9eeb6f 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -544,15 +544,74 @@ int UI_icon_from_id(ID *id) int UI_icon_from_report_type(int type) { if (type & RPT_ERROR_ALL) { - return ICON_ERROR; + return ICON_CANCEL; } - if (type & RPT_WARNING_ALL) { + else if (type & RPT_WARNING_ALL) { return ICON_ERROR; } - if (type & RPT_INFO_ALL) { + else if (type & RPT_INFO_ALL) { return ICON_INFO; } - return ICON_NONE; + else if (type & RPT_DEBUG_ALL) { + return ICON_SYSTEM; + } + else if (type & RPT_PROPERTY) { + return ICON_OPTIONS; + } + else if (type & RPT_OPERATOR) { + return ICON_CHECKMARK; + } + return ICON_INFO; +} + +int UI_icon_colorid_from_report_type(int type) +{ + if (type & RPT_ERROR_ALL) { + return TH_INFO_ERROR; + } + else if (type & RPT_WARNING_ALL) { + return TH_INFO_WARNING; + } + else if (type & RPT_INFO_ALL) { + return TH_INFO_INFO; + } + else if (type & RPT_DEBUG_ALL) { + return TH_INFO_DEBUG; + } + else if (type & RPT_PROPERTY) { + return TH_INFO_PROPERTY; + } + else if (type & RPT_OPERATOR) { + return TH_INFO_OPERATOR; + } + else { + return TH_INFO_WARNING; + } +} + +int UI_text_colorid_from_report_type(int type) +{ + if (type & RPT_ERROR_ALL) { + return TH_INFO_ERROR_TEXT; + } + else if (type & RPT_WARNING_ALL) { + return TH_INFO_WARNING_TEXT; + } + else if (type & RPT_INFO_ALL) { + return TH_INFO_INFO_TEXT; + } + else if (type & RPT_DEBUG_ALL) { + return TH_INFO_DEBUG_TEXT; + } + else if (type & RPT_PROPERTY) { + return TH_INFO_PROPERTY_TEXT; + } + else if (type & RPT_OPERATOR) { + return TH_INFO_OPERATOR_TEXT; + } + else { + return TH_INFO_WARNING_TEXT; + } } /********************************** Misc **************************************/ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 868f62c89c9..5c59d0edeb5 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1311,7 +1311,7 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb, tria_col[3] = wcol->item[3]; } - /* Draw everything in one drawcall */ + /* Draw everything in one draw-call. */ if (inner_col1[3] || inner_col2[3] || outline_col[3] || emboss_col[3] || tria_col[3] || show_alpha_checkers) { widgetbase_set_uniform_colors_ubv( @@ -1533,25 +1533,22 @@ static void ui_text_clip_right_ex(const uiFontStyle *fstyle, { BLI_assert(str[0]); - /* If the trailing ellipsis takes more than 20% of all available width, just cut the string - * (as using the ellipsis would remove even more useful chars, and we cannot show much - * already!). - */ - if (sep_strwidth / okwidth > 0.2f) { - float tmp; - const int l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, &tmp); - str[l_end] = '\0'; + /* How many BYTES (not characters) of this utf-8 string can fit, along with appended ellipsis. */ + int l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth - sep_strwidth, NULL); + + if (l_end > 0) { + /* At least one character, so clip and add the ellipsis. */ + memcpy(str + l_end, sep, sep_len + 1); /* +1 for trailing '\0'. */ if (r_final_len) { - *r_final_len = (size_t)l_end; + *r_final_len = (size_t)(l_end) + sep_len; } } else { - float tmp; - const int l_end = BLF_width_to_strlen( - fstyle->uifont_id, str, max_len, okwidth - sep_strwidth, &tmp); - memcpy(str + l_end, sep, sep_len + 1); /* +1 for trailing '\0'. */ + /* Otherwise fit as much as we can without adding an ellipsis. */ + l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, NULL); + str[l_end] = '\0'; if (r_final_len) { - *r_final_len = (size_t)(l_end) + sep_len; + *r_final_len = (size_t)l_end; } } } @@ -2352,7 +2349,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, int icon_size = BLI_rcti_size_y(rect); int text_size = 0; - /* This is a bit britle, but avoids adding an 'UI_BUT_HAS_LABEL' flag to but... */ + /* This is a bit brittle, but avoids adding an 'UI_BUT_HAS_LABEL' flag to but... */ if (icon_size > BLI_rcti_size_x(rect)) { /* button is not square, it has extra height for label */ text_size = UI_UNIT_Y; @@ -2413,7 +2410,9 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, rect->xmin += 0.2f * U.widget_unit; } - widget_draw_icon(but, icon, alpha, rect, wcol->text); + /* By default icon is the color of text, but can optionally override with but->col. */ + widget_draw_icon(but, icon, alpha, rect, (but->col[3] != 0) ? but->col : wcol->text); + if (show_menu_icon) { BLI_assert(but->block->content_hints & UI_BLOCK_CONTAINS_SUBMENU_BUT); widget_draw_submenu_tria(but, rect, wcol); @@ -3617,7 +3616,7 @@ static void widget_scroll( rect1.xmin = rect1.xmin + ceilf(fac * (value - but->softmin)); rect1.xmax = rect1.xmin + ceilf(fac * (but->a1 - but->softmin)); - /* ensure minimium size */ + /* Ensure minimum size. */ const float min = BLI_rcti_size_y(rect); if (BLI_rcti_size_x(&rect1) < min) { @@ -3634,7 +3633,7 @@ static void widget_scroll( rect1.ymax = rect1.ymax - ceilf(fac * (value - but->softmin)); rect1.ymin = rect1.ymax - ceilf(fac * (but->a1 - but->softmin)); - /* ensure minimium size */ + /* Ensure minimum size. */ const float min = BLI_rcti_size_x(rect); if (BLI_rcti_size_y(&rect1) < min) { @@ -3671,7 +3670,7 @@ static void widget_progressbar( const float offs = wcol->roundness * BLI_rcti_size_y(&rect_prog); float w = value * BLI_rcti_size_x(&rect_prog); - /* ensure minimium size */ + /* Ensure minimum size. */ w = MAX2(w, offs); rect_bar.xmax = rect_bar.xmin + w; @@ -5224,8 +5223,7 @@ void ui_draw_tooltip_background(const uiStyle *UNUSED(style), uiBlock *UNUSED(bl * * \param state: The state of the button, * typically #UI_ACTIVE, #UI_BUT_DISABLED, #UI_BUT_INACTIVE. - * \param use_sep: When true, characters after the last #UI_SEP_CHAR are right aligned, - * use for displaying key shortcuts. + * \param separator_type: The kind of separator which controls if and how the string is clipped. * \param r_xmax: The right hand position of the text, this takes into the icon, * padding and text clipping when there is not enough room to display the full text. */ @@ -5273,7 +5271,7 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1, INT_MAX) + UI_DPI_ICON_SIZE; } else if (separator_type == UI_MENU_ITEM_SEPARATOR_HINT) { - /* Deterimine max-width for the hint string to leave the name string un-clipped (if there's + /* Determine max-width for the hint string to leave the name string un-clipped (if there's * enough space to display it). */ const int available_width = BLI_rcti_size_x(rect) - padding; diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index f115618c13b..59aee0fde29 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -1895,7 +1895,7 @@ void UI_view2d_scroller_size_get(const View2D *v2d, float *r_x, float *r_y) * * \param r_x, r_y: scale on each axis */ -void UI_view2d_scale_get(View2D *v2d, float *r_x, float *r_y) +void UI_view2d_scale_get(const View2D *v2d, float *r_x, float *r_y) { if (r_x) { *r_x = UI_view2d_scale_get_x(v2d); diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 222f03ee1d8..e234ab5dcdc 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -46,7 +46,7 @@ #include "UI_interface.h" #include "UI_view2d.h" -#include "PIL_time.h" /* USER_ZOOM_CONT */ +#include "PIL_time.h" /* USER_ZOOM_CONTINUE */ /* -------------------------------------------------------------------- */ /** \name Internal Utilities @@ -1106,14 +1106,9 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op) float dx = RNA_float_get(op->ptr, "deltax") / U.dpi_fac; float dy = RNA_float_get(op->ptr, "deltay") / U.dpi_fac; - if (U.uiflag & USER_ZOOM_INVERT) { - dx *= -1; - dy *= -1; - } - /* Check if the 'timer' is initialized, as zooming with the trackpad * never uses the "Continuous" zoom method, and the 'timer' is not initialized. */ - if ((U.viewzoom == USER_ZOOM_CONT) && vzd->timer) { /* XXX store this setting as RNA prop? */ + if ((U.viewzoom == USER_ZOOM_CONTINUE) && vzd->timer) { /* XXX store this setting as RNA prop? */ const double time = PIL_check_seconds_timer(); const float time_step = (float)(time - vzd->timer_lastdraw); @@ -1232,26 +1227,53 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even vzd->lastx = event->prevx; vzd->lasty = event->prevy; - /* As we have only 1D information (magnify value), feed both axes - * with magnify information that is stored in x axis - */ - float fac = 0.01f * (event->prevx - event->x); - float dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f; + float facx, facy; + float zoomfac = 0.01f; + + /* Some view2d's (graph) don't have min/max zoom, or extreme ones. */ + if (v2d->maxzoom > 0.0f) { + zoomfac = clamp_f(0.001f * v2d->maxzoom, 0.001f, 0.01f); + } + if (event->type == MOUSEPAN) { - fac = 0.01f * (event->prevy - event->y); + facx = zoomfac * WM_event_absolute_delta_x(event); + facy = zoomfac * WM_event_absolute_delta_y(event); + + if (U.uiflag & USER_ZOOM_INVERT) { + facx *= -1.0f; + facy *= -1.0f; + } + } + else { /* MOUSEZOOM */ + facx = facy = zoomfac * WM_event_absolute_delta_x(event); + } + + /* Only respect user setting zoom axis if the view does not have any zoom restrictions + * any will be scaled uniformly. */ + if (((v2d->keepzoom & (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y)) == 0) && + (v2d->keepzoom & V2D_KEEPASPECT)) { + if (U.uiflag & USER_ZOOM_HORIZ) { + facy = 0.0f; + } + else { + facx = 0.0f; + } } - float dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f; /* support trackpad zoom to always zoom entirely - the v2d code uses portrait or * landscape exceptions */ if (v2d->keepzoom & V2D_KEEPASPECT) { - if (fabsf(dx) > fabsf(dy)) { - dy = dx; + if (fabsf(facx) > fabsf(facy)) { + facy = facx; } else { - dx = dy; + facx = facy; } } + + const float dx = facx * BLI_rctf_size_x(&v2d->cur); + const float dy = facy * BLI_rctf_size_y(&v2d->cur); + RNA_float_set(op->ptr, "deltax", dx); RNA_float_set(op->ptr, "deltay", dy); @@ -1282,7 +1304,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even /* add temp handler */ WM_event_add_modal_handler(C, op); - if (U.viewzoom == USER_ZOOM_CONT) { + if (U.viewzoom == USER_ZOOM_CONTINUE) { /* needs a timer to continue redrawing */ vzd->timer = WM_event_add_timer(CTX_wm_manager(C), window, TIMER, 0.01f); vzd->timer_lastdraw = PIL_check_seconds_timer(); @@ -1320,19 +1342,13 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event /* x-axis transform */ dist = BLI_rcti_size_x(&v2d->mask) / 2.0f; - len_old[0] = fabsf(vzd->lastx - vzd->region->winrct.xmin - dist); - len_new[0] = fabsf(event->x - vzd->region->winrct.xmin - dist); - - len_old[0] *= zoomfac * BLI_rctf_size_x(&v2d->cur); - len_new[0] *= zoomfac * BLI_rctf_size_x(&v2d->cur); + len_old[0] = zoomfac * fabsf(vzd->lastx - vzd->region->winrct.xmin - dist); + len_new[0] = zoomfac * fabsf(event->x - vzd->region->winrct.xmin - dist); /* y-axis transform */ dist = BLI_rcti_size_y(&v2d->mask) / 2.0f; - len_old[1] = fabsf(vzd->lasty - vzd->region->winrct.ymin - dist); - len_new[1] = fabsf(event->y - vzd->region->winrct.ymin - dist); - - len_old[1] *= zoomfac * BLI_rctf_size_y(&v2d->cur); - len_new[1] *= zoomfac * BLI_rctf_size_y(&v2d->cur); + len_old[1] = zoomfac * fabsf(vzd->lasty - vzd->region->winrct.ymin - dist); + len_new[1] = zoomfac * fabsf(event->y - vzd->region->winrct.ymin - dist); /* Calculate distance */ if (v2d->keepzoom & V2D_KEEPASPECT) { @@ -1343,40 +1359,44 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event dx = len_new[0] - len_old[0]; dy = len_new[1] - len_old[1]; } - } - else { - /* 'continuous' or 'dolly' */ - float fac; - /* x-axis transform */ - fac = zoomfac * (event->x - vzd->lastx); - dx = fac * BLI_rctf_size_x(&v2d->cur); - /* y-axis transform */ - fac = zoomfac * (event->y - vzd->lasty); - dy = fac * BLI_rctf_size_y(&v2d->cur); + dx *= BLI_rctf_size_x(&v2d->cur); + dy *= BLI_rctf_size_y(&v2d->cur); + } + else { /* USER_ZOOM_CONTINUE or USER_ZOOM_DOLLY */ + float facx = zoomfac * (event->x - vzd->lastx); + float facy = zoomfac * (event->y - vzd->lasty); /* Only respect user setting zoom axis if the view does not have any zoom restrictions * any will be scaled uniformly */ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->keepzoom & V2D_KEEPASPECT)) { if (U.uiflag & USER_ZOOM_HORIZ) { - dy = 0; + facy = 0.0f; } else { - dx = 0; + facx = 0.0f; } } - } - /* support zoom to always zoom entirely - the v2d code uses portrait or - * landscape exceptions */ - if (v2d->keepzoom & V2D_KEEPASPECT) { - if (fabsf(dx) > fabsf(dy)) { - dy = dx; - } - else { - dx = dy; + /* support zoom to always zoom entirely - the v2d code uses portrait or + * landscape exceptions */ + if (v2d->keepzoom & V2D_KEEPASPECT) { + if (fabsf(facx) > fabsf(facy)) { + facy = facx; + } + else { + facx = facy; + } } + + dx = facx * BLI_rctf_size_x(&v2d->cur); + dy = facy * BLI_rctf_size_y(&v2d->cur); + } + + if (U.uiflag & USER_ZOOM_INVERT) { + dx *= -1.0f; + dy *= -1.0f; } /* set transform amount, and add current deltas to stored total delta (for redo) */ @@ -1390,7 +1410,7 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event * - Continuous zoom only depends on distance of mouse * to starting point to determine rate of change. */ - if (U.viewzoom != USER_ZOOM_CONT) { /* XXX store this setting as RNA prop? */ + if (U.viewzoom != USER_ZOOM_CONTINUE) { /* XXX store this setting as RNA prop? */ vzd->lastx = event->x; vzd->lasty = event->y; } @@ -2204,7 +2224,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent * scroller_activate_init(C, op, event, in_scroller); v2dScrollerMove *vsm = (v2dScrollerMove *)op->customdata; - /* support for quick jump to location - gtk and qt do this on linux */ + /* Support for quick jump to location - GTK and QT do this on Linux. */ if (event->type == MIDDLEMOUSE) { switch (vsm->scroller) { case 'h': /* horizontal scroller - so only horizontal movement diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 636e6688971..a66f53ea839 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -35,19 +35,16 @@ # include "MEM_guardedalloc.h" -# include "DNA_mesh_types.h" # include "DNA_modifier_types.h" # include "DNA_object_types.h" # include "DNA_scene_types.h" # include "DNA_space_types.h" # include "BKE_context.h" -# include "BKE_global.h" # include "BKE_main.h" # include "BKE_report.h" # include "BLI_listbase.h" -# include "BLI_math_vector.h" # include "BLI_path_util.h" # include "BLI_string.h" # include "BLI_utildefines.h" diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c index b73b8abccfe..1e66a86c8fd 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -26,7 +26,6 @@ #include "DNA_cachefile_types.h" #include "DNA_space_types.h" -#include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_string.h" diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 200786ca99d..2bf975cc4f5 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -29,7 +29,6 @@ # include "BLI_utildefines.h" # include "BKE_context.h" -# include "BKE_global.h" # include "BKE_main.h" # include "BKE_object.h" # include "BKE_report.h" @@ -37,7 +36,6 @@ # include "DEG_depsgraph.h" # include "ED_object.h" -# include "ED_screen.h" # include "RNA_access.h" # include "RNA_define.h" diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c index 4497ca1a379..cb3f9a89e62 100644 --- a/source/blender/editors/lattice/editlattice_select.c +++ b/source/blender/editors/lattice/editlattice_select.c @@ -108,7 +108,7 @@ bool ED_lattice_deselect_all_multi(struct bContext *C) static int lattice_select_random_exec(bContext *C, wmOperator *op) { - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c index 3a5734706f1..3ffbc3712fc 100644 --- a/source/blender/editors/lattice/editlattice_undo.c +++ b/source/blender/editors/lattice/editlattice_undo.c @@ -212,8 +212,11 @@ static bool lattice_undosys_step_encode(struct bContext *C, Main *bmain, UndoSte return true; } -static void lattice_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) +static void lattice_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir UNUSED(dir), + bool UNUSED(is_final)) { LatticeUndoStep *us = (LatticeUndoStep *)us_p; diff --git a/source/blender/editors/lattice/lattice_ops.c b/source/blender/editors/lattice/lattice_ops.c index d5505c00132..3f96b8a303b 100644 --- a/source/blender/editors/lattice/lattice_ops.c +++ b/source/blender/editors/lattice/lattice_ops.c @@ -23,15 +23,10 @@ #include "DNA_scene_types.h" -#include "RNA_access.h" - #include "WM_api.h" -#include "WM_types.h" #include "ED_lattice.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "lattice_intern.h" diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index d7b3d74bc7e..1226cc57359 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -507,6 +507,9 @@ static int add_vertex_handle_cyclic( static int add_vertex_exec(bContext *C, wmOperator *op) { + MaskViewLockState lock_state; + ED_mask_view_lock_state_store(C, &lock_state); + Mask *mask = CTX_data_edit_mask(C); if (mask == NULL) { /* if there's no active mask, create one */ @@ -548,6 +551,8 @@ static int add_vertex_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + return OPERATOR_FINISHED; } @@ -690,6 +695,9 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot) static int create_primitive_from_points( bContext *C, wmOperator *op, const float (*points)[2], int num_points, char handle_type) { + MaskViewLockState lock_state; + ED_mask_view_lock_state_store(C, &lock_state); + ScrArea *area = CTX_wm_area(C); int size = RNA_float_get(op->ptr, "size"); @@ -752,6 +760,8 @@ static int create_primitive_from_points( DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 89fd2fa9b62..d3fa0e93597 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -539,7 +539,7 @@ static void draw_spline_curve(const bContext *C, uint tot_feather_point; float(*feather_points)[2]; - diff_points = BKE_mask_spline_differentiate_with_resolution(spline, &tot_diff_point, resol); + diff_points = BKE_mask_spline_differentiate_with_resolution(spline, resol, &tot_diff_point); if (!diff_points) { return; @@ -550,7 +550,7 @@ static void draw_spline_curve(const bContext *C, } feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution( - spline, &tot_feather_point, resol, (is_fill != false)); + spline, resol, (is_fill != false), &tot_feather_point); /* draw feather */ mask_spline_feather_color_get(mask_layer, spline, is_spline_sel, rgb_tmp); diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 663ae0097ad..f1041d062a8 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -184,3 +184,39 @@ void ED_operatormacros_mask(void) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Lock-to-selection viewport preservation + * \{ */ + +void ED_mask_view_lock_state_store(const bContext *C, MaskViewLockState *state) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + if (space_clip != NULL) { + ED_clip_view_lock_state_store(C, &state->space_clip_state); + } +} + +void ED_mask_view_lock_state_restore_no_jump(const bContext *C, const MaskViewLockState *state) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + if (space_clip != NULL) { + if ((space_clip->flag & SC_LOCK_SELECTION) == 0) { + /* Early output if the editor is not locked to selection. + * Avoids forced dependency graph evaluation here. */ + return; + } + + /* Mask's lock-to-selection requires deformed splines to be evaluated to calculate bounds of + * points after animation has been evaluated. The restore-no-jump type of function does + * calculation of new offset for the view for an updated state of mask to cancel the offset out + * by modifying locked offset. In order to do such calculation mask needs to be evaluated after + * modification by an operator. */ + struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + (void)depsgraph; + + ED_clip_view_lock_state_restore_no_jump(C, &state->space_clip_state); + } +} + +/** \} */ diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index f6990583383..ee1784011ea 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -23,6 +23,8 @@ #pragma once +#include "ED_clip.h" + struct Mask; struct bContext; struct wmOperatorType; @@ -92,6 +94,19 @@ void ED_mask_select_flush_all(struct Mask *mask); bool ED_maskedit_poll(struct bContext *C); bool ED_maskedit_mask_poll(struct bContext *C); +/* Generalized solution for preserving editor viewport when making changes while lock-to-selection + * is enabled. + * Any mask operator can use this API, without worrying that some editors do not have an idea of + * lock-to-selection. */ + +typedef struct MaskViewLockState { + ClipViewLockState space_clip_state; +} MaskViewLockState; + +void ED_mask_view_lock_state_store(const struct bContext *C, MaskViewLockState *state); +void ED_mask_view_lock_state_restore_no_jump(const struct bContext *C, + const MaskViewLockState *state); + /* mask_query.c */ bool ED_mask_find_nearest_diff_point(const struct bContext *C, struct Mask *mask, diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 25cc39bf9a0..14f81520b9a 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -226,13 +226,19 @@ typedef struct SlidePointData { int width, height; float prev_mouse_coord[2]; + + /* Previous clip coordinate which was resolved from mouse position (0, 0). + * Is used to compensate for view offset moving in-between of mouse events when + * lock-to-selection is enabled. */ + float prev_zero_coord[2]; + float no[2]; bool is_curvature_only, is_accurate, is_initial_feather, is_overall_feather; bool is_sliding_new_point; - /* Data needed to restre the state. */ + /* Data needed to restore the state. */ float vec[3][3]; char old_h1, old_h2; @@ -431,6 +437,9 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent * const float threshold = 19; eMaskWhichHandle which_handle; + MaskViewLockState lock_state; + ED_mask_view_lock_state_store(C, &lock_state); + ED_mask_mouse_pos(area, region, event->mval, co); ED_mask_get_size(area, &width, &height); @@ -530,7 +539,15 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent * } customdata->which_handle = which_handle; + { + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + DEG_id_tag_update(&mask->id, 0); + + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + } + ED_mask_mouse_pos(area, region, event->mval, customdata->prev_mouse_coord); + ED_mask_mouse_pos(area, region, (int[2]){0, 0}, customdata->prev_zero_coord); } return customdata; @@ -655,10 +672,24 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event) ED_mask_mouse_pos(area, region, event->mval, co); sub_v2_v2v2(delta, co, data->prev_mouse_coord); + copy_v2_v2(data->prev_mouse_coord, co); + + /* Compensate for possibly moved view offset since the last event. + * The idea is to see how mapping of a fixed and known position did change. */ + { + float zero_coord[2]; + ED_mask_mouse_pos(area, region, (int[2]){0, 0}, zero_coord); + + float zero_delta[2]; + sub_v2_v2v2(zero_delta, zero_coord, data->prev_zero_coord); + sub_v2_v2(delta, zero_delta); + + copy_v2_v2(data->prev_zero_coord, zero_coord); + } + if (data->is_accurate) { mul_v2_fl(delta, 0.2f); } - copy_v2_v2(data->prev_mouse_coord, co); if (data->action == SLIDE_ACTION_HANDLE) { float new_handle[2]; @@ -832,7 +863,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event) if (event->type == data->event_invoke_type && event->val == KM_RELEASE) { Scene *scene = CTX_data_scene(C); - /* dont key sliding feather uw's */ + /* Don't key sliding feather UW's. */ if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == false) { if (IS_AUTOKEY_ON(scene)) { ED_mask_layer_shape_auto_key(data->mask_layer, CFRA); @@ -966,6 +997,9 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(bContext *C, float u, co[2]; BezTriple *next_bezt; + MaskViewLockState lock_state; + ED_mask_view_lock_state_store(C, &lock_state); + ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co); if (!ED_mask_find_nearest_diff_point(C, @@ -1019,7 +1053,7 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(bContext *C, slide_data->bezt_backup = *slide_data->adjust_bezt; slide_data->other_bezt_backup = *slide_data->other_bezt; - /* Let's dont touch other side of the point for now, so set handle to FREE. */ + /* Let's don't touch other side of the point for now, so set handle to FREE. */ if (u < 0.5f) { if (slide_data->adjust_bezt->h2 <= HD_VECT) { slide_data->adjust_bezt->h2 = HD_FREE; @@ -1047,6 +1081,9 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(bContext *C, mask_layer->act_point = point; ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, 0); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + return slide_data; } @@ -1233,7 +1270,7 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve case LEFTMOUSE: case RIGHTMOUSE: if (event->type == slide_data->event_invoke_type && event->val == KM_RELEASE) { - /* dont key sliding feather uw's */ + /* Don't key sliding feather UW's. */ if (IS_AUTOKEY_ON(scene)) { ED_mask_layer_shape_auto_key(slide_data->mask_layer, CFRA); } diff --git a/source/blender/editors/mask/mask_query.c b/source/blender/editors/mask/mask_query.c index cfd57ca3477..401b6eac4f2 100644 --- a/source/blender/editors/mask/mask_query.c +++ b/source/blender/editors/mask/mask_query.c @@ -604,22 +604,37 @@ void ED_mask_point_pos__reverse( *yr = co[1]; } -bool ED_mask_selected_minmax(const bContext *C, float min[2], float max[2]) +static void handle_position_for_minmax(const MaskSplinePoint *point, + eMaskWhichHandle which_handle, + bool handles_as_control_point, + float r_handle[2]) +{ + if (handles_as_control_point) { + copy_v2_v2(r_handle, point->bezt.vec[1]); + return; + } + BKE_mask_point_handle(point, which_handle, r_handle); +} + +bool ED_mask_selected_minmax(const bContext *C, + float min[2], + float max[2], + bool handles_as_control_point) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Mask *mask = CTX_data_edit_mask(C); - /* Use evaluated mask to take animation into account. - * The animation of splies is not "flushed" back to original, so need to explicitly - * sue evaluated datablock here. */ - Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask->id); - bool ok = false; if (mask == NULL) { return ok; } + /* Use evaluated mask to take animation into account. + * The animation of splies is not "flushed" back to original, so need to explicitly + * sue evaluated datablock here. */ + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask->id); + INIT_MINMAX2(min, max); for (MaskLayer *mask_layer = mask_eval->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) { @@ -638,22 +653,29 @@ bool ED_mask_selected_minmax(const bContext *C, float min[2], float max[2]) } if (bezt->f2 & SELECT) { minmax_v2v2_v2(min, max, deform_point->bezt.vec[1]); + ok = true; } + if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) { - BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_STICK, handle); + handle_position_for_minmax( + deform_point, MASK_WHICH_HANDLE_STICK, handles_as_control_point, handle); minmax_v2v2_v2(min, max, handle); + ok = true; } else { if ((bezt->f1 & SELECT) && (bezt->h1 != HD_VECT)) { - BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_LEFT, handle); + handle_position_for_minmax( + deform_point, MASK_WHICH_HANDLE_LEFT, handles_as_control_point, handle); minmax_v2v2_v2(min, max, handle); + ok = true; } if ((bezt->f3 & SELECT) && (bezt->h2 != HD_VECT)) { - BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_RIGHT, handle); + handle_position_for_minmax( + deform_point, MASK_WHICH_HANDLE_RIGHT, handles_as_control_point, handle); minmax_v2v2_v2(min, max, handle); + ok = true; } } - ok = true; } } } diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index cdc6ece1e84..5c369afc4cd 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -214,12 +214,17 @@ static int select_all_exec(bContext *C, wmOperator *op) Mask *mask = CTX_data_edit_mask(C); int action = RNA_enum_get(op->ptr, "action"); + MaskViewLockState lock_state; + ED_mask_view_lock_state_store(C, &lock_state); + ED_mask_select_toggle_all(mask, action); ED_mask_select_flush_all(mask); DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + return OPERATOR_FINISHED; } @@ -261,6 +266,9 @@ static int select_exec(bContext *C, wmOperator *op) eMaskWhichHandle which_handle; const float threshold = 19; + MaskViewLockState lock_state; + ED_mask_view_lock_state_store(C, &lock_state); + RNA_float_get_array(op->ptr, "location", co); point = ED_mask_point_find_nearest( @@ -324,6 +332,8 @@ static int select_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + return OPERATOR_FINISHED; } @@ -364,12 +374,15 @@ static int select_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + return OPERATOR_FINISHED; } if (deselect_all) { /* For clip editor tracks, leave deselect all to clip editor. */ if (!ED_clip_can_select(C)) { ED_mask_deselect_all(C); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); return OPERATOR_FINISHED; } } diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index a5dd29c9d73..d60d83850a5 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -24,7 +24,6 @@ #include "BLI_math.h" #include "BLI_sys_types.h" -#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -42,7 +41,6 @@ #include "ED_mesh.h" #include "ED_object.h" #include "ED_screen.h" -#include "ED_uvedit.h" #include "mesh_intern.h" /* own include */ diff --git a/source/blender/editors/mesh/editmesh_automerge.c b/source/blender/editors/mesh/editmesh_automerge.c index f9910f01f47..2bd5b9b26ca 100644 --- a/source/blender/editors/mesh/editmesh_automerge.c +++ b/source/blender/editors/mesh/editmesh_automerge.c @@ -26,12 +26,9 @@ * - #EDBM_automerge_and_split */ -#include "MEM_guardedalloc.h" - #include "BKE_editmesh.h" #include "DNA_object_types.h" -#include "DNA_scene_types.h" #include "ED_mesh.h" diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 8ea3c883433..66a7b97b440 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -28,11 +28,9 @@ #include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_curveprofile.h" #include "BKE_editmesh.h" #include "BKE_global.h" #include "BKE_layer.h" -#include "BKE_mesh.h" #include "BKE_unit.h" #include "DNA_curveprofile_types.h" @@ -575,7 +573,7 @@ static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event) opdata->shift_value[vmode] = -1.0f; } - /* clamp accordingto value mode, and store value back */ + /* Clamp according to value mode, and store value back. */ CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]); if (vmode == SEGMENTS_VALUE) { opdata->segments = value; diff --git a/source/blender/editors/mesh/editmesh_extrude_spin.c b/source/blender/editors/mesh/editmesh_extrude_spin.c index 7b3fabf07fc..187652ae00f 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin.c @@ -33,17 +33,13 @@ #include "RNA_access.h" #include "RNA_define.h" -#include "RNA_enum_types.h" -#include "WM_api.h" #include "WM_types.h" #include "ED_mesh.h" #include "ED_screen.h" #include "ED_view3d.h" -#include "UI_resources.h" - #include "MEM_guardedalloc.h" #include "mesh_intern.h" /* own include */ diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index f45f48e0e32..1f894ec0f1d 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -210,7 +210,7 @@ typedef struct KnifeTool_OpData { /* run by the UI or not */ bool is_interactive; - /* operatpr options */ + /* Operator options. */ bool cut_through; /* preference, can be modified at runtime (that feature may go) */ bool only_select; /* set on initialization */ bool select_result; /* set on initialization */ @@ -2752,8 +2752,6 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event) } } - view3d_operator_needs_opengl(C); - /* alloc new customdata */ kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), __func__); @@ -2831,7 +2829,6 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) em_setup_viewcontext(C, &kcd->vc); kcd->region = kcd->vc.region; - view3d_operator_needs_opengl(C); ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */ if (kcd->mode == MODE_PANNING) { @@ -3067,8 +3064,6 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug { KnifeTool_OpData *kcd; - view3d_operator_needs_opengl(C); - /* init */ { const bool only_select = false; diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index 3e0bee3c4b8..7d849c096e7 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -81,7 +81,7 @@ typedef struct GeometryExtactParams { /* For extracting Mask. */ float mask_threshold; - /* Common paramenters. */ + /* Common parameters. */ bool add_boundary_loop; int num_smooth_iterations; bool apply_shrinkwrap; @@ -106,7 +106,7 @@ static int geometry_extract_apply(bContext *C, BKE_sculpt_mask_layers_ensure(ob, NULL); - /* Ensures that deformation from sculpt mode is taken into accunt before duplicating the mesh to + /* Ensures that deformation from sculpt mode is taken into account before duplicating the mesh to * extract the geometry. */ CTX_data_ensure_evaluated_depsgraph(C); @@ -385,7 +385,7 @@ static int face_set_extract_modal(bContext *C, wmOperator *op, const wmEvent *ev ED_workspace_status_text(C, NULL); /* This modal operator uses and eyedropper to pick a Face Set from the mesh. This ensures - * that the mouse clicked in a viewport region and its coordinates can be used to raycast + * that the mouse clicked in a viewport region and its coordinates can be used to ray-cast * the PBVH and update the active Face Set ID. */ bScreen *screen = CTX_wm_screen(C); ARegion *region = BKE_screen_find_main_region_at_xy( diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index b5b4802aa78..c8449644dd0 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2205,7 +2205,7 @@ void EDBM_selectmode_set(BMEditMesh *em) } } else if (em->selectmode & SCE_SELECT_FACE) { - /* deselect eges, and select again based on face select */ + /* Deselect edges, and select again based on face select. */ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { BM_edge_select_set(em->bm, eed, false); } @@ -2247,7 +2247,7 @@ void EDBM_selectmode_convert(BMEditMesh *em, /* first tag-to-select, then select --- this avoids a feedback loop */ - /* have to find out what the selectionmode was previously */ + /* Have to find out what the selection-mode was previously. */ if (selectmode_old == SCE_SELECT_VERTEX) { if (bm->totvertsel == 0) { /* pass */ @@ -4573,7 +4573,7 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot) static int edbm_select_random_exec(bContext *C, wmOperator *op) { const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); ViewLayer *view_layer = CTX_data_view_layer(C); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 84f4e35cb0c..de37ddec885 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3905,7 +3905,7 @@ static float bm_edge_seg_isect(const float sco_a[2], x12 = mouse_path[i][0]; y12 = mouse_path[i][1]; - /* Perp. Distance from point to line */ + /* Calculate the distance from point to line. */ if (m2 != MAXSLOPE) { /* sqrt(m2 * m2 + 1); Only looking for change in sign. Skip extra math .*/ dist = (y12 - m2 * x12 - b2); @@ -4010,7 +4010,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) short numcuts = 1; const short mode = RNA_int_get(op->ptr, "type"); - /* allocd vars */ + /* Allocated variables. */ float(*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2]; /* edit-object needed for matrix, and region->regiondata for projections to work */ diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 41bb3faa135..dd51d63961c 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -188,7 +188,7 @@ static void um_arraystore_cd_compact(struct CustomData *cdata, else { bcd_reference_current = NULL; - /* do a full lookup when un-alligned */ + /* Do a full lookup when unaligned. */ if (bcd_reference) { const BArrayCustomData *bcd_iter = bcd_reference; while (bcd_iter) { @@ -766,8 +766,11 @@ static bool mesh_undosys_step_encode(struct bContext *C, struct Main *bmain, Und return true; } -static void mesh_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) +static void mesh_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir UNUSED(dir), + bool UNUSED(is_final)) { MeshUndoStep *us = (MeshUndoStep *)us_p; diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 2cf97b7235f..27d73497b49 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -21,7 +21,6 @@ * \ingroup edmesh */ -#include "DNA_modifier_types.h" #include "DNA_scene_types.h" #include "RNA_access.h" @@ -30,9 +29,7 @@ #include "WM_types.h" #include "ED_mesh.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "mesh_intern.h" /* own include */ diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 3b5897de0b0..3450d61337c 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -145,7 +145,7 @@ static void join_mesh_single(Depsgraph *depsgraph, if (ob_src != ob_dst) { float cmat[4][4]; - /* watch this: switch matmul order really goes wrong */ + /* Watch this: switch matrix multiplication order really goes wrong. */ mul_m4_m4m4(cmat, imat, ob_src->obmat); /* transform vertex coordinates into new space */ @@ -733,7 +733,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) BKE_key_sort(key); } - /* Due to dependnecy cycle some other object might access old derived data. */ + /* Due to dependency cycle some other object might access old derived data. */ BKE_object_free_derived_caches(ob); DEG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */ diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c index cbc60bcc031..b817bc3a718 100644 --- a/source/blender/editors/metaball/editmball_undo.c +++ b/source/blender/editors/metaball/editmball_undo.c @@ -187,8 +187,11 @@ static bool mball_undosys_step_encode(struct bContext *C, struct Main *bmain, Un return true; } -static void mball_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) +static void mball_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir UNUSED(dir), + bool UNUSED(is_final)) { MBallUndoStep *us = (MBallUndoStep *)us_p; diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index 094011ebef1..cf453bf0c32 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -483,7 +483,7 @@ void MBALL_OT_select_similar(wmOperatorType *ot) static int select_random_metaelems_exec(bContext *C, wmOperator *op) { const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); ViewLayer *view_layer = CTX_data_view_layer(C); diff --git a/source/blender/editors/metaball/mball_ops.c b/source/blender/editors/metaball/mball_ops.c index 100ca4691ca..a54ec384d8e 100644 --- a/source/blender/editors/metaball/mball_ops.c +++ b/source/blender/editors/metaball/mball_ops.c @@ -29,9 +29,7 @@ #include "WM_types.h" #include "ED_mball.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "mball_intern.h" diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index c6d6b8b16b9..b6b6dcfaa59 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -516,7 +516,7 @@ bool ED_object_add_generic_get_opts(bContext *C, if (RNA_struct_property_is_set(op->ptr, "rotation")) { /* If rotation is set, always use it. Alignment (and corresponding user preference) * can be ignored since this is in world space anyways. - * To not confuse (e.g. on redo), dont set it to ALIGN_WORLD in the op UI though. */ + * To not confuse (e.g. on redo), don't set it to #ALIGN_WORLD in the op UI though. */ *is_view_aligned = false; RNA_float_get_array(op->ptr, "rotation", rot); } @@ -607,7 +607,6 @@ Object *ED_object_add_type_with_obdata(bContext *C, Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - /* For as long scene has editmode... */ { Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); if (obedit != NULL) { @@ -1712,9 +1711,8 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) Object *ob = ED_object_add_type(C, OB_SPEAKER, NULL, 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 - * ready to be moved around to retime the sound and/or make new sound clips - */ + /* To make it easier to start using this immediately in NLA, a default sound clip is created + * ready to be moved around to re-time the sound and/or make new sound clips. */ { /* create new data for NLA hierarchy */ AnimData *adt = BKE_animdata_add_id(&ob->id); @@ -3364,6 +3362,9 @@ static int object_add_named_exec(bContext *C, wmOperator *op) ED_view3d_cursor3d_position(C, mval, false, basen->object->loc); } + /* 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, BA_DESELECT); ED_object_base_select(basen, BA_SELECT); ED_object_base_activate(C, basen); diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 7179cc26fc1..9ec0c625f71 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -1364,7 +1364,7 @@ static int bake(const BakeAPIRender *bkr, highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false); - /* lowpoly to highpoly transformation matrix */ + /* Low-poly to high-poly transformation matrix. */ copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat); invert_m4_m4(highpoly[i].imat, highpoly[i].obmat); diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 4cbb8858bf4..b251e617a4c 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -51,8 +51,6 @@ #include "ED_object.h" -#include "UI_interface.h" - #include "object_intern.h" /* All possible data to transfer. @@ -65,7 +63,7 @@ static const EnumPropertyItem DT_layer_items[] = { 0, "Vertex Group(s)", "Transfer active or all vertex groups"}, -#if 0 /* XXX For now, would like to finish/merge work from 2014 gsoc first. */ +#if 0 /* XXX For now, would like to finish/merge work from 2014 GSOC first. */ {DT_TYPE_SHAPEKEY, "SHAPEKEYS", 0, "Shapekey(s)", "Transfer active or all shape keys"}, #endif /* XXX When SkinModifier is enabled, diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 6350ffb9c77..7e0e52d3874 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -3024,7 +3024,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) i++; } - /* make a copy of ocean to use for baking - threadsafety */ + /* Make a copy of ocean to use for baking - thread-safety. */ struct Ocean *ocean = BKE_ocean_add(); BKE_ocean_init_from_modifier(ocean, omd, omd->resolution); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 964d9898ac0..2124d242ee2 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -25,23 +25,15 @@ #include <stdlib.h> #include "DNA_object_types.h" -#include "DNA_scene_types.h" - -#include "BLI_utildefines.h" #include "BKE_context.h" #include "RNA_access.h" -#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_types.h" #include "ED_object.h" -#include "ED_screen.h" -#include "ED_select_utils.h" - -#include "DEG_depsgraph.h" #include "object_intern.h" diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index acad1b43cbb..5a2ef1c6556 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1790,20 +1790,33 @@ void OBJECT_OT_make_links_scene(wmOperatorType *ot) void OBJECT_OT_make_links_data(wmOperatorType *ot) { static const EnumPropertyItem make_links_items[] = { - {MAKE_LINKS_OBDATA, "OBDATA", 0, "Object Data", ""}, - {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Materials", ""}, - {MAKE_LINKS_ANIMDATA, "ANIMATION", 0, "Animation Data", ""}, - {MAKE_LINKS_GROUP, "GROUPS", 0, "Collection", ""}, - {MAKE_LINKS_DUPLICOLLECTION, "DUPLICOLLECTION", 0, "Instance Collection", ""}, - {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""}, - {MAKE_LINKS_FONTS, "FONTS", 0, "Fonts", ""}, - {MAKE_LINKS_SHADERFX, "EFFECTS", 0, "Effects", ""}, + {MAKE_LINKS_OBDATA, "OBDATA", 0, "Link Object Data", "Replace assigned Object Data"}, + {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Link Materials", "Replace assigned Materials"}, + {MAKE_LINKS_ANIMDATA, + "ANIMATION", + 0, + "Link Animation Data", + "Replace assigned Animation Data"}, + {MAKE_LINKS_GROUP, "GROUPS", 0, "Link Collections", "Replace assigned Collections"}, + {MAKE_LINKS_DUPLICOLLECTION, + "DUPLICOLLECTION", + 0, + "Link Instance Collection", + "Replace assigned Collection Instance"}, + {MAKE_LINKS_FONTS, "FONTS", 0, "Link Fonts to Text", "Replace Text object Fonts"}, + {0, "", 0, NULL, NULL}, + {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Copy Modifiers", "Replace Modifiers"}, + {MAKE_LINKS_SHADERFX, + "EFFECTS", + 0, + "Copy Grease Pencil Effects", + "Replace Grease Pencil Effects"}, {0, NULL, 0, NULL, NULL}, }; /* identifiers */ - ot->name = "Link Data"; - ot->description = "Apply active object links to other selected objects"; + ot->name = "Link/Transfer Data"; + ot->description = "Transfer data from active object to selected objects"; ot->idname = "OBJECT_OT_make_links_data"; /* api callbacks */ @@ -2328,7 +2341,7 @@ void OBJECT_OT_make_local(wmOperatorType *ot) static bool make_override_library_object_overridable_check(Main *bmain, Object *object) { - /* An object is actually overrideable only if it is in at least one local collections. + /* An object is actually overridable only if it is in at least one local collection. * Unfortunately 'direct link' flag is not enough here. */ LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, object)) { diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c index d560d347217..f55ce88b426 100644 --- a/source/blender/editors/object/object_remesh.c +++ b/source/blender/editors/object/object_remesh.c @@ -327,7 +327,7 @@ static void voxel_size_edit_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), const float total_len = len_v3v3(cd->preview_plane[0], cd->preview_plane[1]); const int tot_lines = (int)(total_len / cd->voxel_size); - /* Smoothstep to reduce the alpha of the grid as the line number increases. */ + /* Smooth-step to reduce the alpha of the grid as the line number increases. */ const float a = VOXEL_SIZE_EDIT_MAX_GRIDS_LINES * 0.1f; const float b = VOXEL_SIZE_EDIT_MAX_GRIDS_LINES; const float x = clamp_f((tot_lines - a) / (b - a), 0.0f, 1.0); @@ -738,7 +738,7 @@ static int quadriflow_break_job(void *customdata) return should_break; } -/* called by oceanbake, wmJob sends notifier */ +/** Called by ocean-bake, #wmJob sends notifier. */ static void quadriflow_update_job(void *customdata, float progress, int *cancel) { QuadriFlowJob *qj = customdata; @@ -982,7 +982,7 @@ static int quadriflow_remesh_exec(bContext *C, wmOperator *op) quadriflow_free_job(job); } else { - /* Non blocking call. For when the operator has been called from the gui */ + /* Non blocking call. For when the operator has been called from the GUI. */ job->is_nonblocking_job = true; wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index b36d89dc37a..1e6a7b9f14e 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -317,7 +317,7 @@ bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_ /** * Select and make the target object and bone active. * Switches to Pose mode if in Object mode so the selection is visible. - * Unhides the target bone and bone layer if necessary. + * Un-hides the target bone and bone layer if necessary. * * \returns false if object not in layer, bone not found, or other error */ @@ -1453,7 +1453,7 @@ void OBJECT_OT_select_less(wmOperatorType *ot) static int object_select_random_exec(bContext *C, wmOperator *op) { - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 1bb0246deb5..fd649854d8f 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -36,7 +36,6 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "DNA_curve_types.h" #include "DNA_key_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" @@ -44,7 +43,6 @@ #include "DNA_object_types.h" #include "BKE_context.h" -#include "BKE_curve.h" #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_main.h" diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 0528d64dca9..13c0740bce6 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1394,7 +1394,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) * (all layers are considered without evaluating lock attributes) */ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); /* undo matrix */ invert_m4_m4(inverse_diff_mat, diff_mat); LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { diff --git a/source/blender/editors/object/object_volume.c b/source/blender/editors/object/object_volume.c index 6b46d43e5bf..fbdee00c29c 100644 --- a/source/blender/editors/object/object_volume.c +++ b/source/blender/editors/object/object_volume.c @@ -23,9 +23,6 @@ #include <string.h> -#include "MEM_guardedalloc.h" - -#include "BLI_fileops.h" #include "BLI_listbase.h" #include "BLI_math_base.h" #include "BLI_path_util.h" diff --git a/source/blender/editors/object/object_warp.c b/source/blender/editors/object/object_warp.c index b36a8543d67..4b15385b537 100644 --- a/source/blender/editors/object/object_warp.c +++ b/source/blender/editors/object/object_warp.c @@ -36,7 +36,6 @@ #include "WM_types.h" #include "ED_transverts.h" -#include "ED_view3d.h" #include "object_intern.h" @@ -75,7 +74,7 @@ static void object_warp_transverts_minmax_x(TransVertStore *tvs, for (int i = 0; i < tvs->transverts_tot; i++, tv++) { float val; - /* convert objectspace->viewspace */ + /* Convert object-space to view-space. */ val = dot_m4_v3_row_x(mat_view, tv->loc); min = min_ff(min, val); @@ -123,7 +122,7 @@ static void object_warp_transverts(TransVertStore *tvs, float co[3], co_add[2]; float val, phi; - /* convert objectspace->viewspace */ + /* Convert object-space to view-space. */ mul_v3_m4v3(co, mat_view, tv->loc); sub_v2_v2(co, center_view); @@ -158,7 +157,7 @@ static void object_warp_transverts(TransVertStore *tvs, add_v2_v2(co, co_add); - /* convert viewspace->objectspace */ + /* Convert view-space to object-space. */ add_v2_v2(co, center_view); mul_v3_m4v3(tv->loc, imat_view, co); } @@ -187,7 +186,7 @@ static int object_warp_verts_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* get viewmatrix */ + /* Get view-matrix. */ { PropertyRNA *prop_viewmat = RNA_struct_find_property(op->ptr, "viewmat"); if (RNA_property_is_set(op->ptr, prop_viewmat)) { diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c index 381bf317bee..a761701f60b 100644 --- a/source/blender/editors/physics/dynamicpaint_ops.c +++ b/source/blender/editors/physics/dynamicpaint_ops.c @@ -233,7 +233,7 @@ static int output_toggle_exec(bContext *C, wmOperator *op) /* if type is already enabled, toggle it off */ if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { - int exists = dynamicPaint_outputLayerExists(surface, ob, output); + bool exists = dynamicPaint_outputLayerExists(surface, ob, output); const char *name; if (output == 0) { diff --git a/source/blender/editors/physics/particle_boids.c b/source/blender/editors/physics/particle_boids.c index 22cfa50aee9..9b8622e6eac 100644 --- a/source/blender/editors/physics/particle_boids.c +++ b/source/blender/editors/physics/particle_boids.c @@ -33,7 +33,6 @@ #include "BKE_boids.h" #include "BKE_context.h" #include "BKE_main.h" -#include "BKE_particle.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 8ab25fa74b8..d7e30f2b65c 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -1999,7 +1999,7 @@ static int select_random_exec(bContext *C, wmOperator *op) int p; int k; - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); RNG *rng; @@ -2905,7 +2905,7 @@ static void remove_tagged_keys(Depsgraph *depsgraph, Object *ob, ParticleSystem } } -/************************ subdivide opertor *********************/ +/************************ subdivide operator *********************/ /* works like normal edit mode subdivide, inserts keys between neighboring selected keys */ static void subdivide_particle(PEData *data, int pa_index) @@ -3029,7 +3029,7 @@ void PARTICLE_OT_subdivide(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/************************ remove doubles opertor *********************/ +/************************ remove doubles operator *********************/ static int remove_doubles_exec(bContext *C, wmOperator *op) { @@ -3750,8 +3750,7 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance) } } else { - /* compute position as if hair was standing up straight. - * */ + /* Compute position as if hair was standing up straight. */ float length; copy_v3_v3(co_prev, co); copy_v3_v3(co, key->co); @@ -4566,7 +4565,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) mval[0] = mouse[0]; mval[1] = mouse[1]; - /* disable locking temporatily for disconnected hair */ + /* Disable locking temporarily for disconnected hair. */ if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) { pset->flag &= ~PE_LOCK_FIRST; } @@ -5004,7 +5003,7 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - /* disable locking temporatily for disconnected hair */ + /* Disable locking temporarily for disconnected hair. */ if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) { pset->flag &= ~PE_LOCK_FIRST; } diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c index 77b8d410d81..5d2e0e5b6ef 100644 --- a/source/blender/editors/physics/particle_edit_undo.c +++ b/source/blender/editors/physics/particle_edit_undo.c @@ -247,7 +247,7 @@ static bool particle_undosys_step_encode(struct bContext *C, static void particle_undosys_step_decode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, - int UNUSED(dir), + const eUndoStepDir UNUSED(dir), bool UNUSED(is_final)) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 32d2e39d6f6..a94a2b9b764 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -33,21 +33,17 @@ #include "DNA_object_types.h" #include "BLI_blenlib.h" -#include "BLI_math.h" #include "BLI_path_util.h" #include "BLI_utildefines.h" #include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_customdata.h" #include "BKE_fluid.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_modifier.h" -#include "BKE_object.h" #include "BKE_report.h" -#include "BKE_scene.h" #include "BKE_screen.h" #include "DEG_depsgraph.h" @@ -59,11 +55,9 @@ #include "WM_api.h" #include "WM_types.h" -#include "manta_fluid_API.h" #include "physics_intern.h" /* own include */ #include "DNA_fluid_types.h" -#include "DNA_mesh_types.h" #include "DNA_scene_types.h" #define FLUID_JOB_BAKE_ALL "FLUID_OT_bake_all" diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index eb154b97eb0..f5b80679689 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -23,14 +23,9 @@ #include <stdlib.h> -#include "RNA_access.h" - #include "WM_api.h" -#include "WM_types.h" -#include "ED_object.h" #include "ED_physics.h" -#include "ED_select_utils.h" #include "physics_intern.h" /* own include */ diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index 1d5903bf417..ea8a4ce2a79 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -34,7 +34,6 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_layer.h" -#include "BKE_particle.h" #include "BKE_pointcache.h" #include "DEG_depsgraph.h" diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index 4fd304ea71d..81a8b57776b 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -34,9 +34,7 @@ #include "BLT_translation.h" -#include "BKE_collection.h" #include "BKE_context.h" -#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_report.h" #include "BKE_rigidbody.h" diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 10cf4131584..50ba5907703 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -43,14 +43,10 @@ #include "DNA_userdef_types.h" #include "DNA_view3d_types.h" -#include "BKE_blender_undo.h" -#include "BKE_blender_version.h" -#include "BKE_camera.h" #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_image.h" -#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_node.h" @@ -58,19 +54,15 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_undo_system.h" #include "DEG_depsgraph.h" #include "WM_api.h" #include "WM_types.h" -#include "ED_object.h" #include "ED_render.h" #include "ED_screen.h" -#include "ED_undo.h" #include "ED_util.h" -#include "ED_view3d.h" #include "BIF_glutil.h" @@ -85,8 +77,6 @@ #include "SEQ_relations.h" -#include "BLO_undofile.h" - #include "render_intern.h" /* Render Callbacks */ @@ -1098,7 +1088,7 @@ void RENDER_OT_render(wmOperatorType *ot) ot->cancel = screen_render_cancel; ot->exec = screen_render_exec; - /* this isn't needed, causes failer in background mode */ + /* This isn't needed, causes failure in background mode. */ #if 0 ot->poll = ED_operator_screenactive; #endif diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 546156e3406..6744461b2f2 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -363,7 +363,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R } } else { - /* shouldnt suddenly give errors mid-render but possible */ + /* shouldn't suddenly give errors mid-render but possible */ char err_out[256] = "unknown"; ImBuf *ibuf_view; const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL; diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 6cf8515bdbb..4e766841c24 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -200,6 +200,11 @@ static bool check_engine_supports_preview(Scene *scene) return (type->flag & RE_USE_PREVIEW) != 0; } +static bool preview_method_is_render(int pr_method) +{ + return ELEM(pr_method, PR_ICON_RENDER, PR_BUTS_RENDER, PR_NODE_RENDER); +} + void ED_preview_free_dbase(void) { if (G_pr_main) { @@ -1179,7 +1184,7 @@ static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect) return; } - /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */ + /* Waste of cpu cycles... but the imbuf API has no other way to scale fast (ton). */ ima = IMB_dupImBuf(ibuf); if (!ima) { @@ -1352,13 +1357,12 @@ static void common_preview_startjob(void *customdata, */ static void other_id_types_preview_render(IconPreview *ip, IconPreviewSize *cur_size, - const bool is_deferred, + const int pr_method, short *stop, short *do_update, float *progress) { ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview"); - const bool is_render = !is_deferred; /* These types don't use the ShaderPreview mess, they have their own types and functions. */ BLI_assert(!ip->id || !ELEM(GS(ip->id->name), ID_OB)); @@ -1368,7 +1372,7 @@ static void other_id_types_preview_render(IconPreview *ip, sp->owner = ip->owner; sp->sizex = cur_size->sizex; sp->sizey = cur_size->sizey; - sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED; + sp->pr_method = pr_method; sp->pr_rect = cur_size->rect; sp->id = ip->id; sp->id_copy = ip->id_copy; @@ -1376,7 +1380,7 @@ static void other_id_types_preview_render(IconPreview *ip, sp->own_id_copy = false; Material *ma = NULL; - if (is_render) { + if (sp->pr_method == PR_ICON_RENDER) { BLI_assert(ip->id); /* grease pencil use its own preview file */ @@ -1424,6 +1428,8 @@ static void icon_preview_startjob_all_sizes(void *customdata, for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) { PreviewImage *prv = ip->owner; + /* Is this a render job or a deferred loading job? */ + const int pr_method = (prv->tag & PRV_TAG_DEFFERED) ? PR_ICON_DEFERRED : PR_ICON_RENDER; if (*stop) { break; @@ -1434,7 +1440,7 @@ static void icon_preview_startjob_all_sizes(void *customdata, continue; } - if (!check_engine_supports_preview(ip->scene)) { + if (preview_method_is_render(pr_method) && !check_engine_supports_preview(ip->scene)) { continue; } @@ -1450,8 +1456,7 @@ static void icon_preview_startjob_all_sizes(void *customdata, object_preview_render(ip, cur_size); } else { - other_id_types_preview_render( - ip, cur_size, (prv->tag & PRV_TAG_DEFFERED), stop, do_update, progress); + other_id_types_preview_render(ip, cur_size, pr_method, stop, do_update, progress); } } } @@ -1634,7 +1639,7 @@ void ED_preview_shader_job(const bContext *C, /* Use workspace render only for buttons Window, * since the other previews are related to the datablock. */ - if (!check_engine_supports_preview(scene)) { + if (preview_method_is_render(method) && !check_engine_supports_preview(scene)) { return; } diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 499ffac6028..4ed1cbd60a5 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -25,7 +25,6 @@ #include "DNA_light_types.h" #include "DNA_material_types.h" -#include "DNA_meshdata_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -33,7 +32,6 @@ #include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" -#include "DNA_workspace_types.h" #include "DNA_world_types.h" #include "DRW_engine.h" @@ -44,13 +42,11 @@ #include "BKE_context.h" #include "BKE_icons.h" -#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_node.h" #include "BKE_paint.h" #include "BKE_scene.h" -#include "BKE_workspace.h" #include "RE_engine.h" #include "RE_pipeline.h" @@ -65,8 +61,6 @@ #include "WM_api.h" -#include "render_intern.h" /* own include */ - #include <stdio.h> /***************************** Render Engines ********************************/ diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 581169d823e..2c71345699f 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -141,13 +141,15 @@ void ED_region_pixelspace(ARegion *region) } /* only exported for WM */ -void ED_region_do_listen( - wmWindow *win, ScrArea *area, ARegion *region, wmNotifier *note, const Scene *scene) +void ED_region_do_listen(wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *notifier = params->notifier; + /* generic notes first */ - switch (note->category) { + switch (notifier->category) { case NC_WM: - if (note->data == ND_FILEREAD) { + if (notifier->data == ND_FILEREAD) { ED_region_tag_redraw(region); } break; @@ -157,16 +159,16 @@ void ED_region_do_listen( } if (region->type && region->type->listener) { - region->type->listener(win, area, region, note, scene); + region->type->listener(params); } } /* only exported for WM */ -void ED_area_do_listen(wmWindow *win, ScrArea *area, wmNotifier *note, Scene *scene) +void ED_area_do_listen(wmSpaceTypeListenerParams *params) { /* no generic notes? */ - if (area->type && area->type->listener) { - area->type->listener(win, area, note, scene); + if (params->area->type && params->area->type->listener) { + params->area->type->listener(params); } } @@ -289,7 +291,15 @@ static void region_draw_azone_tab_arrow(ScrArea *area, ARegion *region, AZone *a float alpha = WM_region_use_viewport(area, region) ? 0.6f : 0.4f; const float color[4] = {0.05f, 0.05f, 0.05f, alpha}; UI_draw_roundbox_aa( - true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, color); + &(const rctf){ + .xmin = (float)az->x1, + .xmax = (float)az->x2, + .ymin = (float)az->y1, + .ymax = (float)az->y2, + }, + true, + 4.0f, + color); draw_azone_arrow((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, az->edge); } @@ -373,7 +383,16 @@ static void region_draw_status_text(ScrArea *area, ARegion *region) float color[4] = {0.0f, 0.0f, 0.0f, 0.5f}; UI_GetThemeColor3fv(TH_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, x1, y1, x2, y2, 4.0f, color); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = x1, + .xmax = x2, + .ymin = y1, + .ymax = y2, + }, + true, + 4.0f, + color); UI_FontThemeColor(fontid, TH_TEXT); } @@ -418,16 +437,13 @@ void ED_area_do_msg_notify_tag_refresh( ED_area_tag_refresh(area); } -void ED_area_do_mgs_subscribe_for_tool_header( - /* Follow ARegionType.message_subscribe */ - const struct bContext *UNUSED(C), - struct WorkSpace *workspace, - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +/* Follow ARegionType.message_subscribe */ +void ED_area_do_mgs_subscribe_for_tool_header(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + WorkSpace *workspace = params->workspace; + ARegion *region = params->region; + BLI_assert(region->regiontype == RGN_TYPE_TOOL_HEADER); wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, @@ -438,16 +454,12 @@ void ED_area_do_mgs_subscribe_for_tool_header( mbus, &workspace->id, workspace, WorkSpace, tools, &msg_sub_value_region_tag_redraw); } -void ED_area_do_mgs_subscribe_for_tool_ui( - /* Follow ARegionType.message_subscribe */ - const struct bContext *UNUSED(C), - struct WorkSpace *workspace, - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +void ED_area_do_mgs_subscribe_for_tool_ui(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + WorkSpace *workspace = params->workspace; + ARegion *region = params->region; + BLI_assert(region->regiontype == RGN_TYPE_UI); const char *panel_category_tool = "Tool"; const char *category = UI_panel_category_active_get(region, false); @@ -634,7 +646,16 @@ void ED_region_do_draw(bContext *C, ARegion *region) WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_region_tag_redraw, __func__); } - ED_region_message_subscribe(C, workspace, scene, screen, area, region, mbus); + wmRegionMessageSubscribeParams message_subscribe_params = { + .context = C, + .message_bus = mbus, + .workspace = workspace, + .scene = scene, + .screen = screen, + .area = area, + .region = region, + }; + ED_region_message_subscribe(&message_subscribe_params); } } @@ -4027,14 +4048,12 @@ void ED_region_cache_draw_cached_segments( /** * Generate subscriptions for this region. */ -void ED_region_message_subscribe(bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +void ED_region_message_subscribe(wmRegionMessageSubscribeParams *params) { + ARegion *region = params->region; + const bContext *C = params->context; + struct wmMsgBus *mbus = params->message_bus; + if (region->gizmo_map != NULL) { WM_gizmomap_message_subscribe(C, region->gizmo_map, region, mbus); } @@ -4044,7 +4063,7 @@ void ED_region_message_subscribe(bContext *C, } if (region->type->message_subscribe != NULL) { - region->type->message_subscribe(C, workspace, scene, screen, area, region, mbus); + region->type->message_subscribe(params); } } diff --git a/source/blender/editors/screen/area_utils.c b/source/blender/editors/screen/area_utils.c index 075759f1120..30553bb7f07 100644 --- a/source/blender/editors/screen/area_utils.c +++ b/source/blender/editors/screen/area_utils.c @@ -22,6 +22,8 @@ #include "DNA_userdef_types.h" +#include "BKE_screen.h" + #include "BLI_blenlib.h" #include "BLI_utildefines.h" @@ -32,7 +34,6 @@ #include "ED_screen.h" -#include "UI_interface.h" #include "UI_interface_icons.h" /* -------------------------------------------------------------------- */ @@ -42,14 +43,11 @@ /** * Callback for #ARegionType.message_subscribe */ -void ED_region_generic_tools_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +void ED_region_generic_tools_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 33b918e6d4d..a88afecd064 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -57,11 +57,12 @@ static void immDrawPixelsTexSetupAttributes(IMMDrawPixelsTexState *state) vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); } -/* To be used before calling immDrawPixelsTex - * Default shader is GPU_SHADER_2D_IMAGE_COLOR - * You can still set uniforms with : - * GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "name"), 0); - * */ +/** + * To be used before calling #immDrawPixelsTex + * Default shader is #GPU_SHADER_2D_IMAGE_COLOR + * You can still set uniforms with: + * `GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "name"), 0);` + */ IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin) { IMMDrawPixelsTexState state; @@ -77,10 +78,11 @@ IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin) return state; } -/* Use the currently bound shader. +/** + * Use the currently bound shader. * - * Use immDrawPixelsTexSetup to bind the shader you - * want before calling immDrawPixelsTex. + * Use #immDrawPixelsTexSetup to bind the shader you + * want before calling #immDrawPixelsTex. * * If using a special shader double check it uses the same * attributes "pos" "texCoord" and uniform "image". @@ -89,7 +91,7 @@ IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin) * * Be also aware that this function unbinds the shader when * it's finished. - * */ + */ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, float x, float y, diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 1dfe606be78..627a67358f2 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -866,7 +866,7 @@ static eContextResult screen_ctx_editable_gpencil_strokes(const bContext *C, LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { if (ED_gpencil_stroke_can_use_direct(area, gps)) { /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c index 6432bdac1b1..1ea64c542f5 100644 --- a/source/blender/editors/screen/screen_draw.c +++ b/source/blender/editors/screen/screen_draw.c @@ -478,7 +478,7 @@ void ED_screen_draw_split_preview(ScrArea *area, const int dir, const float fac) uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - /* splitpoint */ + /* Split-point. */ GPU_blend(GPU_BLEND_ALPHA); immUniformColor4ub(255, 255, 255, 100); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index be52874ed0b..c25b572d200 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -871,6 +871,11 @@ static void screen_global_area_refresh(wmWindow *win, const short height_min, const short height_max) { + /* Full-screens shouldn't have global areas. Don't touch them. */ + if (screen->state == SCREENFULL) { + return; + } + ScrArea *area = NULL; LISTBASE_FOREACH (ScrArea *, area_iter, &win->global_areas.areabase) { if (area_iter->spacetype == space_type) { @@ -1019,7 +1024,7 @@ void screen_change_update(bContext *C, wmWindow *win, bScreen *screen) WM_event_add_notifier(C, NC_WINDOW, NULL); WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTSET, layout); - /* makes button hilites work */ + /* Makes button highlights work. */ WM_event_add_mousemove(win); } @@ -1216,7 +1221,7 @@ void ED_screen_full_restore(bContext *C, ScrArea *area) } /** - * \param toggle_area: If this is set, its space data will be swapped with the one of the new emtpy + * \param toggle_area: If this is set, its space data will be swapped with the one of the new empty * area, when toggling back it can be swapped back again. * \return The newly created screen with the non-normal area. */ diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h index a03e65d8a9d..c51ff559786 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -29,10 +29,10 @@ struct bContextDataResult; /* internal exports only */ -#define AZONESPOTW UI_HEADER_OFFSET /* width of corner azone - max */ -#define AZONESPOTH (0.6f * U.widget_unit) /* height of corner azone */ -#define AZONEFADEIN (5.0f * U.widget_unit) /* when azone is totally visible */ -#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the azone */ +#define AZONESPOTW UI_HEADER_OFFSET /* width of corner #AZone - max */ +#define AZONESPOTH (0.6f * U.widget_unit) /* height of corner #AZone */ +#define AZONEFADEIN (5.0f * U.widget_unit) /* when #AZone is totally visible */ +#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the #AZone */ #define AREAJOINTOLERANCE (1.0f * U.widget_unit) /* Edges must be close to allow joining. */ diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index ca1c75be0a1..244d8c10e4e 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1637,7 +1637,7 @@ static int area_snap_calc_location(const bScreen *screen, /* Thirds. */ 1.0f / 3.0f, 2.0f / 3.0f, - /* Quaters. */ + /* Quarters. */ 1.0f / 4.0f, 3.0f / 4.0f, /* Eighth. */ diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 550913fc8af..7eb08cbabac 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -1755,7 +1755,7 @@ static void paint_cursor_cursor_draw_3d_view_brush_cursor_active(PaintCursorCont else if (brush->cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_RADIAL && brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL) { /* Display the simulation limits if sculpting outside them. */ - /* This does not makes much sense of plane falloff as the falloff is infinte or global. */ + /* This does not makes much sense of plane falloff as the falloff is infinite or global. */ if (len_v3v3(ss->cache->true_location, ss->cache->true_initial_location) > ss->cache->radius * (1.0f + brush->cloth_sim_limit)) { diff --git a/source/blender/editors/sculpt_paint/paint_curve_undo.c b/source/blender/editors/sculpt_paint/paint_curve_undo.c index a8e22f66734..dbe522bf304 100644 --- a/source/blender/editors/sculpt_paint/paint_curve_undo.c +++ b/source/blender/editors/sculpt_paint/paint_curve_undo.c @@ -126,7 +126,7 @@ static bool paintcurve_undosys_step_encode(struct bContext *C, static void paintcurve_undosys_step_decode(struct bContext *UNUSED(C), struct Main *UNUSED(bmain), UndoStep *us_p, - int UNUSED(dir), + const eUndoStepDir UNUSED(dir), bool UNUSED(is_final)) { PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 5c15fd05116..f7c0f7718bb 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -138,7 +138,7 @@ BLI_INLINE uchar f_to_char(const float val) #ifndef PROJ_DEBUG_NOSEAMBLEED /* projectFaceSeamFlags options */ -//#define PROJ_FACE_IGNORE (1<<0) /* When the face is hidden, backfacing or occluded */ +//#define PROJ_FACE_IGNORE (1<<0) /* When the face is hidden, back-facing or occluded. */ //#define PROJ_FACE_INIT (1<<1) /* When we have initialized the faces data */ /* If this face has a seam on any of its edges. */ @@ -150,7 +150,7 @@ BLI_INLINE uchar f_to_char(const float val) # define PROJ_FACE_NOSEAM1 (1 << 5) # define PROJ_FACE_NOSEAM2 (1 << 6) -/* If the seam is completely initialized, including adjecent seams. */ +/* If the seam is completely initialized, including adjacent seams. */ # define PROJ_FACE_SEAM_INIT0 (1 << 8) # define PROJ_FACE_SEAM_INIT1 (1 << 9) # define PROJ_FACE_SEAM_INIT2 (1 << 10) @@ -294,7 +294,7 @@ typedef struct ProjPaintState { /** verts projected into floating point screen space. */ float (*screenCoords)[4]; - /** 2D bounds for mesh verts on the screen's plane (screenspace). */ + /** 2D bounds for mesh verts on the screen's plane (screen-space). */ float screenMin[2]; float screenMax[2]; /** Calculated from screenMin & screenMax. */ @@ -310,10 +310,10 @@ typedef struct ProjPaintState { bool do_stencil_brush; bool do_material_slots; - /** Use raytraced occlusion? - ortherwise will paint right through to the back. */ + /** Use ray-traced occlusion? - otherwise will paint right through to the back. */ bool do_occlude; /** ignore faces with normals pointing away, - * skips a lot of raycasts if your normals are correctly flipped. */ + * skips a lot of ray-casts if your normals are correctly flipped. */ bool do_backfacecull; /** mask out pixels based on their normals. */ bool do_mask_normal; @@ -579,7 +579,7 @@ static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_i /* fast projection bucket array lookup, use the safe version for bound checking */ static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[2]) { - /* If we were not dealing with screenspace 2D coords we could simple do... + /* If we were not dealing with screen-space 2D coords we could simple do... * ps->bucketRect[x + (y*ps->buckets_y)] */ /* please explain? @@ -887,8 +887,8 @@ static int project_paint_occlude_ptv_clip(const float pt[3], return -1; } -/* Check if a screenspace location is occluded by any other faces - * check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison +/* Check if a screen-space location is occluded by any other faces + * check, pixelScreenCo must be in screen-space, its Z-Depth only needs to be used for comparison * and doesn't need to be correct in relation to X and Y coords * (this is the case in perspective view) */ static bool project_bucket_point_occluded(const ProjPaintState *ps, @@ -1514,10 +1514,10 @@ static void project_face_seams_init(const ProjPaintState *ps, } #endif // PROJ_DEBUG_NOSEAMBLEED -/* Converts a UV location to a 3D screenspace location +/* Converts a UV location to a 3D screen-space location * Takes a 'uv' and 3 UV coords, and sets the values of pixelScreenCo * - * This is used for finding a pixels location in screenspace for painting */ + * This is used for finding a pixels location in screen-space for painting */ static void screen_px_from_ortho(const float uv[2], const float v1co[3], const float v2co[3], @@ -1537,7 +1537,7 @@ static void screen_px_from_ortho(const float uv[2], static void screen_px_from_persp(const float uv[2], const float v1co[4], const float v2co[4], - const float v3co[4], /* screenspace coords */ + const float v3co[4], /* screen-space coords */ const float uv1co[2], const float uv2co[2], const float uv3co[2], @@ -1923,7 +1923,7 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps, projPixel->newColor.uint = 0; } - /* screenspace unclamped, we could keep its z and w values but don't need them at the moment */ + /* Screen-space unclamped, we could keep its z and w values but don't need them at the moment. */ if (ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { copy_v3_v3(projPixel->worldCoSS, world_spaceCo); } @@ -2304,14 +2304,14 @@ static bool project_bucket_isect_circle(const float cent[2], return false; } -/* Note for rect_to_uvspace_ortho() and rect_to_uvspace_persp() +/* Note for #rect_to_uvspace_ortho() and #rect_to_uvspace_persp() * in ortho view this function gives good results when bucket_bounds are outside the triangle * however in some cases, perspective view will mess up with faces - * that have minimal screenspace area (viewed from the side). + * that have minimal screen-space area (viewed from the side). * * for this reason its not reliable in this case so we'll use the Simple Barycentric' - * funcs that only account for points inside the triangle. - * however switching back to this for ortho is always an option */ + * functions that only account for points inside the triangle. + * however switching back to this for ortho is always an option. */ static void rect_to_uvspace_ortho(const rctf *bucket_bounds, const float *v1coSS, @@ -2415,9 +2415,10 @@ static bool IsectPT2Df_limit( (area_tri_v2(v1, v2, v3))) < limit; } -/* Clip the face by a bucket and set the uv-space bucket_bounds_uv +/** + * Clip the face by a bucket and set the uv-space bucket_bounds_uv * so we have the clipped UV's to do pixel intersection tests with - * */ + */ static int float_z_sort_flip(const void *p1, const void *p2) { return (((float *)p1)[2] < ((float *)p2)[2] ? 1 : -1); @@ -2516,8 +2517,8 @@ static void project_bucket_clip_face(const bool is_ortho, flip = (((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != is_flip_object) != (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f)); - /* all screenspace points are inside the bucket bounding box, - * this means we don't need to clip and can simply return the UVs */ + /* All screen-space points are inside the bucket bounding box, + * this means we don't need to clip and can simply return the UVs. */ if (flip) { /* facing the back? */ copy_v2_v2(bucket_bounds_uv[0], uv3co); copy_v2_v2(bucket_bounds_uv[1], uv2co); @@ -2634,7 +2635,7 @@ static void project_bucket_clip_face(const bool is_ortho, (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f)); if (inside_face_flag == ISECT_ALL4) { - /* bucket is totally inside the screenspace face, we can safely use weights */ + /* Bucket is totally inside the screen-space face, we can safely use weights. */ if (is_ortho) { rect_to_uvspace_ortho( @@ -2655,7 +2656,7 @@ static void project_bucket_clip_face(const bool is_ortho, * The 2 cases above are where the face is inside the bucket * or the bucket is inside the face. * - * we need to make a convex polyline from the intersection between the screenspace face + * we need to make a convex poly-line from the intersection between the screen-space face * and the bucket bounds. * * There are a number of ways this could be done, currently it just collects all @@ -2996,7 +2997,7 @@ static void project_paint_face_init(const ProjPaintState *ps, /* vert co screen-space, these will be assigned to lt_vtri[0-2] */ const float *v1coSS, *v2coSS, *v3coSS; - /* vertex screenspace coords */ + /* Vertex screen-space coords. */ const float *vCo[3]; float w[3], wco[3]; @@ -3006,9 +3007,9 @@ static void project_paint_face_init(const ProjPaintState *ps, float pixelScreenCo[4]; bool do_3d_mapping = ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D; - /* ispace bounds */ + /* Image-space bounds. */ rcti bounds_px; - /* vars for getting uvspace bounds */ + /* Variables for getting UV-space bounds. */ /* bucket bounds in UV space so we can init pixels only for this face, */ float lt_uv_pxoffset[3][2]; @@ -3206,10 +3207,10 @@ static void project_paint_face_init(const ProjPaintState *ps, /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in perspective view */ float insetCos[3][3]; - /* vertex screenspace coords */ + /* Vertex screen-space coords. */ const float *vCoSS[3]; - /* Store the screenspace coords of the face, + /* Store the screen-space coords of the face, * clipped by the bucket's screen aligned rectangle. */ float bucket_clip_edges[2][2]; float edge_verts_inset_clip[2][3]; @@ -3418,7 +3419,7 @@ static void project_paint_face_init(const ProjPaintState *ps, } /** - * Takes floating point screenspace min/max and + * Takes floating point screen-space min/max and * returns int min/max to be used as indices for ps->bucketRect, ps->bucketFlags */ static void project_paint_bucket_bounds(const ProjPaintState *ps, @@ -3887,7 +3888,7 @@ static void proj_paint_state_cavity_init(ProjPaintState *ps) float no[3]; mul_v3_fl(edges[a], 1.0f / counter[a]); normal_short_to_float_v3(no, mv->no); - /* augment the diffe*/ + /* Augment the difference. */ cavities[a] = saacos(10.0f * dot_v3v3(no, edges[a])) * (float)M_1_PI; } else { @@ -4307,7 +4308,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, slot_last = slot; } - /* don't allow using the same inage for painting and stencilling */ + /* Don't allow using the same image for painting and stenciling. */ if (slot->ima == ps->stencil_ima) { /* Delay continuing the loop until after loop_uvs and bleed faces are initialized. * While this shouldn't be used, face-winding reads all polys. @@ -4337,7 +4338,6 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, continue; } - /* tfbase here should be non-null! */ BLI_assert(mloopuv_base != NULL); if (is_face_sel && tpage) { diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index bacb3b549e3..26e2bcc42cf 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -1073,8 +1073,6 @@ static void sculpt_gesture_trim_calculate_depth(SculptGestureContext *sgcontext) mid_point_depth = ss->gesture_initial_hit ? 0.0f : (trim_operation->depth_back + trim_operation->depth_front) * 0.5f; - - } const float depth_radius = ss->cursor_radius; diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c index 8eb2ebd0f19..8fd5759d695 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -168,8 +168,11 @@ void PAINT_OT_weight_from_bones(wmOperatorType *ot) /** \name Sample Weight Operator * \{ */ -/* sets wp->weight to the closest weight value to vertex */ -/* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */ +/** + * Sets wp->weight to the closest weight value to vertex. + * + * \note we can't sample front-buffer, weight colors are interpolated too unpredictable. + */ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -201,7 +204,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even } else if (ED_mesh_pick_face( C, vc.obact, event->mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) { - /* this relies on knowning the internal worksings of ED_mesh_pick_face_vert() */ + /* This relies on knowing the internal workings of #ED_mesh_pick_face_vert() */ BKE_report( op->reports, RPT_WARNING, "The modifier used does not support deformed locations"); } @@ -604,7 +607,7 @@ static void gradientVert_update(WPGradient_userData *grad_data, int index) Mesh *me = grad_data->me; WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index]; - /* Optionally restrict to assigned verices only. */ + /* Optionally restrict to assigned vertices only. */ if (grad_data->use_vgroup_restrict && ((vs->flag & VGRAD_STORE_DW_EXIST) == 0)) { return; } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index cb5d708908b..d1028e5f542 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -391,13 +391,14 @@ void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visibl case PBVH_FACES: case PBVH_GRIDS: for (int i = 0; i < ss->totfaces; i++) { - if (abs(ss->face_sets[i]) == face_set) { - if (visible) { - ss->face_sets[i] = abs(ss->face_sets[i]); - } - else { - ss->face_sets[i] = -abs(ss->face_sets[i]); - } + if (abs(ss->face_sets[i]) != face_set) { + continue; + } + if (visible) { + ss->face_sets[i] = abs(ss->face_sets[i]); + } + else { + ss->face_sets[i] = -abs(ss->face_sets[i]); } } break; @@ -1057,12 +1058,13 @@ bool SCULPT_is_vertex_inside_brush_radius_symm(const float vertex[3], char symm) { for (char i = 0; i <= symm; ++i) { - if (SCULPT_is_symmetry_iteration_valid(i, symm)) { - float location[3]; - flip_v3_v3(location, br_co, (char)i); - if (len_squared_v3v3(location, vertex) < radius * radius) { - return true; - } + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; + } + float location[3]; + flip_v3_v3(location, br_co, (char)i); + if (len_squared_v3v3(location, vertex) < radius * radius) { + return true; } } return false; @@ -1107,20 +1109,22 @@ void SCULPT_floodfill_add_initial_with_symmetry( /* Add active vertex and symmetric vertices to the queue. */ const char symm = SCULPT_mesh_symmetry_xyz_get(ob); for (char i = 0; i <= symm; ++i) { - if (SCULPT_is_symmetry_iteration_valid(i, symm)) { - int v = -1; - if (i == 0) { - v = index; - } - else if (radius > 0.0f) { - float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; - float location[3]; - flip_v3_v3(location, SCULPT_vertex_co_get(ss, index), i); - v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); - } - if (v != -1) { - SCULPT_floodfill_add_initial(flood, v); - } + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; + } + int v = -1; + if (i == 0) { + v = index; + } + else if (radius > 0.0f) { + float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; + float location[3]; + flip_v3_v3(location, SCULPT_vertex_co_get(ss, index), i); + v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); + } + + if (v != -1) { + SCULPT_floodfill_add_initial(flood, v); } } } @@ -1131,20 +1135,22 @@ void SCULPT_floodfill_add_active( /* Add active vertex and symmetric vertices to the queue. */ const char symm = SCULPT_mesh_symmetry_xyz_get(ob); for (char i = 0; i <= symm; ++i) { - if (SCULPT_is_symmetry_iteration_valid(i, symm)) { - int v = -1; - if (i == 0) { - v = SCULPT_active_vertex_get(ss); - } - else if (radius > 0.0f) { - float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; - float location[3]; - flip_v3_v3(location, SCULPT_active_vertex_co_get(ss), i); - v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); - } - if (v != -1) { - SCULPT_floodfill_add_initial(flood, v); - } + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; + } + int v = -1; + if (i == 0) { + v = SCULPT_active_vertex_get(ss); + } + else if (radius > 0.0f) { + float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; + float location[3]; + flip_v3_v3(location, SCULPT_active_vertex_co_get(ss), i); + v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); + } + + if (v != -1) { + SCULPT_floodfill_add_initial(flood, v); } } } @@ -1161,12 +1167,19 @@ void SCULPT_floodfill_execute( SculptVertexNeighborIter ni; SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) { const int to_v = ni.index; - if (!BLI_BITMAP_TEST(flood->visited_vertices, to_v) && SCULPT_vertex_visible_get(ss, to_v)) { - BLI_BITMAP_ENABLE(flood->visited_vertices, to_v); - if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) { - BLI_gsqueue_push(flood->queue, &to_v); - } + if (BLI_BITMAP_TEST(flood->visited_vertices, to_v)) { + continue; + } + + if (!SCULPT_vertex_visible_get(ss, to_v)) { + continue; + } + + BLI_BITMAP_ENABLE(flood->visited_vertices, to_v); + + if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) { + BLI_gsqueue_push(flood->queue, &to_v); } } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); @@ -1466,40 +1479,42 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata, unode = SCULPT_undo_get_node(data->nodes[n]); } - if (unode) { - PBVHVertexIter vd; - SculptOrigVertData orig_data; + if (!unode) { + return; + } - SCULPT_orig_vert_data_unode_init(&orig_data, data->ob, unode); + PBVHVertexIter vd; + SculptOrigVertData orig_data; - BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) - { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_unode_init(&orig_data, data->ob, unode); - if (orig_data.unode->type == SCULPT_UNDO_COORDS) { - copy_v3_v3(vd.co, orig_data.co); - if (vd.no) { - copy_v3_v3_short(vd.no, orig_data.no); - } - else { - normal_short_to_float_v3(vd.fno, orig_data.no); - } - } - else if (orig_data.unode->type == SCULPT_UNDO_MASK) { - *vd.mask = orig_data.mask; - } - else if (orig_data.unode->type == SCULPT_UNDO_COLOR) { - copy_v4_v4(vd.col, orig_data.col); - } + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + SCULPT_orig_vert_data_update(&orig_data, &vd); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + if (orig_data.unode->type == SCULPT_UNDO_COORDS) { + copy_v3_v3(vd.co, orig_data.co); + if (vd.no) { + copy_v3_v3_short(vd.no, orig_data.no); + } + else { + normal_short_to_float_v3(vd.fno, orig_data.no); } } - BKE_pbvh_vertex_iter_end; + else if (orig_data.unode->type == SCULPT_UNDO_MASK) { + *vd.mask = orig_data.mask; + } + else if (orig_data.unode->type == SCULPT_UNDO_COLOR) { + copy_v4_v4(vd.col, orig_data.col); + } - BKE_pbvh_node_mark_update(data->nodes[n]); + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } } + BKE_pbvh_vertex_iter_end; + + BKE_pbvh_node_mark_update(data->nodes[n]); } static void paint_mesh_restore_co(Sculpt *sd, Object *ob) @@ -1545,11 +1560,15 @@ static void sculpt_extend_redraw_rect_previous(Object *ob, rcti *rect) * mesh parts could disappear from screen (sergey). */ SculptSession *ss = ob->sculpt; - if (ss->cache) { - if (!BLI_rcti_is_empty(&ss->cache->previous_r)) { - BLI_rcti_union(rect, &ss->cache->previous_r); - } + if (!ss->cache) { + return; + } + + if (BLI_rcti_is_empty(&ss->cache->previous_r)) { + return; } + + BLI_rcti_union(rect, &ss->cache->previous_r); } /* Get a screen-space rectangle of the modified area. */ @@ -1651,28 +1670,30 @@ bool SCULPT_brush_test_sphere(SculptBrushTest *test, const float co[3]) { float distsq = len_squared_v3v3(co, test->location); - if (distsq <= test->radius_squared) { - if (sculpt_brush_test_clipping(test, co)) { - return false; - } - test->dist = sqrtf(distsq); - return true; + if (distsq > test->radius_squared) { + return false; } - return false; + + if (sculpt_brush_test_clipping(test, co)) { + return false; + } + + test->dist = sqrtf(distsq); + return true; } bool SCULPT_brush_test_sphere_sq(SculptBrushTest *test, const float co[3]) { float distsq = len_squared_v3v3(co, test->location); - if (distsq <= test->radius_squared) { - if (sculpt_brush_test_clipping(test, co)) { - return false; - } - test->dist = distsq; - return true; + if (distsq > test->radius_squared) { + return false; } - return false; + if (sculpt_brush_test_clipping(test, co)) { + return false; + } + test->dist = distsq; + return true; } bool SCULPT_brush_test_sphere_fast(const SculptBrushTest *test, const float co[3]) @@ -1689,14 +1710,16 @@ bool SCULPT_brush_test_circle_sq(SculptBrushTest *test, const float co[3]) closest_to_plane_normalized_v3(co_proj, test->plane_view, co); float distsq = len_squared_v3v3(co_proj, test->location); - if (distsq <= test->radius_squared) { - if (sculpt_brush_test_clipping(test, co)) { - return false; - } - test->dist = distsq; - return true; + if (distsq > test->radius_squared) { + return false; } - return false; + + if (sculpt_brush_test_clipping(test, co)) { + return false; + } + + test->dist = distsq; + return true; } bool SCULPT_brush_test_cube(SculptBrushTest *test, @@ -1724,25 +1747,26 @@ bool SCULPT_brush_test_cube(SculptBrushTest *test, const float constant_side = hardness * side; const float falloff_side = roundness * side; - if (local_co[0] <= side && local_co[1] <= side && local_co[2] <= side) { + if (!(local_co[0] <= side && local_co[1] <= side && local_co[2] <= side)) { + /* Outside the square. */ + return false; + } + if (min_ff(local_co[0], local_co[1]) > constant_side) { /* Corner, distance to the center of the corner circle. */ - if (min_ff(local_co[0], local_co[1]) > constant_side) { - float r_point[3]; - copy_v3_fl(r_point, constant_side); - test->dist = len_v2v2(r_point, local_co) / falloff_side; - return true; - } + float r_point[3]; + copy_v3_fl(r_point, constant_side); + test->dist = len_v2v2(r_point, local_co) / falloff_side; + return true; + } + if (max_ff(local_co[0], local_co[1]) > constant_side) { /* Side, distance to the square XY axis. */ - if (max_ff(local_co[0], local_co[1]) > constant_side) { - test->dist = (max_ff(local_co[0], local_co[1]) - constant_side) / falloff_side; - return true; - } - /* Inside the square, constant distance. */ - test->dist = 0.0f; + test->dist = (max_ff(local_co[0], local_co[1]) - constant_side) / falloff_side; return true; } - /* Outside the square. */ - return false; + + /* Inside the square, constant distance. */ + test->dist = 0.0f; + return true; } SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss, @@ -1777,21 +1801,21 @@ static float frontface(const Brush *br, const short no[3], const float fno[3]) { - if (br->flag & BRUSH_FRONTFACE) { - float dot; + if (!(br->flag & BRUSH_FRONTFACE)) { + return 1.0f; + } - if (no) { - float tmp[3]; + float dot; + if (no) { + float tmp[3]; - normal_short_to_float_v3(tmp, no); - dot = dot_v3v3(tmp, sculpt_normal); - } - else { - dot = dot_v3v3(fno, sculpt_normal); - } - return dot > 0.0f ? dot : 0.0f; + normal_short_to_float_v3(tmp, no); + dot = dot_v3v3(tmp, sculpt_normal); + } + else { + dot = dot_v3v3(fno, sculpt_normal); } - return 1.0f; + return dot > 0.0f ? dot : 0.0f; } #if 0 @@ -1871,25 +1895,25 @@ static float calc_radial_symmetry_feather(Sculpt *sd, static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache) { - if (sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER) { - float overlap; - const int symm = cache->symmetry; - - overlap = 0.0f; - for (int i = 0; i <= symm; i++) { - if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) { - - overlap += calc_overlap(cache, i, 0, 0); + if (!(sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER)) { + return 1.0f; + } + float overlap; + const int symm = cache->symmetry; - overlap += calc_radial_symmetry_feather(sd, cache, i, 'X'); - overlap += calc_radial_symmetry_feather(sd, cache, i, 'Y'); - overlap += calc_radial_symmetry_feather(sd, cache, i, 'Z'); - } + overlap = 0.0f; + for (int i = 0; i <= symm; i++) { + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; } - return 1.0f / overlap; + overlap += calc_overlap(cache, i, 0, 0); + + overlap += calc_radial_symmetry_feather(sd, cache, i, 'X'); + overlap += calc_radial_symmetry_feather(sd, cache, i, 'Y'); + overlap += calc_radial_symmetry_feather(sd, cache, i, 'Z'); } - return 1.0f; + return 1.0f / overlap; } /* -------------------------------------------------------------------- */ @@ -1991,35 +2015,37 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, normal_test_r = sculpt_brush_normal_test_sq_fn(&normal_test, co); area_test_r = sculpt_brush_area_test_sq_fn(&area_test, co); - if (normal_test_r || area_test_r) { - float no[3]; - int flip_index; + if (!normal_test_r && !area_test_r) { + continue; + } - normal_tri_v3(no, UNPACK3(co_tri)); + float no[3]; + int flip_index; - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); - if (use_area_cos && area_test_r) { - /* Weight the coordinates towards the center. */ - float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius); - const float afactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); + normal_tri_v3(no, UNPACK3(co_tri)); - float disp[3]; - sub_v3_v3v3(disp, co, area_test.location); - mul_v3_fl(disp, 1.0f - afactor); - add_v3_v3v3(co, area_test.location, disp); - add_v3_v3(anctd->area_cos[flip_index], co); + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + if (use_area_cos && area_test_r) { + /* Weight the coordinates towards the center. */ + float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius); + const float afactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); - anctd->count_co[flip_index] += 1; - } - if (use_area_nos && normal_test_r) { - /* Weight the normals towards the center. */ - float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius); - const float nfactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); - mul_v3_fl(no, nfactor); - - add_v3_v3(anctd->area_nos[flip_index], no); - anctd->count_no[flip_index] += 1; - } + float disp[3]; + sub_v3_v3v3(disp, co, area_test.location); + mul_v3_fl(disp, 1.0f - afactor); + add_v3_v3v3(co, area_test.location, disp); + add_v3_v3(anctd->area_cos[flip_index], co); + + anctd->count_co[flip_index] += 1; + } + if (use_area_nos && normal_test_r) { + /* Weight the normals towards the center. */ + float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius); + const float nfactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); + mul_v3_fl(no, nfactor); + + add_v3_v3(anctd->area_nos[flip_index], no); + anctd->count_no[flip_index] += 1; } } } @@ -2051,49 +2077,51 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, normal_test_r = sculpt_brush_normal_test_sq_fn(&normal_test, co); area_test_r = sculpt_brush_area_test_sq_fn(&area_test, co); - if (normal_test_r || area_test_r) { - float no[3]; - int flip_index; + if (!normal_test_r && !area_test_r) { + continue; + } + + float no[3]; + int flip_index; - data->any_vertex_sampled = true; + data->any_vertex_sampled = true; - if (use_original) { - normal_short_to_float_v3(no, no_s); + if (use_original) { + normal_short_to_float_v3(no, no_s); + } + else { + if (vd.no) { + normal_short_to_float_v3(no, vd.no); } else { - if (vd.no) { - normal_short_to_float_v3(no, vd.no); - } - else { - copy_v3_v3(no, vd.fno); - } + copy_v3_v3(no, vd.fno); } + } - flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <= - 0.0f); + flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <= + 0.0f); - if (use_area_cos && area_test_r) { - /* Weight the coordinates towards the center. */ - float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius); - const float afactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); + if (use_area_cos && area_test_r) { + /* Weight the coordinates towards the center. */ + float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius); + const float afactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); - float disp[3]; - sub_v3_v3v3(disp, co, area_test.location); - mul_v3_fl(disp, 1.0f - afactor); - add_v3_v3v3(co, area_test.location, disp); + float disp[3]; + sub_v3_v3v3(disp, co, area_test.location); + mul_v3_fl(disp, 1.0f - afactor); + add_v3_v3v3(co, area_test.location, disp); - add_v3_v3(anctd->area_cos[flip_index], co); - anctd->count_co[flip_index] += 1; - } - if (use_area_nos && normal_test_r) { - /* Weight the normals towards the center. */ - float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius); - const float nfactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); - mul_v3_fl(no, nfactor); - - add_v3_v3(anctd->area_nos[flip_index], no); - anctd->count_no[flip_index] += 1; - } + add_v3_v3(anctd->area_cos[flip_index], co); + anctd->count_co[flip_index] += 1; + } + if (use_area_nos && normal_test_r) { + /* Weight the normals towards the center. */ + float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius); + const float nfactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); + mul_v3_fl(no, nfactor); + + add_v3_v3(anctd->area_nos[flip_index], no); + anctd->count_no[flip_index] += 1; } } BKE_pbvh_vertex_iter_end; @@ -2150,10 +2178,12 @@ static void calc_area_center( /* For flatten center. */ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { - if (anctd.count_co[n] != 0) { - mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]); - break; + if (anctd.count_co[n] == 0) { + continue; } + + mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]); + break; } if (n == 2) { @@ -2249,10 +2279,12 @@ static void calc_area_normal_and_center( /* For flatten center. */ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { - if (anctd.count_co[n] != 0) { - mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]); - break; + if (anctd.count_co[n] == 0) { + continue; } + + mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]); + break; } if (n == 2) { @@ -2892,26 +2924,27 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata, PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = - bstrength * - SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, *vd.mask, vd.index, thread_id) * - ss->cache->pressure; + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = + bstrength * + SCULPT_brush_strength_factor( + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, *vd.mask, vd.index, thread_id) * + ss->cache->pressure; - float avg[3], val[3]; + float avg[3], val[3]; - SCULPT_bmesh_four_neighbor_average(avg, direction, vd.bm_vert); + SCULPT_bmesh_four_neighbor_average(avg, direction, vd.bm_vert); - sub_v3_v3v3(val, avg, vd.co); + sub_v3_v3v3(val, avg, vd.co); - madd_v3_v3v3fl(val, vd.co, val, fade); + madd_v3_v3v3fl(val, vd.co, val, fade); - SCULPT_clip(sd, ss, vd.co, val); + SCULPT_clip(sd, ss, vd.co, val); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -2964,21 +2997,23 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } - if (bstrength > 0.0f) { - (*vd.mask) += fade * bstrength * (1.0f - *vd.mask); - } - else { - (*vd.mask) += fade * bstrength * (*vd.mask); - } - *vd.mask = clamp_f(*vd.mask, 0.0f, 1.0f); + const float fade = SCULPT_brush_strength_factor( + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (bstrength > 0.0f) { + (*vd.mask) += fade * bstrength * (1.0f - *vd.mask); + } + else { + (*vd.mask) += fade * bstrength * (*vd.mask); + } + *vd.mask = clamp_f(*vd.mask, 0.0f, 1.0f); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } BKE_pbvh_vertex_iter_end; } @@ -3039,26 +3074,27 @@ static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata, PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - float limit_co[3]; - float disp[3]; - SCULPT_vertex_limit_surface_get(ss, vd.index, limit_co); - sub_v3_v3v3(disp, limit_co, vd.co); - mul_v3_v3fl(proxy[vd.i], disp, fade); + float limit_co[3]; + float disp[3]; + SCULPT_vertex_limit_surface_get(ss, vd.index, limit_co); + sub_v3_v3v3(disp, limit_co, vd.co); + mul_v3_v3fl(proxy[vd.i], disp, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3151,12 +3187,15 @@ static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata, ss->cache->limit_surface_co[vd.index]); const float *neighbor_limit_surface_disp = ss->cache->prev_displacement[ni.index]; normalize_v3_v3(vertex_disp_norm, vertex_disp); - if (dot_v3v3(current_disp_norm, vertex_disp_norm) < 0.0f) { - const float disp_interp = clamp_f( - -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); - madd_v3_v3fl(interp_limit_surface_disp, neighbor_limit_surface_disp, disp_interp); - weights_accum += disp_interp; + + if (dot_v3v3(current_disp_norm, vertex_disp_norm) >= 0.0f) { + continue; } + + const float disp_interp = clamp_f( + -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); + madd_v3_v3fl(interp_limit_surface_disp, neighbor_limit_surface_disp, disp_interp); + weights_accum += disp_interp; } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); @@ -3246,23 +3285,24 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - /* Offset vertex. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + /* Offset vertex. */ + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], offset, fade); + mul_v3_v3fl(proxy[vd.i], offset, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3325,23 +3365,24 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - /* Offset vertex. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + /* Offset vertex. */ + const float fade = SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], offset, fade); + mul_v3_v3fl(proxy[vd.i], offset, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3407,52 +3448,53 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - float current_disp[3]; - float current_disp_norm[3]; - float final_disp[3] = {0.0f, 0.0f, 0.0f}; + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + const float fade = SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + float current_disp[3]; + float current_disp_norm[3]; + float final_disp[3] = {0.0f, 0.0f, 0.0f}; - switch (brush->slide_deform_type) { - case BRUSH_SLIDE_DEFORM_DRAG: - sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); - break; - case BRUSH_SLIDE_DEFORM_PINCH: - sub_v3_v3v3(current_disp, ss->cache->location, vd.co); - break; - case BRUSH_SLIDE_DEFORM_EXPAND: - sub_v3_v3v3(current_disp, vd.co, ss->cache->location); - break; - } + switch (brush->slide_deform_type) { + case BRUSH_SLIDE_DEFORM_DRAG: + sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); + break; + case BRUSH_SLIDE_DEFORM_PINCH: + sub_v3_v3v3(current_disp, ss->cache->location, vd.co); + break; + case BRUSH_SLIDE_DEFORM_EXPAND: + sub_v3_v3v3(current_disp, vd.co, ss->cache->location); + break; + } - normalize_v3_v3(current_disp_norm, current_disp); - mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); - - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { - float vertex_disp[3]; - float vertex_disp_norm[3]; - sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); - normalize_v3_v3(vertex_disp_norm, vertex_disp); - if (dot_v3v3(current_disp_norm, vertex_disp_norm) > 0.0f) { - madd_v3_v3fl(final_disp, vertex_disp_norm, dot_v3v3(current_disp, vertex_disp)); - } + normalize_v3_v3(current_disp_norm, current_disp); + mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { + float vertex_disp[3]; + float vertex_disp_norm[3]; + sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); + normalize_v3_v3(vertex_disp_norm, vertex_disp); + if (dot_v3v3(current_disp_norm, vertex_disp_norm) > 0.0f) { + madd_v3_v3fl(final_disp, vertex_disp_norm, dot_v3v3(current_disp, vertex_disp)); } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); - mul_v3_v3fl(proxy[vd.i], final_disp, fade); + mul_v3_v3fl(proxy[vd.i], final_disp, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3482,16 +3524,17 @@ void SCULPT_relax_vertex(SculptSession *ss, /* When the vertex to relax is boundary, use only connected boundary vertices for the average * position. */ if (is_boundary) { - if (SCULPT_vertex_is_boundary(ss, ni.index)) { - add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); - avg_count++; - - /* Calculate a normal for the constraint plane using the edges of the boundary. */ - float to_neighbor[3]; - sub_v3_v3v3(to_neighbor, SCULPT_vertex_co_get(ss, ni.index), vd->co); - normalize_v3(to_neighbor); - add_v3_v3(boundary_normal, to_neighbor); + if (!SCULPT_vertex_is_boundary(ss, ni.index)) { + continue; } + add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); + avg_count++; + + /* Calculate a normal for the constraint plane using the edges of the boundary. */ + float to_neighbor[3]; + sub_v3_v3v3(to_neighbor, SCULPT_vertex_co_get(ss, ni.index), vd->co); + normalize_v3(to_neighbor); + add_v3_v3(boundary_normal, to_neighbor); } else { add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); @@ -3563,21 +3606,22 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - SCULPT_relax_vertex(ss, &vd, fade * bstrength, false, vd.co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + const float fade = SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + SCULPT_relax_vertex(ss, &vd, fade * bstrength, false, vd.co); + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3728,38 +3772,39 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - /* Offset vertex. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - float val1[3]; - float val2[3]; - - /* First we pinch. */ - sub_v3_v3v3(val1, test.location, vd.co); - if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - project_plane_v3_v3v3(val1, val1, ss->cache->view_normal); - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + /* Offset vertex. */ + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + float val1[3]; + float val2[3]; + + /* First we pinch. */ + sub_v3_v3v3(val1, test.location, vd.co); + if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { + project_plane_v3_v3v3(val1, val1, ss->cache->view_normal); + } - mul_v3_fl(val1, fade * flippedbstrength); + mul_v3_fl(val1, fade * flippedbstrength); - sculpt_project_v3(spvc, val1, val1); + sculpt_project_v3(spvc, val1, val1); - /* Then we draw. */ - mul_v3_v3fl(val2, offset, fade); + /* Then we draw. */ + mul_v3_v3fl(val2, offset, fade); - add_v3_v3v3(proxy[vd.i], val1, val2); + add_v3_v3v3(proxy[vd.i], val1, val2); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3845,40 +3890,41 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - float disp_center[3]; - float x_disp[3]; - float z_disp[3]; - /* Calculate displacement from the vertex to the brush center. */ - sub_v3_v3v3(disp_center, test.location, vd.co); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + float disp_center[3]; + float x_disp[3]; + float z_disp[3]; + /* Calculate displacement from the vertex to the brush center. */ + sub_v3_v3v3(disp_center, test.location, vd.co); - /* Project the displacement into the X vector (aligned to the stroke). */ - mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space)); + /* Project the displacement into the X vector (aligned to the stroke). */ + mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space)); - /* Project the displacement into the Z vector (aligned to the surface normal). */ - mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space)); + /* Project the displacement into the Z vector (aligned to the surface normal). */ + mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space)); - /* Add the two projected vectors to calculate the final displacement. - * The Y component is removed. */ - add_v3_v3v3(disp_center, x_disp, z_disp); + /* Add the two projected vectors to calculate the final displacement. + * The Y component is removed. */ + add_v3_v3v3(disp_center, x_disp, z_disp); - if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - project_plane_v3_v3v3(disp_center, disp_center, ss->cache->view_normal); - } - mul_v3_v3fl(proxy[vd.i], disp_center, fade); + if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { + project_plane_v3_v3v3(disp_center, disp_center, ss->cache->view_normal); + } + mul_v3_v3fl(proxy[vd.i], disp_center, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3961,33 +4007,34 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata, { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - if (grab_silhouette) { - float silhouette_test_dir[3]; - normalize_v3_v3(silhouette_test_dir, grab_delta); - if (dot_v3v3(ss->cache->initial_normal, ss->cache->grab_delta_symmetry) < 0.0f) { - mul_v3_fl(silhouette_test_dir, -1.0f); - } - float vno[3]; - normal_short_to_float_v3(vno, orig_data.no); - fade *= max_ff(dot_v3v3(vno, silhouette_test_dir), 0.0f); + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + if (grab_silhouette) { + float silhouette_test_dir[3]; + normalize_v3_v3(silhouette_test_dir, grab_delta); + if (dot_v3v3(ss->cache->initial_normal, ss->cache->grab_delta_symmetry) < 0.0f) { + mul_v3_fl(silhouette_test_dir, -1.0f); } + float vno[3]; + normal_short_to_float_v3(vno, orig_data.no); + fade *= max_ff(dot_v3v3(vno, silhouette_test_dir), 0.0f); + } - mul_v3_v3fl(proxy[vd.i], grab_delta, fade); + mul_v3_v3fl(proxy[vd.i], grab_delta, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4149,13 +4196,14 @@ void SCULPT_flip_v3_by_symm_area(float v[3], { for (int i = 0; i < 3; i++) { ePaintSymmetryFlags symm_it = 1 << i; - if (symm & symm_it) { - if (symmarea & symm_it) { - flip_v3(v, symm_it); - } - if (pivot[i] < 0.0f) { - flip_v3(v, symm_it); - } + if (!(symm & symm_it)) { + continue; + } + if (symmarea & symm_it) { + flip_v3(v, symm_it); + } + if (pivot[i] < 0.0f) { + flip_v3(v, symm_it); } } } @@ -4167,13 +4215,14 @@ void SCULPT_flip_quat_by_symm_area(float quat[3], { for (int i = 0; i < 3; i++) { ePaintSymmetryFlags symm_it = 1 << i; - if (symm & symm_it) { - if (symmarea & symm_it) { - flip_qt(quat, symm_it); - } - if (pivot[i] < 0.0f) { - flip_qt(quat, symm_it); - } + if (!(symm & symm_it)) { + continue; + } + if (symmarea & symm_it) { + flip_qt(quat, symm_it); + } + if (pivot[i] < 0.0f) { + flip_qt(quat, symm_it); } } } @@ -4289,22 +4338,23 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], cono, fade); + mul_v3_v3fl(proxy[vd.i], cono, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4368,75 +4418,76 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (do_elastic || sculpt_brush_test_sq_fn(&test, vd.co)) { + if (!do_elastic && !sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } - float fade; - if (do_elastic) { - fade = 1.0f; - } - else { - fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - } + float fade; + if (do_elastic) { + fade = 1.0f; + } + else { + fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + } - mul_v3_v3fl(proxy[vd.i], grab_delta, fade); + mul_v3_v3fl(proxy[vd.i], grab_delta, fade); - /* Negative pinch will inflate, helps maintain volume. */ - if (do_pinch) { - float delta_pinch_init[3], delta_pinch[3]; + /* Negative pinch will inflate, helps maintain volume. */ + if (do_pinch) { + float delta_pinch_init[3], delta_pinch[3]; - sub_v3_v3v3(delta_pinch, vd.co, test.location); - if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - project_plane_v3_v3v3(delta_pinch, delta_pinch, ss->cache->true_view_normal); - } + sub_v3_v3v3(delta_pinch, vd.co, test.location); + if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { + project_plane_v3_v3v3(delta_pinch, delta_pinch, ss->cache->true_view_normal); + } - /* Important to calculate based on the grabbed location - * (intentionally ignore fade here). */ - add_v3_v3(delta_pinch, grab_delta); + /* Important to calculate based on the grabbed location + * (intentionally ignore fade here). */ + add_v3_v3(delta_pinch, grab_delta); - sculpt_project_v3(spvc, delta_pinch, delta_pinch); + sculpt_project_v3(spvc, delta_pinch, delta_pinch); - copy_v3_v3(delta_pinch_init, delta_pinch); + copy_v3_v3(delta_pinch_init, delta_pinch); - float pinch_fade = pinch * fade; - /* When reducing, scale reduction back by how close to the center we are, - * so we don't pinch into nothingness. */ - if (pinch > 0.0f) { - /* Square to have even less impact for close vertices. */ - pinch_fade *= pow2f(min_ff(1.0f, len_v3(delta_pinch) / ss->cache->radius)); - } - mul_v3_fl(delta_pinch, 1.0f + pinch_fade); - sub_v3_v3v3(delta_pinch, delta_pinch_init, delta_pinch); - add_v3_v3(proxy[vd.i], delta_pinch); + float pinch_fade = pinch * fade; + /* When reducing, scale reduction back by how close to the center we are, + * so we don't pinch into nothingness. */ + if (pinch > 0.0f) { + /* Square to have even less impact for close vertices. */ + pinch_fade *= pow2f(min_ff(1.0f, len_v3(delta_pinch) / ss->cache->radius)); } + mul_v3_fl(delta_pinch, 1.0f + pinch_fade); + sub_v3_v3v3(delta_pinch, delta_pinch_init, delta_pinch); + add_v3_v3(proxy[vd.i], delta_pinch); + } - if (do_rake_rotation) { - float delta_rotate[3]; - sculpt_rake_rotate(ss, test.location, vd.co, fade, delta_rotate); - add_v3_v3(proxy[vd.i], delta_rotate); - } + if (do_rake_rotation) { + float delta_rotate[3]; + sculpt_rake_rotate(ss, test.location, vd.co, fade, delta_rotate); + add_v3_v3(proxy[vd.i], delta_rotate); + } - if (do_elastic) { - float disp[3]; - BKE_kelvinlet_grab_triscale(disp, ¶ms, vd.co, ss->cache->location, proxy[vd.i]); - mul_v3_fl(disp, bstrength * 20.0f); - if (vd.mask) { - mul_v3_fl(disp, 1.0f - *vd.mask); - } - mul_v3_fl(disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index)); - copy_v3_v3(proxy[vd.i], disp); + if (do_elastic) { + float disp[3]; + BKE_kelvinlet_grab_triscale(disp, ¶ms, vd.co, ss->cache->location, proxy[vd.i]); + mul_v3_fl(disp, bstrength * 20.0f); + if (vd.mask) { + mul_v3_fl(disp, 1.0f - *vd.mask); } + mul_v3_fl(disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index)); + copy_v3_v3(proxy[vd.i], disp); + } - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4507,22 +4558,23 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata, { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], cono, fade); + mul_v3_v3fl(proxy[vd.i], cono, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4580,27 +4632,28 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata, { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - float vec[3], rot[3][3]; - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + float vec[3], rot[3][3]; + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - sub_v3_v3v3(vec, orig_data.co, ss->cache->location); - axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade); - mul_v3_m3v3(proxy[vd.i], rot, vec); - add_v3_v3(proxy[vd.i], ss->cache->location); - sub_v3_v3(proxy[vd.i], orig_data.co); + sub_v3_v3v3(vec, orig_data.co, ss->cache->location); + axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade); + mul_v3_m3v3(proxy[vd.i], rot, vec); + add_v3_v3(proxy[vd.i], ss->cache->location); + sub_v3_v3(proxy[vd.i], orig_data.co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4652,70 +4705,71 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - const int vi = vd.index; - float *disp_factor; - if (use_persistent_base) { - disp_factor = &ss->persistent_base[vi].disp; - } - else { - disp_factor = &ss->cache->layer_displacement_factor[vi]; - } + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + const int vi = vd.index; + float *disp_factor; + if (use_persistent_base) { + disp_factor = &ss->persistent_base[vi].disp; + } + else { + disp_factor = &ss->cache->layer_displacement_factor[vi]; + } - /* When using persistent base, the layer brush (holding Control) invert mode resets the - * height of the layer to 0. This makes possible to clean edges of previously added layers - * on top of the base. */ - /* The main direction of the layers is inverted using the regular brush strength with the - * brush direction property. */ - if (use_persistent_base && ss->cache->invert) { - (*disp_factor) += fabsf(fade * bstrength * (*disp_factor)) * - ((*disp_factor) > 0.0f ? -1.0f : 1.0f); - } - else { - (*disp_factor) += fade * bstrength * (1.05f - fabsf(*disp_factor)); - } - if (vd.mask) { - const float clamp_mask = 1.0f - *vd.mask; - *disp_factor = clamp_f(*disp_factor, -clamp_mask, clamp_mask); - } - else { - *disp_factor = clamp_f(*disp_factor, -1.0f, 1.0f); - } + /* When using persistent base, the layer brush (holding Control) invert mode resets the + * height of the layer to 0. This makes possible to clean edges of previously added layers + * on top of the base. */ + /* The main direction of the layers is inverted using the regular brush strength with the + * brush direction property. */ + if (use_persistent_base && ss->cache->invert) { + (*disp_factor) += fabsf(fade * bstrength * (*disp_factor)) * + ((*disp_factor) > 0.0f ? -1.0f : 1.0f); + } + else { + (*disp_factor) += fade * bstrength * (1.05f - fabsf(*disp_factor)); + } + if (vd.mask) { + const float clamp_mask = 1.0f - *vd.mask; + *disp_factor = clamp_f(*disp_factor, -clamp_mask, clamp_mask); + } + else { + *disp_factor = clamp_f(*disp_factor, -1.0f, 1.0f); + } - float final_co[3]; - float normal[3]; + float final_co[3]; + float normal[3]; - if (use_persistent_base) { - SCULPT_vertex_persistent_normal_get(ss, vi, normal); - mul_v3_fl(normal, brush->height); - madd_v3_v3v3fl(final_co, SCULPT_vertex_persistent_co_get(ss, vi), normal, *disp_factor); - } - else { - normal_short_to_float_v3(normal, orig_data.no); - mul_v3_fl(normal, brush->height); - madd_v3_v3v3fl(final_co, orig_data.co, normal, *disp_factor); - } + if (use_persistent_base) { + SCULPT_vertex_persistent_normal_get(ss, vi, normal); + mul_v3_fl(normal, brush->height); + madd_v3_v3v3fl(final_co, SCULPT_vertex_persistent_co_get(ss, vi), normal, *disp_factor); + } + else { + normal_short_to_float_v3(normal, orig_data.no); + mul_v3_fl(normal, brush->height); + madd_v3_v3v3fl(final_co, orig_data.co, normal, *disp_factor); + } - float vdisp[3]; - sub_v3_v3v3(vdisp, final_co, vd.co); - mul_v3_fl(vdisp, fabsf(fade)); - add_v3_v3v3(final_co, vd.co, vdisp); + float vdisp[3]; + sub_v3_v3v3(vdisp, final_co, vd.co); + mul_v3_fl(vdisp, fabsf(fade)); + add_v3_v3v3(final_co, vd.co, vdisp); - SCULPT_clip(sd, ss, vd.co, final_co); + SCULPT_clip(sd, ss, vd.co, final_co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4764,31 +4818,32 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - float val[3]; + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + float val[3]; - if (vd.fno) { - copy_v3_v3(val, vd.fno); - } - else { - normal_short_to_float_v3(val, vd.no); - } + if (vd.fno) { + copy_v3_v3(val, vd.fno); + } + else { + normal_short_to_float_v3(val, vd.no); + } - mul_v3_fl(val, fade * ss->cache->radius); - mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale); + mul_v3_fl(val, fade * ss->cache->radius); + mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4869,30 +4924,31 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float intr[3]; - float val[3]; + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + float intr[3]; + float val[3]; - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - sub_v3_v3v3(val, intr, vd.co); + sub_v3_v3v3(val, intr, vd.co); - if (SCULPT_plane_trim(ss->cache, brush, val)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (SCULPT_plane_trim(ss->cache, brush, val)) { + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], val, fade); + mul_v3_v3fl(proxy[vd.i], val, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } } @@ -4975,16 +5031,17 @@ static void calc_clay_surface_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float plane_dist = dist_signed_to_plane_v3(vd.co, plane); - float plane_dist_abs = fabsf(plane_dist); - if (plane_dist > 0.0f) { - csd->plane_dist[0] = MIN2(csd->plane_dist[0], plane_dist_abs); - } - else { - csd->plane_dist[1] = MIN2(csd->plane_dist[1], plane_dist_abs); - } + float plane_dist = dist_signed_to_plane_v3(vd.co, plane); + float plane_dist_abs = fabsf(plane_dist); + if (plane_dist > 0.0f) { + csd->plane_dist[0] = MIN2(csd->plane_dist[0], plane_dist_abs); + } + else { + csd->plane_dist[1] = MIN2(csd->plane_dist[1], plane_dist_abs); } BKE_pbvh_vertex_iter_end; } @@ -5025,28 +5082,30 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float intr[3]; - float val[3]; - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } - sub_v3_v3v3(val, intr, vd.co); + float intr[3]; + float val[3]; + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + sub_v3_v3v3(val, intr, vd.co); - mul_v3_v3fl(proxy[vd.i], val, fade); + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5143,35 +5202,37 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (SCULPT_brush_test_cube(&test, vd.co, mat, brush->tip_roundness)) { - if (plane_point_side_flip(vd.co, test.plane_tool, flip)) { - float intr[3]; - float val[3]; + if (!SCULPT_brush_test_cube(&test, vd.co, mat, brush->tip_roundness)) { + continue; + } - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + if (!plane_point_side_flip(vd.co, test.plane_tool, flip)) { + continue; + } - sub_v3_v3v3(val, intr, vd.co); + float intr[3]; + float val[3]; + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + sub_v3_v3v3(val, intr, vd.co); - if (SCULPT_plane_trim(ss->cache, brush, val)) { - /* The normal from the vertices is ignored, it causes glitch with planes, see: T44390. */ - const float fade = bstrength * - SCULPT_brush_strength_factor(ss, - brush, - vd.co, - ss->cache->radius * test.dist, - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!SCULPT_plane_trim(ss->cache, brush, val)) { + continue; + } + /* The normal from the vertices is ignored, it causes glitch with planes, see: T44390. */ + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + ss->cache->radius * test.dist, + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], val, fade); + mul_v3_v3fl(proxy[vd.i], val, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5295,33 +5356,37 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - if (SCULPT_plane_point_side(vd.co, test.plane_tool)) { - float intr[3]; - float val[3]; - - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - - sub_v3_v3v3(val, intr, vd.co); - - if (SCULPT_plane_trim(ss->cache, brush, val)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + + if (!SCULPT_plane_point_side(vd.co, test.plane_tool)) { + continue; + } + + float intr[3]; + float val[3]; + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + sub_v3_v3v3(val, intr, vd.co); + + if (!SCULPT_plane_trim(ss->cache, brush, val)) { + continue; + } + + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5390,33 +5455,37 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - if (!SCULPT_plane_point_side(vd.co, test.plane_tool)) { - float intr[3]; - float val[3]; - - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - - sub_v3_v3v3(val, intr, vd.co); - - if (SCULPT_plane_trim(ss->cache, brush, val)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + + if (SCULPT_plane_point_side(vd.co, test.plane_tool)) { + continue; + } + + float intr[3]; + float val[3]; + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + sub_v3_v3v3(val, intr, vd.co); + + if (!SCULPT_plane_trim(ss->cache, brush, val)) { + continue; + } + + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5501,38 +5570,39 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float local_co[3]; - mul_v3_m4v3(local_co, mat, vd.co); - float intr[3], intr_tilt[3]; - float val[3]; - - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - closest_to_plane_normalized_v3(intr_tilt, plane_tilt, vd.co); - - /* Mix the deformation of the aligned and the tilted plane based on the brush space vertex - * coordinates. */ - /* We can also control the mix with a curve if it produces noticeable artifacts in the center - * of the brush. */ - const float tilt_mix = local_co[1] > 0.0f ? 0.0f : 1.0f; - interp_v3_v3v3(intr, intr, intr_tilt, tilt_mix); - sub_v3_v3v3(val, intr_tilt, vd.co); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + float local_co[3]; + mul_v3_m4v3(local_co, mat, vd.co); + float intr[3], intr_tilt[3]; + float val[3]; - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + closest_to_plane_normalized_v3(intr_tilt, plane_tilt, vd.co); - mul_v3_v3fl(proxy[vd.i], val, fade); + /* Mix the deformation of the aligned and the tilted plane based on the brush space vertex + * coordinates. */ + /* We can also control the mix with a curve if it produces noticeable artifacts in the center + * of the brush. */ + const float tilt_mix = local_co[1] > 0.0f ? 0.0f : 1.0f; + interp_v3_v3v3(intr, intr, intr_tilt, tilt_mix); + sub_v3_v3v3(val, intr_tilt, vd.co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5656,22 +5726,23 @@ static void do_gravity_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], offset, fade); + mul_v3_v3fl(proxy[vd.i], offset, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5766,49 +5837,51 @@ static void sculpt_topology_update(Sculpt *sd, ob, sd, brush, use_original, radius_scale, &totnode); /* Only act if some verts are inside the brush area. */ - if (totnode) { - PBVHTopologyUpdateMode mode = 0; - float location[3]; + if (totnode == 0) { + return; + } - if (!(sd->flags & SCULPT_DYNTOPO_DETAIL_MANUAL)) { - if (sd->flags & SCULPT_DYNTOPO_SUBDIVIDE) { - mode |= PBVH_Subdivide; - } + PBVHTopologyUpdateMode mode = 0; + float location[3]; - if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) || (brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY)) { - mode |= PBVH_Collapse; - } + if (!(sd->flags & SCULPT_DYNTOPO_DETAIL_MANUAL)) { + if (sd->flags & SCULPT_DYNTOPO_SUBDIVIDE) { + mode |= PBVH_Subdivide; } - for (n = 0; n < totnode; n++) { - SCULPT_undo_push_node(ob, - nodes[n], - brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : - SCULPT_UNDO_COORDS); - BKE_pbvh_node_mark_update(nodes[n]); - - if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { - BKE_pbvh_node_mark_topology_update(nodes[n]); - BKE_pbvh_bmesh_node_save_orig(ss->bm, nodes[n]); - } + if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) || (brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY)) { + mode |= PBVH_Collapse; } + } + + for (n = 0; n < totnode; n++) { + SCULPT_undo_push_node(ob, + nodes[n], + brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : + SCULPT_UNDO_COORDS); + BKE_pbvh_node_mark_update(nodes[n]); if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { - BKE_pbvh_bmesh_update_topology(ss->pbvh, - mode, - ss->cache->location, - ss->cache->view_normal, - ss->cache->radius, - (brush->flag & BRUSH_FRONTFACE) != 0, - (brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE)); + BKE_pbvh_node_mark_topology_update(nodes[n]); + BKE_pbvh_bmesh_node_save_orig(ss->bm, nodes[n]); } + } - MEM_SAFE_FREE(nodes); - - /* Update average stroke position. */ - copy_v3_v3(location, ss->cache->true_location); - mul_m4_v3(ob->obmat, location); + if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { + BKE_pbvh_bmesh_update_topology(ss->pbvh, + mode, + ss->cache->location, + ss->cache->view_normal, + ss->cache->radius, + (brush->flag & BRUSH_FRONTFACE) != 0, + (brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE)); } + + MEM_SAFE_FREE(nodes); + + /* Update average stroke position. */ + copy_v3_v3(location, ss->cache->true_location); + mul_m4_v3(ob->obmat, location); } static void do_brush_action_task_cb(void *__restrict userdata, @@ -5914,202 +5987,199 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe } /* Only act if some verts are inside the brush area. */ - if (totnode) { - float location[3]; + if (totnode == 0) { + return; + } + float location[3]; - SculptThreadedTaskData task_data = { - .sd = sd, - .ob = ob, - .brush = brush, - .nodes = nodes, - }; + SculptThreadedTaskData task_data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + }; - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); - if (sculpt_brush_needs_normal(ss, brush)) { - update_sculpt_normal(sd, ob, nodes, totnode); - } + if (sculpt_brush_needs_normal(ss, brush)) { + update_sculpt_normal(sd, ob, nodes, totnode); + } - if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) { - update_brush_local_mat(sd, ob); - } + if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) { + update_brush_local_mat(sd, ob); + } - if (brush->sculpt_tool == SCULPT_TOOL_POSE && SCULPT_stroke_is_first_brush_step(ss->cache)) { - SCULPT_pose_brush_init(sd, ob, ss, brush); - } + if (brush->sculpt_tool == SCULPT_TOOL_POSE && SCULPT_stroke_is_first_brush_step(ss->cache)) { + SCULPT_pose_brush_init(sd, ob, ss, brush); + } - if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { - if (!ss->cache->cloth_sim) { - ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create( - ss, 1.0f, 0.0f, 0.0f, false, true); - SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim); - } - SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim); - SCULPT_cloth_brush_ensure_nodes_constraints( - sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, FLT_MAX); + if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { + if (!ss->cache->cloth_sim) { + ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create( + ss, 1.0f, 0.0f, 0.0f, false, true); + SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim); } + SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim); + SCULPT_cloth_brush_ensure_nodes_constraints( + sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, FLT_MAX); + } - bool invert = ss->cache->pen_flip || ss->cache->invert || brush->flag & BRUSH_DIR_IN; + bool invert = ss->cache->pen_flip || ss->cache->invert || brush->flag & BRUSH_DIR_IN; - /* Apply one type of brush action. */ - switch (brush->sculpt_tool) { - case SCULPT_TOOL_DRAW: - do_draw_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_SMOOTH: - if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_LAPLACIAN) { - SCULPT_do_smooth_brush(sd, ob, nodes, totnode); - } - else if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) { - SCULPT_do_surface_smooth_brush(sd, ob, nodes, totnode); - } - break; - case SCULPT_TOOL_CREASE: - do_crease_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_BLOB: - do_crease_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_PINCH: - do_pinch_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_INFLATE: - do_inflate_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_GRAB: - do_grab_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_ROTATE: - do_rotate_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_SNAKE_HOOK: - do_snake_hook_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_NUDGE: - do_nudge_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_THUMB: - do_thumb_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_LAYER: - do_layer_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_FLATTEN: - do_flatten_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_CLAY: - do_clay_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_CLAY_STRIPS: - do_clay_strips_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_MULTIPLANE_SCRAPE: - SCULPT_do_multiplane_scrape_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_CLAY_THUMB: - do_clay_thumb_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_FILL: - if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) { - do_scrape_brush(sd, ob, nodes, totnode); - } - else { - do_fill_brush(sd, ob, nodes, totnode); - } - break; - case SCULPT_TOOL_SCRAPE: - if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) { - do_fill_brush(sd, ob, nodes, totnode); - } - else { - do_scrape_brush(sd, ob, nodes, totnode); - } - break; - case SCULPT_TOOL_MASK: - do_mask_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_POSE: - SCULPT_do_pose_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_DRAW_SHARP: - do_draw_sharp_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_ELASTIC_DEFORM: - do_elastic_deform_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_SLIDE_RELAX: - do_slide_relax_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_BOUNDARY: - SCULPT_do_boundary_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_CLOTH: - SCULPT_do_cloth_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_DRAW_FACE_SETS: - SCULPT_do_draw_face_sets_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_DISPLACEMENT_ERASER: - do_displacement_eraser_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_DISPLACEMENT_SMEAR: - do_displacement_smear_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_PAINT: - SCULPT_do_paint_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_SMEAR: - SCULPT_do_smear_brush(sd, ob, nodes, totnode); - break; - } - - if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_MASK) && - brush->autosmooth_factor > 0) { - if (brush->flag & BRUSH_INVERSE_SMOOTH_PRESSURE) { - SCULPT_smooth(sd, - ob, - nodes, - totnode, - brush->autosmooth_factor * (1.0f - ss->cache->pressure), - false); + /* Apply one type of brush action. */ + switch (brush->sculpt_tool) { + case SCULPT_TOOL_DRAW: + do_draw_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SMOOTH: + if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_LAPLACIAN) { + SCULPT_do_smooth_brush(sd, ob, nodes, totnode); + } + else if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) { + SCULPT_do_surface_smooth_brush(sd, ob, nodes, totnode); + } + break; + case SCULPT_TOOL_CREASE: + do_crease_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_BLOB: + do_crease_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_PINCH: + do_pinch_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_INFLATE: + do_inflate_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_GRAB: + do_grab_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_ROTATE: + do_rotate_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SNAKE_HOOK: + do_snake_hook_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_NUDGE: + do_nudge_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_THUMB: + do_thumb_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_LAYER: + do_layer_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_FLATTEN: + do_flatten_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_CLAY: + do_clay_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_CLAY_STRIPS: + do_clay_strips_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_MULTIPLANE_SCRAPE: + SCULPT_do_multiplane_scrape_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_CLAY_THUMB: + do_clay_thumb_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_FILL: + if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) { + do_scrape_brush(sd, ob, nodes, totnode); } else { - SCULPT_smooth(sd, ob, nodes, totnode, brush->autosmooth_factor, false); + do_fill_brush(sd, ob, nodes, totnode); } - } + break; + case SCULPT_TOOL_SCRAPE: + if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) { + do_fill_brush(sd, ob, nodes, totnode); + } + else { + do_scrape_brush(sd, ob, nodes, totnode); + } + break; + case SCULPT_TOOL_MASK: + do_mask_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_POSE: + SCULPT_do_pose_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_DRAW_SHARP: + do_draw_sharp_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_ELASTIC_DEFORM: + do_elastic_deform_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SLIDE_RELAX: + do_slide_relax_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_BOUNDARY: + SCULPT_do_boundary_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_CLOTH: + SCULPT_do_cloth_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_DRAW_FACE_SETS: + SCULPT_do_draw_face_sets_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_DISPLACEMENT_ERASER: + do_displacement_eraser_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_DISPLACEMENT_SMEAR: + do_displacement_smear_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_PAINT: + SCULPT_do_paint_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SMEAR: + SCULPT_do_smear_brush(sd, ob, nodes, totnode); + break; + } - if (sculpt_brush_use_topology_rake(ss, brush)) { - bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor); + if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_MASK) && + brush->autosmooth_factor > 0) { + if (brush->flag & BRUSH_INVERSE_SMOOTH_PRESSURE) { + SCULPT_smooth( + sd, ob, nodes, totnode, brush->autosmooth_factor * (1.0f - ss->cache->pressure), false); } - - /* The cloth brush adds the gravity as a regular force and it is processed in the solver. */ - if (ss->cache->supports_gravity && !ELEM(brush->sculpt_tool, - SCULPT_TOOL_CLOTH, - SCULPT_TOOL_DRAW_FACE_SETS, - SCULPT_TOOL_BOUNDARY)) { - do_gravity(sd, ob, nodes, totnode, sd->gravity_factor); + else { + SCULPT_smooth(sd, ob, nodes, totnode, brush->autosmooth_factor, false); } + } - if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { - if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) { - SCULPT_cloth_sim_activate_nodes(ss->cache->cloth_sim, nodes, totnode); - SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode); - } + if (sculpt_brush_use_topology_rake(ss, brush)) { + bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor); + } + + /* The cloth brush adds the gravity as a regular force and it is processed in the solver. */ + if (ss->cache->supports_gravity && !ELEM(brush->sculpt_tool, + SCULPT_TOOL_CLOTH, + SCULPT_TOOL_DRAW_FACE_SETS, + SCULPT_TOOL_BOUNDARY)) { + do_gravity(sd, ob, nodes, totnode, sd->gravity_factor); + } + + if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { + if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) { + SCULPT_cloth_sim_activate_nodes(ss->cache->cloth_sim, nodes, totnode); + SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode); } + } - MEM_SAFE_FREE(nodes); + MEM_SAFE_FREE(nodes); - /* Update average stroke position. */ - copy_v3_v3(location, ss->cache->true_location); - mul_m4_v3(ob->obmat, location); + /* Update average stroke position. */ + copy_v3_v3(location, ss->cache->true_location); + mul_m4_v3(ob->obmat, location); - add_v3_v3(ups->average_stroke_accum, location); - ups->average_stroke_counter++; - /* Update last stroke position. */ - ups->last_stroke_valid = true; - } + add_v3_v3(ups->average_stroke_accum, location); + ups->average_stroke_counter++; + /* Update last stroke position. */ + ups->last_stroke_valid = true; } /* Flush displacement from deformed PBVH vertex to original mesh. */ @@ -6199,22 +6269,22 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) PBVHNode **nodes; int totnode; - BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode); - - /* First line is tools that don't support proxies. */ - if (ss->cache->supports_gravity || (sculpt_tool_is_proxy_used(brush->sculpt_tool) == false)) { - SculptThreadedTaskData data = { - .sd = sd, - .ob = ob, - .brush = brush, - .nodes = nodes, - }; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); + if (!ss->cache->supports_gravity && sculpt_tool_is_proxy_used(brush->sculpt_tool)) { + /* First line is tools that don't support proxies. */ + return; } + BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode); + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); MEM_SAFE_FREE(nodes); } @@ -6235,12 +6305,14 @@ static void sculpt_update_keyblock(Object *ob) vertCos = BKE_pbvh_vert_coords_alloc(ss->pbvh); } - if (vertCos) { - SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos); + if (!vertCos) { + return; + } - if (vertCos != ss->orig_cos) { - MEM_freeN(vertCos); - } + SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos); + + if (vertCos != ss->orig_cos) { + MEM_freeN(vertCos); } } @@ -6259,10 +6331,12 @@ static void SCULPT_flush_stroke_deform_task_cb(void *__restrict userdata, { sculpt_flush_pbvhvert_deform(ob, &vd); - if (vertCos) { - int index = vd.vert_indices[vd.i]; - copy_v3_v3(vertCos[index], ss->orig_cos[index]); + if (!vertCos) { + continue; } + + int index = vd.vert_indices[vd.i]; + copy_v3_v3(vertCos[index], ss->orig_cos[index]); } BKE_pbvh_vertex_iter_end; } @@ -6490,17 +6564,18 @@ static void do_symmetrical_brush_actions(Sculpt *sd, /* `symm` is a bit combination of XYZ - * 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */ for (int i = 0; i <= symm; i++) { - if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) { - cache->mirror_symmetry_pass = i; - cache->radial_symmetry_pass = 0; + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; + } + cache->mirror_symmetry_pass = i; + cache->radial_symmetry_pass = 0; - SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0); - do_tiled(sd, ob, brush, ups, action); + SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0); + do_tiled(sd, ob, brush, ups, action); - do_radial_symmetry(sd, ob, brush, ups, action, i, 'X', feather); - do_radial_symmetry(sd, ob, brush, ups, action, i, 'Y', feather); - do_radial_symmetry(sd, ob, brush, ups, action, i, 'Z', feather); - } + do_radial_symmetry(sd, ob, brush, ups, action, i, 'X', feather); + do_radial_symmetry(sd, ob, brush, ups, action, i, 'Y', feather); + do_radial_symmetry(sd, ob, brush, ups, action, i, 'Z', feather); } } @@ -6668,22 +6743,25 @@ static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss) ModifierData *md; for (md = ob->modifiers.first; md; md = md->next) { - if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) { - MirrorModifierData *mmd = (MirrorModifierData *)md; - - if (mmd->flag & MOD_MIR_CLIPPING) { - /* Check each axis for mirroring. */ - for (int i = 0; i < 3; i++) { - if (mmd->flag & (MOD_MIR_AXIS_X << i)) { - /* Enable sculpt clipping. */ - ss->cache->flag |= CLIP_X << i; - - /* Update the clip tolerance. */ - if (mmd->tolerance > ss->cache->clip_tolerance[i]) { - ss->cache->clip_tolerance[i] = mmd->tolerance; - } - } - } + if (!(md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime))) { + continue; + } + MirrorModifierData *mmd = (MirrorModifierData *)md; + + if (!(mmd->flag & MOD_MIR_CLIPPING)) { + continue; + } + /* Check each axis for mirroring. */ + for (int i = 0; i < 3; i++) { + if (!(mmd->flag & (MOD_MIR_AXIS_X << i))) { + continue; + } + /* Enable sculpt clipping. */ + ss->cache->flag |= CLIP_X << i; + + /* Update the clip tolerance. */ + if (mmd->tolerance > ss->cache->clip_tolerance[i]) { + ss->cache->clip_tolerance[i] = mmd->tolerance; } } } @@ -6926,150 +7004,151 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru }; int tool = brush->sculpt_tool; - if (ELEM(tool, - SCULPT_TOOL_PAINT, - SCULPT_TOOL_GRAB, - SCULPT_TOOL_ELASTIC_DEFORM, - SCULPT_TOOL_CLOTH, - SCULPT_TOOL_NUDGE, - SCULPT_TOOL_CLAY_STRIPS, - SCULPT_TOOL_PINCH, - SCULPT_TOOL_MULTIPLANE_SCRAPE, - SCULPT_TOOL_CLAY_THUMB, - SCULPT_TOOL_SNAKE_HOOK, - SCULPT_TOOL_POSE, - SCULPT_TOOL_BOUNDARY, - SCULPT_TOOL_THUMB) || - sculpt_brush_use_topology_rake(ss, brush)) { - float grab_location[3], imat[4][4], delta[3], loc[3]; + if (!ELEM(tool, + SCULPT_TOOL_PAINT, + SCULPT_TOOL_GRAB, + SCULPT_TOOL_ELASTIC_DEFORM, + SCULPT_TOOL_CLOTH, + SCULPT_TOOL_NUDGE, + SCULPT_TOOL_CLAY_STRIPS, + SCULPT_TOOL_PINCH, + SCULPT_TOOL_MULTIPLANE_SCRAPE, + SCULPT_TOOL_CLAY_THUMB, + SCULPT_TOOL_SNAKE_HOOK, + SCULPT_TOOL_POSE, + SCULPT_TOOL_BOUNDARY, + SCULPT_TOOL_THUMB) && + !sculpt_brush_use_topology_rake(ss, brush)) { + return; + } + float grab_location[3], imat[4][4], delta[3], loc[3]; - if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { - if (tool == SCULPT_TOOL_GRAB && brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) { - copy_v3_v3(cache->orig_grab_location, - SCULPT_vertex_co_for_grab_active_get(ss, SCULPT_active_vertex_get(ss))); - } - else { - copy_v3_v3(cache->orig_grab_location, cache->true_location); - } + if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { + if (tool == SCULPT_TOOL_GRAB && brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) { + copy_v3_v3(cache->orig_grab_location, + SCULPT_vertex_co_for_grab_active_get(ss, SCULPT_active_vertex_get(ss))); } - else if (tool == SCULPT_TOOL_SNAKE_HOOK || - (tool == SCULPT_TOOL_CLOTH && - brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK)) { - add_v3_v3(cache->true_location, cache->grab_delta); + else { + copy_v3_v3(cache->orig_grab_location, cache->true_location); } + } + else if (tool == SCULPT_TOOL_SNAKE_HOOK || + (tool == SCULPT_TOOL_CLOTH && + brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK)) { + add_v3_v3(cache->true_location, cache->grab_delta); + } - /* Compute 3d coordinate at same z from original location + mouse. */ - mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location); - ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mouse, grab_location); + /* Compute 3d coordinate at same z from original location + mouse. */ + mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location); + ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mouse, grab_location); - /* Compute delta to move verts by. */ - if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { - if (sculpt_needs_delta_from_anchored_origin(brush)) { - sub_v3_v3v3(delta, grab_location, cache->old_grab_location); - invert_m4_m4(imat, ob->obmat); - mul_mat3_m4_v3(imat, delta); - add_v3_v3(cache->grab_delta, delta); - } - else if (sculpt_needs_delta_for_tip_orientation(brush)) { - if (brush->flag & BRUSH_ANCHORED) { - float orig[3]; - mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location); - sub_v3_v3v3(cache->grab_delta, grab_location, orig); - } - else { - sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location); - } - invert_m4_m4(imat, ob->obmat); - mul_mat3_m4_v3(imat, cache->grab_delta); + /* Compute delta to move verts by. */ + if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { + if (sculpt_needs_delta_from_anchored_origin(brush)) { + sub_v3_v3v3(delta, grab_location, cache->old_grab_location); + invert_m4_m4(imat, ob->obmat); + mul_mat3_m4_v3(imat, delta); + add_v3_v3(cache->grab_delta, delta); + } + else if (sculpt_needs_delta_for_tip_orientation(brush)) { + if (brush->flag & BRUSH_ANCHORED) { + float orig[3]; + mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location); + sub_v3_v3v3(cache->grab_delta, grab_location, orig); } else { - /* Use for 'Brush.topology_rake_factor'. */ sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location); } + invert_m4_m4(imat, ob->obmat); + mul_mat3_m4_v3(imat, cache->grab_delta); } else { - zero_v3(cache->grab_delta); + /* Use for 'Brush.topology_rake_factor'. */ + sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location); } + } + else { + zero_v3(cache->grab_delta); + } - if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - project_plane_v3_v3v3(cache->grab_delta, cache->grab_delta, ss->cache->true_view_normal); - } + if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { + project_plane_v3_v3v3(cache->grab_delta, cache->grab_delta, ss->cache->true_view_normal); + } - copy_v3_v3(cache->old_grab_location, grab_location); + copy_v3_v3(cache->old_grab_location, grab_location); - if (tool == SCULPT_TOOL_GRAB) { - if (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) { - copy_v3_v3(cache->anchored_location, cache->orig_grab_location); - } - else { - copy_v3_v3(cache->anchored_location, cache->true_location); - } + if (tool == SCULPT_TOOL_GRAB) { + if (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) { + copy_v3_v3(cache->anchored_location, cache->orig_grab_location); } - else if (tool == SCULPT_TOOL_ELASTIC_DEFORM || SCULPT_is_cloth_deform_brush(brush)) { + else { copy_v3_v3(cache->anchored_location, cache->true_location); } - else if (tool == SCULPT_TOOL_THUMB) { - copy_v3_v3(cache->anchored_location, cache->orig_grab_location); - } + } + else if (tool == SCULPT_TOOL_ELASTIC_DEFORM || SCULPT_is_cloth_deform_brush(brush)) { + copy_v3_v3(cache->anchored_location, cache->true_location); + } + else if (tool == SCULPT_TOOL_THUMB) { + copy_v3_v3(cache->anchored_location, cache->orig_grab_location); + } - if (sculpt_needs_delta_from_anchored_origin(brush)) { - /* Location stays the same for finding vertices in brush radius. */ - copy_v3_v3(cache->true_location, cache->orig_grab_location); + if (sculpt_needs_delta_from_anchored_origin(brush)) { + /* Location stays the same for finding vertices in brush radius. */ + copy_v3_v3(cache->true_location, cache->orig_grab_location); - ups->draw_anchored = true; - copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); - ups->anchored_size = ups->pixel_radius; - } + ups->draw_anchored = true; + copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); + ups->anchored_size = ups->pixel_radius; + } - /* Handle 'rake' */ - cache->is_rake_rotation_valid = false; + /* Handle 'rake' */ + cache->is_rake_rotation_valid = false; - invert_m4_m4(imat, ob->obmat); - mul_mat3_m4_v3(imat, grab_location); + invert_m4_m4(imat, ob->obmat); + mul_mat3_m4_v3(imat, grab_location); - if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { - copy_v3_v3(cache->rake_data.follow_co, grab_location); - } + if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { + copy_v3_v3(cache->rake_data.follow_co, grab_location); + } - if (sculpt_brush_needs_rake_rotation(brush)) { - cache->rake_data.follow_dist = cache->radius * SCULPT_RAKE_BRUSH_FACTOR; + if (!sculpt_brush_needs_rake_rotation(brush)) { + return; + } + cache->rake_data.follow_dist = cache->radius * SCULPT_RAKE_BRUSH_FACTOR; - if (!is_zero_v3(cache->grab_delta)) { - const float eps = 0.00001f; + if (!is_zero_v3(cache->grab_delta)) { + const float eps = 0.00001f; - float v1[3], v2[3]; + float v1[3], v2[3]; - copy_v3_v3(v1, cache->rake_data.follow_co); - copy_v3_v3(v2, cache->rake_data.follow_co); - sub_v3_v3(v2, cache->grab_delta); + copy_v3_v3(v1, cache->rake_data.follow_co); + copy_v3_v3(v2, cache->rake_data.follow_co); + sub_v3_v3(v2, cache->grab_delta); - sub_v3_v3(v1, grab_location); - sub_v3_v3(v2, grab_location); + sub_v3_v3(v1, grab_location); + sub_v3_v3(v2, grab_location); - if ((normalize_v3(v2) > eps) && (normalize_v3(v1) > eps) && - (len_squared_v3v3(v1, v2) > eps)) { - const float rake_dist_sq = len_squared_v3v3(cache->rake_data.follow_co, grab_location); - const float rake_fade = (rake_dist_sq > square_f(cache->rake_data.follow_dist)) ? - 1.0f : - sqrtf(rake_dist_sq) / cache->rake_data.follow_dist; + if ((normalize_v3(v2) > eps) && (normalize_v3(v1) > eps) && (len_squared_v3v3(v1, v2) > eps)) { + const float rake_dist_sq = len_squared_v3v3(cache->rake_data.follow_co, grab_location); + const float rake_fade = (rake_dist_sq > square_f(cache->rake_data.follow_dist)) ? + 1.0f : + sqrtf(rake_dist_sq) / cache->rake_data.follow_dist; - float axis[3], angle; - float tquat[4]; + float axis[3], angle; + float tquat[4]; - rotation_between_vecs_to_quat(tquat, v1, v2); + rotation_between_vecs_to_quat(tquat, v1, v2); - /* Use axis-angle to scale rotation since the factor may be above 1. */ - quat_to_axis_angle(axis, &angle, tquat); - normalize_v3(axis); + /* Use axis-angle to scale rotation since the factor may be above 1. */ + quat_to_axis_angle(axis, &angle, tquat); + normalize_v3(axis); - angle *= brush->rake_factor * rake_fade; - axis_angle_normalized_to_quat(cache->rake_rotation, axis, angle); - cache->is_rake_rotation_valid = true; - } - } - sculpt_rake_data_update(&cache->rake_data, grab_location); + angle *= brush->rake_factor * rake_fade; + axis_angle_normalized_to_quat(cache->rake_rotation, axis, angle); + cache->is_rake_rotation_valid = true; } } + sculpt_rake_data_update(&cache->rake_data, grab_location); } static void sculpt_update_cache_paint_variants(StrokeCache *cache, const Brush *brush) @@ -7257,71 +7336,73 @@ void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *b static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin) { - if (BKE_pbvh_node_get_tmin(node) < *tmin) { - SculptRaycastData *srd = data_v; - float(*origco)[3] = NULL; - bool use_origco = false; + if (BKE_pbvh_node_get_tmin(node) >= *tmin) { + return; + } + SculptRaycastData *srd = data_v; + float(*origco)[3] = NULL; + bool use_origco = false; - if (srd->original && srd->ss->cache) { - if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { - use_origco = true; - } - else { - /* Intersect with coordinates from before we started stroke. */ - SculptUndoNode *unode = SCULPT_undo_get_node(node); - origco = (unode) ? unode->co : NULL; - use_origco = origco ? true : false; - } + if (srd->original && srd->ss->cache) { + if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { + use_origco = true; } - - if (BKE_pbvh_node_raycast(srd->ss->pbvh, - node, - origco, - use_origco, - srd->ray_start, - srd->ray_normal, - &srd->isect_precalc, - &srd->depth, - &srd->active_vertex_index, - &srd->active_face_grid_index, - srd->face_normal)) { - srd->hit = true; - *tmin = srd->depth; + else { + /* Intersect with coordinates from before we started stroke. */ + SculptUndoNode *unode = SCULPT_undo_get_node(node); + origco = (unode) ? unode->co : NULL; + use_origco = origco ? true : false; } } + + if (BKE_pbvh_node_raycast(srd->ss->pbvh, + node, + origco, + use_origco, + srd->ray_start, + srd->ray_normal, + &srd->isect_precalc, + &srd->depth, + &srd->active_vertex_index, + &srd->active_face_grid_index, + srd->face_normal)) { + srd->hit = true; + *tmin = srd->depth; + } } static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *tmin) { - if (BKE_pbvh_node_get_tmin(node) < *tmin) { - SculptFindNearestToRayData *srd = data_v; - float(*origco)[3] = NULL; - bool use_origco = false; + if (BKE_pbvh_node_get_tmin(node) >= *tmin) { + return; + } + SculptFindNearestToRayData *srd = data_v; + float(*origco)[3] = NULL; + bool use_origco = false; - if (srd->original && srd->ss->cache) { - if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { - use_origco = true; - } - else { - /* Intersect with coordinates from before we started stroke. */ - SculptUndoNode *unode = SCULPT_undo_get_node(node); - origco = (unode) ? unode->co : NULL; - use_origco = origco ? true : false; - } + if (srd->original && srd->ss->cache) { + if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { + use_origco = true; } - - if (BKE_pbvh_node_find_nearest_to_ray(srd->ss->pbvh, - node, - origco, - use_origco, - srd->ray_start, - srd->ray_normal, - &srd->depth, - &srd->dist_sq_to_ray)) { - srd->hit = true; - *tmin = srd->dist_sq_to_ray; + else { + /* Intersect with coordinates from before we started stroke. */ + SculptUndoNode *unode = SCULPT_undo_get_node(node); + origco = (unode) ? unode->co : NULL; + use_origco = origco ? true : false; } } + + if (BKE_pbvh_node_find_nearest_to_ray(srd->ss->pbvh, + node, + origco, + use_origco, + srd->ray_start, + srd->ray_normal, + &srd->depth, + &srd->dist_sq_to_ray)) { + srd->hit = true; + *tmin = srd->dist_sq_to_ray; + } } float SCULPT_raycast_init(ViewContext *vc, @@ -7546,26 +7627,30 @@ bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mouse[2]) } } - if (!hit) { - if (ELEM(brush->falloff_shape, PAINT_FALLOFF_SHAPE_TUBE)) { - SculptFindNearestToRayData srd = { - .original = original, - .ss = ob->sculpt, - .hit = false, - .ray_start = ray_start, - .ray_normal = ray_normal, - .depth = FLT_MAX, - .dist_sq_to_ray = FLT_MAX, - }; - BKE_pbvh_find_nearest_to_ray( - ss->pbvh, sculpt_find_nearest_to_ray_cb, &srd, ray_start, ray_normal, srd.original); - if (srd.hit) { - hit = true; - copy_v3_v3(out, ray_normal); - mul_v3_fl(out, srd.depth); - add_v3_v3(out, ray_start); - } - } + if (hit) { + return hit; + } + + if (!ELEM(brush->falloff_shape, PAINT_FALLOFF_SHAPE_TUBE)) { + return hit; + } + + SculptFindNearestToRayData srd = { + .original = original, + .ss = ob->sculpt, + .hit = false, + .ray_start = ray_start, + .ray_normal = ray_normal, + .depth = FLT_MAX, + .dist_sq_to_ray = FLT_MAX, + }; + BKE_pbvh_find_nearest_to_ray( + ss->pbvh, sculpt_find_nearest_to_ray_cb, &srd, ray_start, ray_normal, srd.original); + if (srd.hit) { + hit = true; + copy_v3_v3(out, ray_normal); + mul_v3_fl(out, srd.depth); + add_v3_v3(out, ray_start); } return hit; @@ -7748,19 +7833,20 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up bScreen *screen = WM_window_get_active_screen(win); LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { SpaceLink *sl = area->spacedata.first; - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *)sl; - if (v3d != current_v3d) { - need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, v3d); - } + if (sl->spacetype != SPACE_VIEW3D) { + continue; + } + View3D *v3d = (View3D *)sl; + if (v3d != current_v3d) { + need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, v3d); + } - /* Tag all 3D viewports for redraw now that we are done. Others - * viewports did not get a full redraw, and anti-aliasing for the - * current viewport was deactivated. */ - LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { - if (region->regiontype == RGN_TYPE_WINDOW) { - ED_region_tag_redraw(region); - } + /* Tag all 3D viewports for redraw now that we are done. Others + * viewports did not get a full redraw, and anti-aliasing for the + * current viewport was deactivated. */ + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + if (region->regiontype == RGN_TYPE_WINDOW) { + ED_region_tag_redraw(region); } } } @@ -7920,55 +8006,56 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str Sculpt *sd = CTX_data_tool_settings(C)->sculpt; /* Finished. */ - if (ss->cache) { - UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; - Brush *brush = BKE_paint_brush(&sd->paint); - BLI_assert(brush == ss->cache->brush); /* const, so we shouldn't change. */ - ups->draw_inverted = false; + if (!ss->cache) { + sculpt_brush_exit_tex(sd); + return; + } + UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; + Brush *brush = BKE_paint_brush(&sd->paint); + BLI_assert(brush == ss->cache->brush); /* const, so we shouldn't change. */ + ups->draw_inverted = false; - SCULPT_stroke_modifiers_check(C, ob, brush); + SCULPT_stroke_modifiers_check(C, ob, brush); - /* Alt-Smooth. */ - if (ss->cache->alt_smooth) { - if (brush->sculpt_tool == SCULPT_TOOL_MASK) { - brush->mask_tool = ss->cache->saved_mask_brush_tool; - } - else if (ELEM(brush->sculpt_tool, - SCULPT_TOOL_SLIDE_RELAX, - SCULPT_TOOL_DRAW_FACE_SETS, - SCULPT_TOOL_PAINT, - SCULPT_TOOL_SMEAR)) { - /* Do nothing. */ - } - else { - BKE_brush_size_set(scene, brush, ss->cache->saved_smooth_size); - brush = (Brush *)BKE_libblock_find_name(bmain, ID_BR, ss->cache->saved_active_brush_name); - if (brush) { - BKE_paint_brush_set(&sd->paint, brush); - } - } + /* Alt-Smooth. */ + if (ss->cache->alt_smooth) { + if (brush->sculpt_tool == SCULPT_TOOL_MASK) { + brush->mask_tool = ss->cache->saved_mask_brush_tool; } - - if (SCULPT_is_automasking_enabled(sd, ss, brush)) { - SCULPT_automasking_cache_free(ss->cache->automasking); + else if (ELEM(brush->sculpt_tool, + SCULPT_TOOL_SLIDE_RELAX, + SCULPT_TOOL_DRAW_FACE_SETS, + SCULPT_TOOL_PAINT, + SCULPT_TOOL_SMEAR)) { + /* Do nothing. */ } + else { + BKE_brush_size_set(scene, brush, ss->cache->saved_smooth_size); + brush = (Brush *)BKE_libblock_find_name(bmain, ID_BR, ss->cache->saved_active_brush_name); + if (brush) { + BKE_paint_brush_set(&sd->paint, brush); + } + } + } - BKE_pbvh_node_color_buffer_free(ss->pbvh); - SCULPT_cache_free(ss->cache); - ss->cache = NULL; + if (SCULPT_is_automasking_enabled(sd, ss, brush)) { + SCULPT_automasking_cache_free(ss->cache->automasking); + } - SCULPT_undo_push_end(); + BKE_pbvh_node_color_buffer_free(ss->pbvh); + SCULPT_cache_free(ss->cache); + ss->cache = NULL; - if (brush->sculpt_tool == SCULPT_TOOL_MASK) { - SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); - } - else { - SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); - } + SCULPT_undo_push_end(); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + if (brush->sculpt_tool == SCULPT_TOOL_MASK) { + SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); + } + else { + SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); } + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); sculpt_brush_exit_tex(sd); } @@ -8090,21 +8177,22 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; - if (ss) { - SCULPT_vertex_random_access_ensure(ss); - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); + if (!ss) { + return OPERATOR_FINISHED; + } + SCULPT_vertex_random_access_ensure(ss); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); - MEM_SAFE_FREE(ss->persistent_base); + MEM_SAFE_FREE(ss->persistent_base); - const int totvert = SCULPT_vertex_count_get(ss); - ss->persistent_base = MEM_mallocN(sizeof(SculptPersistentBase) * totvert, - "layer persistent base"); + const int totvert = SCULPT_vertex_count_get(ss); + ss->persistent_base = MEM_mallocN(sizeof(SculptPersistentBase) * totvert, + "layer persistent base"); - for (int i = 0; i < totvert; i++) { - copy_v3_v3(ss->persistent_base[i].co, SCULPT_vertex_co_get(ss, i)); - SCULPT_vertex_normal_get(ss, i, ss->persistent_base[i].no); - ss->persistent_base[i].disp = 0.0f; - } + for (int i = 0; i < totvert; i++) { + copy_v3_v3(ss->persistent_base[i].co, SCULPT_vertex_co_get(ss, i)); + SCULPT_vertex_normal_get(ss, i, ss->persistent_base[i].no); + ss->persistent_base[i].disp = 0.0f; } return OPERATOR_FINISHED; @@ -8564,12 +8652,13 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float totpoints++; ss->preview_vert_index_list[totpoints] = to_v; totpoints++; - if (!BLI_BITMAP_TEST(visited_vertices, to_v)) { - BLI_BITMAP_ENABLE(visited_vertices, to_v); - const float *co = SCULPT_vertex_co_for_grab_active_get(ss, to_v); - if (len_squared_v3v3(brush_co, co) < radius * radius) { - BLI_gsqueue_push(not_visited_vertices, &to_v); - } + if (BLI_BITMAP_TEST(visited_vertices, to_v)) { + continue; + } + BLI_BITMAP_ENABLE(visited_vertices, to_v); + const float *co = SCULPT_vertex_co_for_grab_active_get(ss, to_v); + if (len_squared_v3v3(brush_co, co) < radius * radius) { + BLI_gsqueue_push(not_visited_vertices, &to_v); } } } @@ -8993,7 +9082,7 @@ void SCULPT_fake_neighbors_ensure(Sculpt *sd, Object *ob, const float max_dist) for (int i = 0; i < totvert; i++) { const int from_v = i; - /* This vertex does not have a fake neighbor yet, seach one for it. */ + /* This vertex does not have a fake neighbor yet, search one for it. */ if (ss->fake_neighbors.fake_neighbor_index[from_v] == FAKE_NEIGHBOR_NONE) { const int to_v = SCULPT_fake_neighbor_search(sd, ob, from_v, max_dist); if (to_v != -1) { @@ -9099,11 +9188,12 @@ static void do_mask_by_color_contiguous_update_nodes_cb( const float current_mask = *vd.mask; const float new_mask = data->mask_by_color_floodfill[vd.index]; *vd.mask = sculpt_mask_by_color_final_mask_get(current_mask, new_mask, invert, preserve_mask); - if (current_mask != *vd.mask) { - update_node = true; - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (current_mask == *vd.mask) { + continue; + } + update_node = true; + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -9206,11 +9296,12 @@ static void do_mask_by_color_task_cb(void *__restrict userdata, const float new_mask = sculpt_mask_by_color_delta_get(active_color, vd.col, threshold, invert); *vd.mask = sculpt_mask_by_color_final_mask_get(current_mask, new_mask, invert, preserve_mask); - if (current_mask != *vd.mask) { - update_node = true; - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (current_mask == *vd.mask) { + continue; + } + update_node = true; + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c index bb68ec56b25..5f5fb51d75f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.c +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c @@ -298,24 +298,26 @@ float *SCULPT_boundary_automasking_init(Object *ob, for (int propagation_it = 0; propagation_it < propagation_steps; propagation_it++) { for (int i = 0; i < totvert; i++) { - if (edge_distance[i] == EDGE_DISTANCE_INF) { - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) { - if (edge_distance[ni.index] == propagation_it) { - edge_distance[i] = propagation_it + 1; - } + if (edge_distance[i] != EDGE_DISTANCE_INF) { + continue; + } + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) { + if (edge_distance[ni.index] == propagation_it) { + edge_distance[i] = propagation_it + 1; } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } } for (int i = 0; i < totvert; i++) { - if (edge_distance[i] != EDGE_DISTANCE_INF) { - const float p = 1.0f - ((float)edge_distance[i] / (float)propagation_steps); - const float edge_boundary_automask = pow2f(p); - automask_factor[i] *= (1.0f - edge_boundary_automask); + if (edge_distance[i] == EDGE_DISTANCE_INF) { + continue; } + const float p = 1.0f - ((float)edge_distance[i] / (float)propagation_steps); + const float edge_boundary_automask = pow2f(p); + automask_factor[i] *= (1.0f - edge_boundary_automask); } MEM_SAFE_FREE(edge_distance); diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c index 0cfb6f17adb..fca19c04b98 100644 --- a/source/blender/editors/sculpt_paint/sculpt_boundary.c +++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c @@ -227,19 +227,19 @@ static bool boundary_floodfill_cb( { BoundaryFloodFillData *data = userdata; SculptBoundary *boundary = data->boundary; - if (SCULPT_vertex_is_boundary(ss, to_v)) { - const float edge_len = len_v3v3(SCULPT_vertex_co_get(ss, from_v), - SCULPT_vertex_co_get(ss, to_v)); - const float distance_boundary_to_dst = boundary->distance ? - boundary->distance[from_v] + edge_len : - 0.0f; - sculpt_boundary_index_add(boundary, to_v, distance_boundary_to_dst, data->included_vertices); - if (!is_duplicate) { - sculpt_boundary_preview_edge_add(boundary, from_v, to_v); - } - return sculpt_boundary_is_vertex_in_editable_boundary(ss, to_v); + if (!SCULPT_vertex_is_boundary(ss, to_v)) { + return false; + } + const float edge_len = len_v3v3(SCULPT_vertex_co_get(ss, from_v), + SCULPT_vertex_co_get(ss, to_v)); + const float distance_boundary_to_dst = boundary->distance ? + boundary->distance[from_v] + edge_len : + 0.0f; + sculpt_boundary_index_add(boundary, to_v, distance_boundary_to_dst, data->included_vertices); + if (!is_duplicate) { + sculpt_boundary_preview_edge_add(boundary, from_v, to_v); } - return false; + return sculpt_boundary_is_vertex_in_editable_boundary(ss, to_v); } static void sculpt_boundary_indices_init(SculptSession *ss, @@ -360,49 +360,50 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss, SculptVertexNeighborIter ni; SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) { const bool is_visible = SCULPT_vertex_visible_get(ss, ni.index); - if (is_visible && - boundary->edit_info[ni.index].num_propagation_steps == BOUNDARY_STEPS_NONE) { - boundary->edit_info[ni.index].original_vertex = - boundary->edit_info[from_v].original_vertex; + if (!is_visible || + boundary->edit_info[ni.index].num_propagation_steps != BOUNDARY_STEPS_NONE) { + continue; + } + boundary->edit_info[ni.index].original_vertex = + boundary->edit_info[from_v].original_vertex; - BLI_BITMAP_ENABLE(visited_vertices, ni.index); + BLI_BITMAP_ENABLE(visited_vertices, ni.index); - if (ni.is_duplicate) { - /* Grids duplicates handling. */ - boundary->edit_info[ni.index].num_propagation_steps = - boundary->edit_info[from_v].num_propagation_steps; - } - else { - boundary->edit_info[ni.index].num_propagation_steps = - boundary->edit_info[from_v].num_propagation_steps + 1; - - BLI_gsqueue_push(next_iteration, &ni.index); - - /* When copying the data to the neighbor for the next iteration, it has to be copied to - * all its duplicates too. This is because it is not possible to know if the updated - * neighbor or one if its uninitialized duplicates is going to come first in order to - * copy the data in the from_v neighbor iterator. */ - if (has_duplicates) { - SculptVertexNeighborIter ni_duplis; - SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, ni.index, ni_duplis) { - if (ni_duplis.is_duplicate) { - boundary->edit_info[ni_duplis.index].original_vertex = - boundary->edit_info[from_v].original_vertex; - boundary->edit_info[ni_duplis.index].num_propagation_steps = - boundary->edit_info[from_v].num_propagation_steps + 1; - } + if (ni.is_duplicate) { + /* Grids duplicates handling. */ + boundary->edit_info[ni.index].num_propagation_steps = + boundary->edit_info[from_v].num_propagation_steps; + } + else { + boundary->edit_info[ni.index].num_propagation_steps = + boundary->edit_info[from_v].num_propagation_steps + 1; + + BLI_gsqueue_push(next_iteration, &ni.index); + + /* When copying the data to the neighbor for the next iteration, it has to be copied to + * all its duplicates too. This is because it is not possible to know if the updated + * neighbor or one if its uninitialized duplicates is going to come first in order to + * copy the data in the from_v neighbor iterator. */ + if (has_duplicates) { + SculptVertexNeighborIter ni_duplis; + SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, ni.index, ni_duplis) { + if (ni_duplis.is_duplicate) { + boundary->edit_info[ni_duplis.index].original_vertex = + boundary->edit_info[from_v].original_vertex; + boundary->edit_info[ni_duplis.index].num_propagation_steps = + boundary->edit_info[from_v].num_propagation_steps + 1; } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis); } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis); + } - /* Check the distance using the vertex that was propagated from the initial vertex that - * was used to initialize the boundary. */ - if (boundary->edit_info[from_v].original_vertex == initial_vertex) { - boundary->pivot_vertex = ni.index; - copy_v3_v3(boundary->initial_pivot_position, SCULPT_vertex_co_get(ss, ni.index)); - accum_distance += len_v3v3(SCULPT_vertex_co_get(ss, from_v), - SCULPT_vertex_co_get(ss, ni.index)); - } + /* Check the distance using the vertex that was propagated from the initial vertex that + * was used to initialize the boundary. */ + if (boundary->edit_info[from_v].original_vertex == initial_vertex) { + boundary->pivot_vertex = ni.index; + copy_v3_v3(boundary->initial_pivot_position, SCULPT_vertex_co_get(ss, ni.index)); + accum_distance += len_v3v3(SCULPT_vertex_co_get(ss, from_v), + SCULPT_vertex_co_get(ss, ni.index)); } } } @@ -552,28 +553,30 @@ static void sculpt_boundary_bend_data_init(SculptSession *ss, SculptBoundary *bo totvert, 3 * sizeof(float), "pivot positions"); for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps == boundary->max_propagation_steps) { - float dir[3]; - float normal[3]; - SCULPT_vertex_normal_get(ss, i, normal); - sub_v3_v3v3(dir, - SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex), - SCULPT_vertex_co_get(ss, i)); - cross_v3_v3v3( - boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex], dir, normal); - normalize_v3(boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]); - copy_v3_v3(boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex], - SCULPT_vertex_co_get(ss, i)); + if (boundary->edit_info[i].num_propagation_steps != boundary->max_propagation_steps) { + continue; } + float dir[3]; + float normal[3]; + SCULPT_vertex_normal_get(ss, i, normal); + sub_v3_v3v3(dir, + SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex), + SCULPT_vertex_co_get(ss, i)); + cross_v3_v3v3( + boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex], dir, normal); + normalize_v3(boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]); + copy_v3_v3(boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex], + SCULPT_vertex_co_get(ss, i)); } for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps != BOUNDARY_STEPS_NONE) { - copy_v3_v3(boundary->bend.pivot_positions[i], - boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex]); - copy_v3_v3(boundary->bend.pivot_rotation_axis[i], - boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]); + if (boundary->edit_info[i].num_propagation_steps == BOUNDARY_STEPS_NONE) { + continue; } + copy_v3_v3(boundary->bend.pivot_positions[i], + boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex]); + copy_v3_v3(boundary->bend.pivot_rotation_axis[i], + boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]); } } @@ -583,19 +586,20 @@ static void sculpt_boundary_slide_data_init(SculptSession *ss, SculptBoundary *b boundary->slide.directions = MEM_calloc_arrayN(totvert, 3 * sizeof(float), "slide directions"); for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps == boundary->max_propagation_steps) { - sub_v3_v3v3(boundary->slide.directions[boundary->edit_info[i].original_vertex], - SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex), - SCULPT_vertex_co_get(ss, i)); - normalize_v3(boundary->slide.directions[boundary->edit_info[i].original_vertex]); + if (boundary->edit_info[i].num_propagation_steps != boundary->max_propagation_steps) { } + sub_v3_v3v3(boundary->slide.directions[boundary->edit_info[i].original_vertex], + SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex), + SCULPT_vertex_co_get(ss, i)); + normalize_v3(boundary->slide.directions[boundary->edit_info[i].original_vertex]); } for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps != BOUNDARY_STEPS_NONE) { - copy_v3_v3(boundary->slide.directions[i], - boundary->slide.directions[boundary->edit_info[i].original_vertex]); + if (boundary->edit_info[i].num_propagation_steps == BOUNDARY_STEPS_NONE) { + continue; } + copy_v3_v3(boundary->slide.directions[i], + boundary->slide.directions[boundary->edit_info[i].original_vertex]); } } @@ -662,24 +666,27 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float t_orig_co[3]; - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - sub_v3_v3v3(t_orig_co, orig_data.co, boundary->bend.pivot_positions[vd.index]); - rotate_v3_v3v3fl(target_co, - t_orig_co, - boundary->bend.pivot_rotation_axis[vd.index], - angle * boundary->edit_info[vd.index].strength_factor * mask * automask); - add_v3_v3(target_co, boundary->bend.pivot_positions[vd.index]); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float t_orig_co[3]; + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + sub_v3_v3v3(t_orig_co, orig_data.co, boundary->bend.pivot_positions[vd.index]); + rotate_v3_v3v3fl(target_co, + t_orig_co, + boundary->bend.pivot_rotation_axis[vd.index], + angle * boundary->edit_info[vd.index].strength_factor * mask * automask); + add_v3_v3(target_co, boundary->bend.pivot_positions[vd.index]); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -708,22 +715,25 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - madd_v3_v3v3fl(target_co, - orig_data.co, - boundary->slide.directions[vd.index], - boundary->edit_info[vd.index].strength_factor * disp * mask * automask * - strength); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + madd_v3_v3v3fl(target_co, + orig_data.co, + boundary->slide.directions[vd.index], + boundary->edit_info[vd.index].strength_factor * disp * mask * automask * + strength); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -752,24 +762,27 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float normal[3]; - normal_short_to_float_v3(normal, orig_data.no); - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - madd_v3_v3v3fl(target_co, - orig_data.co, - normal, - boundary->edit_info[vd.index].strength_factor * disp * mask * automask * - strength); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float normal[3]; + normal_short_to_float_v3(normal, orig_data.no); + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + madd_v3_v3v3fl(target_co, + orig_data.co, + normal, + boundary->edit_info[vd.index].strength_factor * disp * mask * automask * + strength); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -796,21 +809,24 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - madd_v3_v3v3fl(target_co, - orig_data.co, - ss->cache->grab_delta_symmetry, - boundary->edit_info[vd.index].strength_factor * mask * automask * strength); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + madd_v3_v3v3fl(target_co, + orig_data.co, + ss->cache->grab_delta_symmetry, + boundary->edit_info[vd.index].strength_factor * mask * automask * strength); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -845,24 +861,27 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float t_orig_co[3]; - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - sub_v3_v3v3(t_orig_co, orig_data.co, boundary->twist.pivot_position); - rotate_v3_v3v3fl(target_co, - t_orig_co, - boundary->twist.rotation_axis, - angle * mask * automask * boundary->edit_info[vd.index].strength_factor); - add_v3_v3(target_co, boundary->twist.pivot_position); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float t_orig_co[3]; + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + sub_v3_v3v3(t_orig_co, orig_data.co, boundary->twist.pivot_position); + rotate_v3_v3v3fl(target_co, + t_orig_co, + boundary->twist.rotation_axis, + angle * mask * automask * boundary->edit_info[vd.index].strength_factor); + add_v3_v3(target_co, boundary->twist.pivot_position); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index c97f31fa682..16d10f6d6bb 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -540,97 +540,98 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, vertex_gravity, vd.index); /* When using the plane falloff mode the falloff is not constrained by the brush radius. */ - if (sculpt_brush_test_sq_fn(&test, current_vertex_location) || use_falloff_plane) { - - float dist = sqrtf(test.dist); + if (!sculpt_brush_test_sq_fn(&test, current_vertex_location) && !use_falloff_plane) { + continue; + } - if (use_falloff_plane) { - dist = dist_to_plane_v3(current_vertex_location, deform_plane); - } + float dist = sqrtf(test.dist); - const float fade = sim_factor * bstrength * - SCULPT_brush_strength_factor(ss, - brush, - current_vertex_location, - dist, - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float brush_disp[3]; - float normal[3]; - if (vd.no) { - normal_short_to_float_v3(normal, vd.no); - } - else { - copy_v3_v3(normal, vd.fno); - } + if (use_falloff_plane) { + dist = dist_to_plane_v3(current_vertex_location, deform_plane); + } - switch (brush->cloth_deform_type) { - case BRUSH_CLOTH_DEFORM_DRAG: - sub_v3_v3v3(brush_disp, ss->cache->location, ss->cache->last_location); - normalize_v3(brush_disp); - mul_v3_v3fl(force, brush_disp, fade); - break; - case BRUSH_CLOTH_DEFORM_PUSH: - /* Invert the fade to push inwards. */ - mul_v3_v3fl(force, offset, -fade); - break; - case BRUSH_CLOTH_DEFORM_GRAB: - madd_v3_v3v3fl(cloth_sim->deformation_pos[vd.index], - cloth_sim->init_pos[vd.index], - ss->cache->grab_delta_symmetry, - fade); - if (use_falloff_plane) { - cloth_sim->deformation_strength[vd.index] = clamp_f(fade, 0.0f, 1.0f); - } - else { - cloth_sim->deformation_strength[vd.index] = 1.0f; - } - zero_v3(force); - break; - case BRUSH_CLOTH_DEFORM_SNAKE_HOOK: - copy_v3_v3(cloth_sim->deformation_pos[vd.index], cloth_sim->pos[vd.index]); - madd_v3_v3fl(cloth_sim->deformation_pos[vd.index], ss->cache->grab_delta_symmetry, fade); - cloth_sim->deformation_strength[vd.index] = fade; - zero_v3(force); - break; - case BRUSH_CLOTH_DEFORM_PINCH_POINT: - if (use_falloff_plane) { - float distance = dist_signed_to_plane_v3(vd.co, deform_plane); - copy_v3_v3(brush_disp, plane_normal); - mul_v3_fl(brush_disp, -distance); - } - else { - sub_v3_v3v3(brush_disp, ss->cache->location, vd.co); - } - normalize_v3(brush_disp); - mul_v3_v3fl(force, brush_disp, fade); - break; - case BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR: { - float disp_center[3]; - float x_disp[3]; - float z_disp[3]; - sub_v3_v3v3(disp_center, ss->cache->location, vd.co); - normalize_v3(disp_center); - mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space)); - mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space)); - add_v3_v3v3(disp_center, x_disp, z_disp); - mul_v3_v3fl(force, disp_center, fade); - } break; - case BRUSH_CLOTH_DEFORM_INFLATE: - mul_v3_v3fl(force, normal, fade); - break; - case BRUSH_CLOTH_DEFORM_EXPAND: - cloth_sim->length_constraint_tweak[vd.index] += fade * 0.1f; - zero_v3(force); - break; - } + const float fade = sim_factor * bstrength * + SCULPT_brush_strength_factor(ss, + brush, + current_vertex_location, + dist, + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float brush_disp[3]; + float normal[3]; + if (vd.no) { + normal_short_to_float_v3(normal, vd.no); + } + else { + copy_v3_v3(normal, vd.fno); + } - cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, force, vd.index); + switch (brush->cloth_deform_type) { + case BRUSH_CLOTH_DEFORM_DRAG: + sub_v3_v3v3(brush_disp, ss->cache->location, ss->cache->last_location); + normalize_v3(brush_disp); + mul_v3_v3fl(force, brush_disp, fade); + break; + case BRUSH_CLOTH_DEFORM_PUSH: + /* Invert the fade to push inwards. */ + mul_v3_v3fl(force, offset, -fade); + break; + case BRUSH_CLOTH_DEFORM_GRAB: + madd_v3_v3v3fl(cloth_sim->deformation_pos[vd.index], + cloth_sim->init_pos[vd.index], + ss->cache->grab_delta_symmetry, + fade); + if (use_falloff_plane) { + cloth_sim->deformation_strength[vd.index] = clamp_f(fade, 0.0f, 1.0f); + } + else { + cloth_sim->deformation_strength[vd.index] = 1.0f; + } + zero_v3(force); + break; + case BRUSH_CLOTH_DEFORM_SNAKE_HOOK: + copy_v3_v3(cloth_sim->deformation_pos[vd.index], cloth_sim->pos[vd.index]); + madd_v3_v3fl(cloth_sim->deformation_pos[vd.index], ss->cache->grab_delta_symmetry, fade); + cloth_sim->deformation_strength[vd.index] = fade; + zero_v3(force); + break; + case BRUSH_CLOTH_DEFORM_PINCH_POINT: + if (use_falloff_plane) { + float distance = dist_signed_to_plane_v3(vd.co, deform_plane); + copy_v3_v3(brush_disp, plane_normal); + mul_v3_fl(brush_disp, -distance); + } + else { + sub_v3_v3v3(brush_disp, ss->cache->location, vd.co); + } + normalize_v3(brush_disp); + mul_v3_v3fl(force, brush_disp, fade); + break; + case BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR: { + float disp_center[3]; + float x_disp[3]; + float z_disp[3]; + sub_v3_v3v3(disp_center, ss->cache->location, vd.co); + normalize_v3(disp_center); + mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space)); + mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space)); + add_v3_v3v3(disp_center, x_disp, z_disp); + mul_v3_v3fl(force, disp_center, fade); + } break; + case BRUSH_CLOTH_DEFORM_INFLATE: + mul_v3_v3fl(force, normal, fade); + break; + case BRUSH_CLOTH_DEFORM_EXPAND: + cloth_sim->length_constraint_tweak[vd.index] += fade * 0.1f; + zero_v3(force); + break; } + + cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, force, vd.index); } BKE_pbvh_vertex_iter_end; } @@ -644,17 +645,22 @@ static ListBase *cloth_brush_collider_cache_create(Depsgraph *depsgraph) DEG_ITER_OBJECT_FLAG_DUPLI) { CollisionModifierData *cmd = (CollisionModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Collision); - if (cmd && cmd->bvhtree) { - if (cache == NULL) { - cache = MEM_callocN(sizeof(ListBase), "ColliderCache array"); - } + if (!cmd) { + continue; + } - ColliderCache *col = MEM_callocN(sizeof(ColliderCache), "ColliderCache"); - col->ob = ob; - col->collmd = cmd; - collision_move_object(cmd, 1.0, 0.0, true); - BLI_addtail(cache, col); + if (!cmd->bvhtree) { + continue; } + if (cache == NULL) { + cache = MEM_callocN(sizeof(ListBase), "ColliderCache array"); + } + + ColliderCache *col = MEM_callocN(sizeof(ColliderCache), "ColliderCache"); + col->ob = ob; + col->collmd = cmd; + collision_move_object(cmd, 1.0, 0.0, true); + BLI_addtail(cache, col); } DEG_OBJECT_ITER_END; return cache; @@ -734,26 +740,27 @@ static void cloth_brush_solve_collision(Object *object, &col, raycast_flag); - if (hit.index != -1) { - - float collision_disp[3]; - float movement_disp[3]; - mul_v3_v3fl(collision_disp, hit.no, 0.005f); - sub_v3_v3v3(movement_disp, pos_world_space, prev_pos_world_space); - float friction_plane[4]; - float pos_on_friction_plane[3]; - plane_from_point_normal_v3(friction_plane, hit.co, hit.no); - closest_to_plane_v3(pos_on_friction_plane, friction_plane, pos_world_space); - sub_v3_v3v3(movement_disp, pos_on_friction_plane, hit.co); - - /* TODO(pablodp606): This can be exposed in a brush/filter property as friction. */ - mul_v3_fl(movement_disp, 0.35f); - - copy_v3_v3(cloth_sim->pos[i], hit.co); - add_v3_v3(cloth_sim->pos[i], movement_disp); - add_v3_v3(cloth_sim->pos[i], collision_disp); - mul_v3_m4v3(cloth_sim->pos[i], obmat_inv, cloth_sim->pos[i]); + if (hit.index == -1) { + continue; } + + float collision_disp[3]; + float movement_disp[3]; + mul_v3_v3fl(collision_disp, hit.no, 0.005f); + sub_v3_v3v3(movement_disp, pos_world_space, prev_pos_world_space); + float friction_plane[4]; + float pos_on_friction_plane[3]; + plane_from_point_normal_v3(friction_plane, hit.co, hit.no); + closest_to_plane_v3(pos_on_friction_plane, friction_plane, pos_world_space); + sub_v3_v3v3(movement_disp, pos_on_friction_plane, hit.co); + + /* TODO(pablodp606): This can be exposed in a brush/filter property as friction. */ + mul_v3_fl(movement_disp, 0.35f); + + copy_v3_v3(cloth_sim->pos[i], hit.co); + add_v3_v3(cloth_sim->pos[i], movement_disp); + add_v3_v3(cloth_sim->pos[i], collision_disp); + mul_v3_m4v3(cloth_sim->pos[i], obmat_inv, cloth_sim->pos[i]); } } @@ -784,38 +791,40 @@ static void do_cloth_brush_solve_simulation_task_cb_ex( ss->cache ? cloth_brush_simulation_falloff_get( brush, ss->cache->radius, sim_location, cloth_sim->init_pos[vd.index]) : 1.0f; - if (sim_factor > 0.0f) { - int i = vd.index; - float temp[3]; - copy_v3_v3(temp, cloth_sim->pos[i]); + if (sim_factor <= 0.0f) { + continue; + } - mul_v3_fl(cloth_sim->acceleration[i], time_step); + int i = vd.index; + float temp[3]; + copy_v3_v3(temp, cloth_sim->pos[i]); - float pos_diff[3]; - sub_v3_v3v3(pos_diff, cloth_sim->pos[i], cloth_sim->prev_pos[i]); - mul_v3_fl(pos_diff, (1.0f - cloth_sim->damping) * sim_factor); + mul_v3_fl(cloth_sim->acceleration[i], time_step); - const float mask_v = (1.0f - (vd.mask ? *vd.mask : 0.0f)) * - SCULPT_automasking_factor_get(automasking, ss, vd.index); + float pos_diff[3]; + sub_v3_v3v3(pos_diff, cloth_sim->pos[i], cloth_sim->prev_pos[i]); + mul_v3_fl(pos_diff, (1.0f - cloth_sim->damping) * sim_factor); - madd_v3_v3fl(cloth_sim->pos[i], pos_diff, mask_v); - madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v); + const float mask_v = (1.0f - (vd.mask ? *vd.mask : 0.0f)) * + SCULPT_automasking_factor_get(automasking, ss, vd.index); - if (cloth_sim->collider_list != NULL) { - cloth_brush_solve_collision(data->ob, cloth_sim, i); - } + madd_v3_v3fl(cloth_sim->pos[i], pos_diff, mask_v); + madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v); - copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); + if (cloth_sim->collider_list != NULL) { + cloth_brush_solve_collision(data->ob, cloth_sim, i); + } - copy_v3_v3(cloth_sim->prev_pos[i], temp); - copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); - copy_v3_fl(cloth_sim->acceleration[i], 0.0f); + copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); - copy_v3_v3(vd.co, cloth_sim->pos[vd.index]); + copy_v3_v3(cloth_sim->prev_pos[i], temp); + copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); + copy_v3_fl(cloth_sim->acceleration[i], 0.0f); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + copy_v3_v3(vd.co, cloth_sim->pos[vd.index]); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c index aa1d407dc24..ddf7ba1e412 100644 --- a/source/blender/editors/sculpt_paint/sculpt_detail.c +++ b/source/blender/editors/sculpt_paint/sculpt_detail.c @@ -24,46 +24,29 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" -#include "BLI_hash.h" #include "BLI_math.h" -#include "BLI_task.h" #include "BLT_translation.h" #include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "BKE_brush.h" #include "BKE_context.h" -#include "BKE_mesh.h" -#include "BKE_mesh_mapping.h" -#include "BKE_object.h" #include "BKE_paint.h" #include "BKE_pbvh.h" -#include "BKE_scene.h" #include "BKE_screen.h" #include "DEG_depsgraph.h" #include "WM_api.h" -#include "WM_message.h" -#include "WM_toolsystem.h" #include "WM_types.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_sculpt.h" #include "ED_view3d.h" -#include "paint_intern.h" #include "sculpt_intern.h" #include "RNA_access.h" #include "RNA_define.h" -#include "UI_interface.h" - -#include "bmesh.h" - #include <math.h> #include <stdlib.h> diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index 1fba958d695..df03d2adeaf 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -148,40 +148,42 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, float poly_center[3]; BKE_mesh_calc_poly_center(p, &ss->mloop[p->loopstart], mvert, poly_center); - if (sculpt_brush_test_sq_fn(&test, poly_center)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) { - ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set); - } + if (!sculpt_brush_test_sq_fn(&test, poly_center)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) { + ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set); } } } else if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) { { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - if (fade > 0.05f) { - SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set); - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + if (fade > 0.05f) { + SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set); } } } @@ -205,7 +207,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, ss, &test, data->brush->falloff_shape); const bool relax_face_sets = !(ss->cache->iteration_count % 3 == 0); - /* This operations needs a stregth tweak as the relax deformation is too weak by default. */ + /* This operations needs a strength tweak as the relax deformation is too weak by default. */ if (relax_face_sets) { bstrength *= 2.0f; } @@ -214,23 +216,26 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - if (relax_face_sets != SCULPT_vertex_has_unique_face_set(ss, vd.index)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.index)) { + continue; + } - SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co); + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -313,7 +318,7 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) const int mode = RNA_enum_get(op->ptr, "mode"); - /* Dyntopo not suported. */ + /* Dyntopo not supported. */ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { return OPERATOR_CANCELLED; } @@ -582,44 +587,49 @@ static void sculpt_face_sets_init_flood_fill(Object *ob, int next_face_set = 1; for (int i = 0; i < totfaces; i++) { - if (!BLI_BITMAP_TEST(visited_faces, i)) { - GSQueue *queue; - queue = BLI_gsqueue_new(sizeof(int)); - - face_sets[i] = next_face_set; - BLI_BITMAP_ENABLE(visited_faces, i); - BLI_gsqueue_push(queue, &i); - - while (!BLI_gsqueue_is_empty(queue)) { - int from_f; - BLI_gsqueue_pop(queue, &from_f); - - BMFace *f, *f_neighbor; - BMEdge *ed; - BMIter iter_a, iter_b; - - f = BM_face_at_index(bm, from_f); - - BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) { - BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) { - if (f_neighbor != f) { - int neighbor_face_index = BM_elem_index_get(f_neighbor); - if (!BLI_BITMAP_TEST(visited_faces, neighbor_face_index)) { - if (test(bm, f, ed, f_neighbor, threshold)) { - face_sets[neighbor_face_index] = next_face_set; - BLI_BITMAP_ENABLE(visited_faces, neighbor_face_index); - BLI_gsqueue_push(queue, &neighbor_face_index); - } - } - } + if (BLI_BITMAP_TEST(visited_faces, i)) { + continue; + } + GSQueue *queue; + queue = BLI_gsqueue_new(sizeof(int)); + + face_sets[i] = next_face_set; + BLI_BITMAP_ENABLE(visited_faces, i); + BLI_gsqueue_push(queue, &i); + + while (!BLI_gsqueue_is_empty(queue)) { + int from_f; + BLI_gsqueue_pop(queue, &from_f); + + BMFace *f, *f_neighbor; + BMEdge *ed; + BMIter iter_a, iter_b; + + f = BM_face_at_index(bm, from_f); + + BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) { + BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) { + if (f_neighbor == f) { + continue; } + int neighbor_face_index = BM_elem_index_get(f_neighbor); + if (BLI_BITMAP_TEST(visited_faces, neighbor_face_index)) { + continue; + } + if (!test(bm, f, ed, f_neighbor, threshold)) { + continue; + } + + face_sets[neighbor_face_index] = next_face_set; + BLI_BITMAP_ENABLE(visited_faces, neighbor_face_index); + BLI_gsqueue_push(queue, &neighbor_face_index); } } + } - next_face_set += 1; + next_face_set += 1; - BLI_gsqueue_free(queue); - } + BLI_gsqueue_free(queue); } MEM_SAFE_FREE(visited_faces); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index e11894a8c01..3cf6a8cc561 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -553,7 +553,7 @@ static void mesh_filter_sharpen_init(SculptSession *ss, filter_cache->sharpen_factor[i] = 1.0f - pow2f(1.0f - filter_cache->sharpen_factor[i]); } - /* Smooth the calculated factors and directions to remove high frecuency detail. */ + /* Smooth the calculated factors and directions to remove high frequency detail. */ for (int smooth_iterations = 0; smooth_iterations < filter_cache->sharpen_curvature_smooth_iterations; smooth_iterations++) { diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index d1e17c7e59b..f90cf366ed9 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -511,7 +511,7 @@ void SCULPT_boundary_edges_preview_draw(const uint gpuattr, const float outline_alpha); void SCULPT_boundary_pivot_line_preview_draw(const uint gpuattr, struct SculptSession *ss); -/* Multiplane Scrape Brush. */ +/* Multi-plane Scrape Brush. */ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode); void SCULPT_multiplane_scrape_preview_draw(const uint gpuattr, Brush *brush, diff --git a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c index e47a94dff90..cfc31e1dcdd 100644 --- a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c +++ b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c @@ -88,38 +88,39 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float local_co[3]; - float normal[3]; - if (vd.no) { - normal_short_to_float_v3(normal, vd.no); - } - else { - copy_v3_v3(normal, vd.fno); - } - mul_v3_m4v3(local_co, mat, vd.co); - /* Use the brush falloff to weight the sampled normals. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - /* Sample the normal and area of the +X and -X axis individually. */ - if (local_co[0] > 0.0f) { - madd_v3_v3fl(mssd->area_nos[0], normal, fade); - add_v3_v3(mssd->area_cos[0], vd.co); - mssd->area_count[0]++; - } - else { - madd_v3_v3fl(mssd->area_nos[1], normal, fade); - add_v3_v3(mssd->area_cos[1], vd.co); - mssd->area_count[1]++; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + float local_co[3]; + float normal[3]; + if (vd.no) { + normal_short_to_float_v3(normal, vd.no); + } + else { + copy_v3_v3(normal, vd.fno); + } + mul_v3_m4v3(local_co, mat, vd.co); + /* Use the brush falloff to weight the sampled normals. */ + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + /* Sample the normal and area of the +X and -X axis individually. */ + if (local_co[0] > 0.0f) { + madd_v3_v3fl(mssd->area_nos[0], normal, fade); + add_v3_v3(mssd->area_cos[0], vd.co); + mssd->area_count[0]++; + } + else { + madd_v3_v3fl(mssd->area_nos[1], normal, fade); + add_v3_v3(mssd->area_cos[1], vd.co); + mssd->area_count[1]++; } BKE_pbvh_vertex_iter_end; } @@ -168,56 +169,61 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float local_co[3]; - bool deform = false; - - mul_v3_m4v3(local_co, mat, vd.co); - - if (local_co[0] > 0.0f) { - deform = !SCULPT_plane_point_side(vd.co, scrape_planes[0]); - } - else { - deform = !SCULPT_plane_point_side(vd.co, scrape_planes[1]); - } - - if (angle < 0.0f) { - deform = true; - } - - if (deform) { - float intr[3]; - float val[3]; - - if (local_co[0] > 0.0f) { - closest_to_plane_normalized_v3(intr, scrape_planes[0], vd.co); - } - else { - closest_to_plane_normalized_v3(intr, scrape_planes[1], vd.co); - } - - sub_v3_v3v3(val, intr, vd.co); - if (SCULPT_plane_trim(ss->cache, brush, val)) { - /* Deform the local space along the Y axis to avoid artifacts on curved strokes. */ - /* This produces a not round brush tip. */ - local_co[1] *= 2.0f; - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - len_v3(local_co), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + + float local_co[3]; + bool deform = false; + + mul_v3_m4v3(local_co, mat, vd.co); + + if (local_co[0] > 0.0f) { + deform = !SCULPT_plane_point_side(vd.co, scrape_planes[0]); + } + else { + deform = !SCULPT_plane_point_side(vd.co, scrape_planes[1]); + } + + if (angle < 0.0f) { + deform = true; + } + + if (!deform) { + continue; + } + + float intr[3]; + float val[3]; + + if (local_co[0] > 0.0f) { + closest_to_plane_normalized_v3(intr, scrape_planes[0], vd.co); + } + else { + closest_to_plane_normalized_v3(intr, scrape_planes[1], vd.co); + } + + sub_v3_v3v3(val, intr, vd.co); + if (!SCULPT_plane_trim(ss->cache, brush, val)) { + continue; + } + /* Deform the local space along the Y axis to avoid artifacts on curved strokes. */ + /* This produces a not round brush tip. */ + local_co[1] *= 2.0f; + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + len_v3(local_co), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c index 39320f3f558..5fdf8415f28 100644 --- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c @@ -87,24 +87,25 @@ static void do_color_smooth_task_cb_exec(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float smooth_color[4]; - SCULPT_neighbor_color_average(ss, smooth_color, vd.index); - blend_color_interpolate_float(vd.col, vd.col, smooth_color, fade); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float smooth_color[4]; + SCULPT_neighbor_color_average(ss, smooth_color, vd.index); + blend_color_interpolate_float(vd.col, vd.col, smooth_color, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -153,46 +154,49 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata, distance_to_stroke_location = sqrtf(test.dist); } - if (affect_vertex) { - float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - distance_to_stroke_location, - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - /* Density. */ - float noise = 1.0f; - const float density = ss->cache->paint_brush.density; - if (density < 1.0f) { - const float hash_noise = BLI_hash_int_01(ss->cache->density_seed * 1000 * vd.index); - if (hash_noise > density) { - noise = density * hash_noise; - fade = fade * noise; - } + if (!affect_vertex) { + continue; + } + + float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + distance_to_stroke_location, + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + /* Density. */ + float noise = 1.0f; + const float density = ss->cache->paint_brush.density; + if (density < 1.0f) { + const float hash_noise = BLI_hash_int_01(ss->cache->density_seed * 1000 * vd.index); + if (hash_noise > density) { + noise = density * hash_noise; + fade = fade * noise; } + } - /* Brush paint color, brush test falloff and flow. */ - float paint_color[4]; - float wet_mix_color[4]; - float buffer_color[4]; + /* Brush paint color, brush test falloff and flow. */ + float paint_color[4]; + float wet_mix_color[4]; + float buffer_color[4]; - mul_v4_v4fl(paint_color, brush_color, fade * ss->cache->paint_brush.flow); - mul_v4_v4fl(wet_mix_color, data->wet_mix_sampled_color, fade * ss->cache->paint_brush.flow); + mul_v4_v4fl(paint_color, brush_color, fade * ss->cache->paint_brush.flow); + mul_v4_v4fl(wet_mix_color, data->wet_mix_sampled_color, fade * ss->cache->paint_brush.flow); - /* Interpolate with the wet_mix color for wet paint mixing. */ - blend_color_interpolate_float( - paint_color, paint_color, wet_mix_color, ss->cache->paint_brush.wet_mix); - blend_color_mix_float(color_buffer->color[vd.i], color_buffer->color[vd.i], paint_color); + /* Interpolate with the wet_mix color for wet paint mixing. */ + blend_color_interpolate_float( + paint_color, paint_color, wet_mix_color, ss->cache->paint_brush.wet_mix); + blend_color_mix_float(color_buffer->color[vd.i], color_buffer->color[vd.i], paint_color); - /* Final mix over the original color using brush alpha. */ - mul_v4_v4fl(buffer_color, color_buffer->color[vd.i], brush->alpha); + /* Final mix over the original color using brush alpha. */ + mul_v4_v4fl(buffer_color, color_buffer->color[vd.i], brush->alpha); + + IMB_blend_color_float(vd.col, orig_data.col, buffer_color, brush->blend); - IMB_blend_color_float(vd.col, orig_data.col, buffer_color, brush->blend); - } CLAMP4(vd.col, 0.0f, 1.0f); if (vd.mvert) { @@ -225,10 +229,12 @@ static void do_sample_wet_paint_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - add_v4_v4(swptd->color, vd.col); - swptd->tot_samples++; + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; } + + add_v4_v4(swptd->color, vd.col); + swptd->tot_samples++; } BKE_pbvh_vertex_iter_end; } @@ -380,59 +386,61 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float current_disp[3]; - float current_disp_norm[3]; - float interp_color[4]; - copy_v4_v4(interp_color, ss->cache->prev_colors[vd.index]); - - switch (brush->smear_deform_type) { - case BRUSH_SMEAR_DEFORM_DRAG: - sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); - break; - case BRUSH_SMEAR_DEFORM_PINCH: - sub_v3_v3v3(current_disp, ss->cache->location, vd.co); - break; - case BRUSH_SMEAR_DEFORM_EXPAND: - sub_v3_v3v3(current_disp, vd.co, ss->cache->location); - break; - } - normalize_v3_v3(current_disp_norm, current_disp); - mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); - - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { - float vertex_disp[3]; - float vertex_disp_norm[3]; - sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); - const float *neighbor_color = ss->cache->prev_colors[ni.index]; - normalize_v3_v3(vertex_disp_norm, vertex_disp); - if (dot_v3v3(current_disp_norm, vertex_disp_norm) < 0.0f) { - const float color_interp = clamp_f( - -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); - float color_mix[4]; - copy_v4_v4(color_mix, neighbor_color); - mul_v4_fl(color_mix, color_interp * fade); - blend_color_mix_float(interp_color, interp_color, color_mix); - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float current_disp[3]; + float current_disp_norm[3]; + float interp_color[4]; + copy_v4_v4(interp_color, ss->cache->prev_colors[vd.index]); + + switch (brush->smear_deform_type) { + case BRUSH_SMEAR_DEFORM_DRAG: + sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); + break; + case BRUSH_SMEAR_DEFORM_PINCH: + sub_v3_v3v3(current_disp, ss->cache->location, vd.co); + break; + case BRUSH_SMEAR_DEFORM_EXPAND: + sub_v3_v3v3(current_disp, vd.co, ss->cache->location); + break; + } + normalize_v3_v3(current_disp_norm, current_disp); + mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { + float vertex_disp[3]; + float vertex_disp_norm[3]; + sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); + const float *neighbor_color = ss->cache->prev_colors[ni.index]; + normalize_v3_v3(vertex_disp_norm, vertex_disp); + if (dot_v3v3(current_disp_norm, vertex_disp_norm) >= 0.0f) { + continue; } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + const float color_interp = clamp_f( + -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); + float color_mix[4]; + copy_v4_v4(color_mix, neighbor_color); + mul_v4_fl(color_mix, color_interp * fade); + blend_color_mix_float(interp_color, interp_color, color_mix); + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); - blend_color_interpolate_float(vd.col, ss->cache->prev_colors[vd.index], interp_color, fade); + blend_color_interpolate_float(vd.col, ss->cache->prev_colors[vd.index], interp_color, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c index 1bf9ba60073..a85f805894b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.c +++ b/source/blender/editors/sculpt_paint/sculpt_pose.c @@ -490,50 +490,52 @@ static bool pose_face_sets_floodfill_cb( is_vertex_valid = SCULPT_vertex_has_face_set(ss, index, data->current_face_set); } - if (is_vertex_valid) { - - if (!BLI_BITMAP_TEST(data->is_weighted, index)) { - data->pose_factor[index] = 1.0f; - BLI_BITMAP_ENABLE(data->is_weighted, index); - visit_next = true; - } - - /* Fallback origin accumulation. */ - if (symmetry_check) { - add_v3_v3(data->fallback_origin, SCULPT_vertex_co_get(ss, index)); - data->fallback_count++; - } - - if (symmetry_check && !SCULPT_vertex_has_unique_face_set(ss, index)) { + if (!is_vertex_valid) { + return visit_next; + } - /* We only add coordinates for calculating the origin when it is possible to go from this - * vertex to another vertex in a valid face set for the next iteration. */ - bool count_as_boundary = false; + if (!BLI_BITMAP_TEST(data->is_weighted, index)) { + data->pose_factor[index] = 1.0f; + BLI_BITMAP_ENABLE(data->is_weighted, index); + visit_next = true; + } - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) { - int next_face_set_candidate = SCULPT_vertex_face_set_get(ss, ni.index); + /* Fallback origin accumulation. */ + if (symmetry_check) { + add_v3_v3(data->fallback_origin, SCULPT_vertex_co_get(ss, index)); + data->fallback_count++; + } - /* Check if we can get a valid face set for the next iteration from this neighbor. */ - if (SCULPT_vertex_has_unique_face_set(ss, ni.index) && - !BLI_gset_haskey(data->visited_face_sets, POINTER_FROM_INT(next_face_set_candidate))) { - if (!data->next_face_set_found) { - data->next_face_set = next_face_set_candidate; - data->next_vertex = ni.index; - data->next_face_set_found = true; - } - count_as_boundary = true; - } - } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + if (!symmetry_check || SCULPT_vertex_has_unique_face_set(ss, index)) { + return visit_next; + } - /* Origin accumulation. */ - if (count_as_boundary) { - add_v3_v3(data->pose_origin, SCULPT_vertex_co_get(ss, index)); - data->tot_co++; + /* We only add coordinates for calculating the origin when it is possible to go from this + * vertex to another vertex in a valid face set for the next iteration. */ + bool count_as_boundary = false; + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) { + int next_face_set_candidate = SCULPT_vertex_face_set_get(ss, ni.index); + + /* Check if we can get a valid face set for the next iteration from this neighbor. */ + if (SCULPT_vertex_has_unique_face_set(ss, ni.index) && + !BLI_gset_haskey(data->visited_face_sets, POINTER_FROM_INT(next_face_set_candidate))) { + if (!data->next_face_set_found) { + data->next_face_set = next_face_set_candidate; + data->next_vertex = ni.index; + data->next_face_set_found = true; } + count_as_boundary = true; } } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + + /* Origin accumulation. */ + if (count_as_boundary) { + add_v3_v3(data->pose_origin, SCULPT_vertex_co_get(ss, index)); + data->tot_co++; + } return visit_next; } @@ -738,7 +740,7 @@ static SculptPoseIKChain *pose_ik_chain_init_topology(Sculpt *sd, * iteration an the current iteration. */ for (int j = 0; j < totvert; j++) { ik_chain->segments[i].weights[j] = pose_factor_grow[j] - pose_factor_grow_prev[j]; - /* Store the current grow factor status for the next interation. */ + /* Store the current grow factor status for the next iteration. */ pose_factor_grow_prev[j] = pose_factor_grow[j]; } } diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 87ee7480c92..4c0795eb0f7 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -231,24 +231,26 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata, const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float disp[3]; - madd_v3_v3v3fl(disp, vd.co, ss->cache->detail_directions[vd.index], fade); - SCULPT_clip(sd, ss, vd.co, disp); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float disp[3]; + madd_v3_v3v3fl(disp, vd.co, ss->cache->detail_directions[vd.index], fade); + SCULPT_clip(sd, ss, vd.co, disp); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -312,33 +314,34 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor( - ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), - vd.index, - thread_id); - if (smooth_mask) { - float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask; - val *= fade * bstrength; - *vd.mask += val; - CLAMP(*vd.mask, 0.0f, 1.0f); - } - else { - float avg[3], val[3]; - SCULPT_neighbor_coords_average_interior(ss, avg, vd.index); - sub_v3_v3v3(val, avg, vd.co); - madd_v3_v3v3fl(val, vd.co, val, fade); - SCULPT_clip(sd, ss, vd.co, val); - } - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor( + ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), + vd.index, + thread_id); + if (smooth_mask) { + float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask; + val *= fade * bstrength; + *vd.mask += val; + CLAMP(*vd.mask, 0.0f, 1.0f); + } + else { + float avg[3], val[3]; + SCULPT_neighbor_coords_average_interior(ss, avg, vd.index); + sub_v3_v3v3(val, avg, vd.co); + madd_v3_v3v3fl(val, vd.co, val, fade); + SCULPT_clip(sd, ss, vd.co, val); + } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -473,32 +476,28 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex( BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float disp[3]; - SCULPT_surface_smooth_laplacian_step(ss, - disp, - vd.co, - ss->cache->surface_smooth_laplacian_disp, - vd.index, - orig_data.co, - alpha); - madd_v3_v3fl(vd.co, disp, clamp_f(fade, 0.0f, 1.0f)); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float disp[3]; + SCULPT_surface_smooth_laplacian_step( + ss, disp, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, orig_data.co, alpha); + madd_v3_v3fl(vd.co, disp, clamp_f(fade, 0.0f, 1.0f)); + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } - BKE_pbvh_vertex_iter_end; } + BKE_pbvh_vertex_iter_end; } static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( @@ -519,19 +518,20 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - SCULPT_surface_smooth_displace_step( - ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + SCULPT_surface_smooth_displace_step( + ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade); } BKE_pbvh_vertex_iter_end; } diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 938080b392d..ec103bd2b98 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -1527,9 +1527,14 @@ static void sculpt_undosys_step_decode_redo(struct bContext *C, } } -static void sculpt_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir, bool UNUSED(is_final)) +static void sculpt_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir dir, + bool UNUSED(is_final)) { + BLI_assert(dir != STEP_INVALID); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); /* Ensure sculpt mode. */ @@ -1568,10 +1573,10 @@ static void sculpt_undosys_step_decode( } SculptUndoStep *us = (SculptUndoStep *)us_p; - if (dir < 0) { + if (dir == STEP_UNDO) { sculpt_undosys_step_decode_undo(C, depsgraph, us); } - else { + else if (dir == STEP_REDO) { sculpt_undosys_step_decode_redo(C, depsgraph, us); } } diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 34617804888..85616f6356d 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -31,7 +31,6 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "DNA_packedFile_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" #include "DNA_sound_types.h" @@ -877,7 +876,7 @@ static void SOUND_OT_unpack(wmOperatorType *ot) /* properties */ RNA_def_enum( ot->srna, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack"); - /* XXX, weark!, will fail with library, name collisions */ + /* XXX: weak!, will fail with library, name collisions */ RNA_def_string( ot->srna, "id", NULL, MAX_ID_NAME - 2, "Sound Name", "Sound data-block name to unpack"); } diff --git a/source/blender/editors/space_action/action_buttons.c b/source/blender/editors/space_action/action_buttons.c index 5e1c205f1d4..dfc3789a26c 100644 --- a/source/blender/editors/space_action/action_buttons.c +++ b/source/blender/editors/space_action/action_buttons.c @@ -26,33 +26,10 @@ #include <stdio.h> #include <string.h> -#include "DNA_anim_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" - -#include "MEM_guardedalloc.h" - #include "BLI_utildefines.h" -#include "BLT_translation.h" - #include "BKE_context.h" -#include "BKE_curve.h" -#include "BKE_fcurve.h" #include "BKE_screen.h" -#include "BKE_unit.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "RNA_access.h" - -#include "ED_anim_api.h" -#include "ED_keyframing.h" -#include "ED_screen.h" - -#include "UI_interface.h" -#include "UI_resources.h" #include "action_intern.h" /* own include */ diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index f731fe23b7c..f8389d40831 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -73,7 +73,7 @@ /* ************************************************************************** */ /* POSE MARKERS STUFF */ -/* *************************** Localise Markers ***************************** */ +/* *************************** Localize Markers ***************************** */ /* ensure that there is: * 1) an active action editor @@ -322,7 +322,7 @@ static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min, bAnimListElem *ale; int filter; - /* NOTE: not bool, since we want prioritise individual channels over expanders */ + /* NOTE: not bool, since we want prioritize individual channels over expanders. */ short found = 0; /* get all items - we need to do it this way */ @@ -346,7 +346,7 @@ static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min, found = acf->channel_role; /* only stop our search when we've found an actual channel - * - datablock expanders get less priority so that we don't abort prematurely + * - data-block expanders get less priority so that we don't abort prematurely */ if (found == ACHANNEL_ROLE_CHANNEL) { break; diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 7422c05511c..7821458d1e5 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -27,9 +27,6 @@ #include "DNA_space_types.h" #include "ED_anim_api.h" -#include "ED_markers.h" -#include "ED_object.h" -#include "ED_select_utils.h" #include "ED_transform.h" #include "action_intern.h" diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index ff0201f9702..722005235d3 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -55,7 +55,6 @@ #include "ED_space_api.h" #include "ED_time_scrub_ui.h" -#include "GPU_framebuffer.h" #include "action_intern.h" /* own include */ /* ******************** default callbacks for action space ***************** */ @@ -305,12 +304,11 @@ static void action_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void action_channel_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void action_channel_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -356,14 +354,13 @@ static void action_channel_region_listener(wmWindow *UNUSED(win), } } -static void saction_channel_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void saction_channel_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, area->spacedata.first, &ptr); @@ -401,12 +398,11 @@ static void saction_channel_region_message_subscribe(const struct bContext *UNUS } } -static void action_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void action_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -460,14 +456,14 @@ static void action_main_region_listener(wmWindow *UNUSED(win), } } -static void saction_main_region_message_subscribe(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void saction_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + Scene *scene = params->scene; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, area->spacedata.first, &ptr); @@ -502,15 +498,14 @@ static void saction_main_region_message_subscribe(const struct bContext *C, } /* Now run the general "channels region" one - since channels and main should be in sync */ - saction_channel_region_message_subscribe(C, workspace, scene, screen, area, region, mbus); + saction_channel_region_message_subscribe(params); } /* editor level listener */ -static void action_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void action_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceAction *saction = (SpaceAction *)area->spacedata.first; /* context changes */ @@ -660,12 +655,11 @@ static void action_listener(wmWindow *UNUSED(win), } } -static void action_header_region_listener(wmWindow *UNUSED(win), - ScrArea *area, - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void action_header_region_listener(const wmRegionListenerParams *params) { + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; SpaceAction *saction = (SpaceAction *)area->spacedata.first; /* context changes */ @@ -737,12 +731,11 @@ static void action_buttons_area_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void action_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void action_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 10fa2c19919..817760615df 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -70,16 +70,13 @@ #include "io_ops.h" -/* only call once on startup, storage is global in BKE kernel listbase */ +/* Only called once on startup. storage is global in BKE kernel listbase. */ void ED_spacetypes_init(void) { - const ListBase *spacetypes; - SpaceType *type; - - /* UI_UNIT_X is now a variable, is used in some spacetype inits? */ + /* UI unit is a variable, may be used in some space type inits. */ U.widget_unit = 20; - /* create space types */ + /* Create space types. */ ED_spacetype_outliner(); ED_spacetype_view3d(); ED_spacetype_ipo(); @@ -98,9 +95,8 @@ void ED_spacetypes_init(void) ED_spacetype_clip(); ED_spacetype_statusbar(); ED_spacetype_topbar(); - // ... - /* register operator types for screen and all spaces */ + /* Register operator types for screen and all spaces. */ ED_operatortypes_userpref(); ED_operatortypes_workspace(); ED_operatortypes_scene(); @@ -132,7 +128,7 @@ void ED_spacetypes_init(void) ED_screen_user_menu_register(); - /* gizmo types */ + /* Gizmo types. */ ED_gizmotypes_button_2d(); ED_gizmotypes_dial_3d(); ED_gizmotypes_move_3d(); @@ -144,10 +140,10 @@ void ED_spacetypes_init(void) ED_gizmotypes_cage_3d(); ED_gizmotypes_snap_3d(); - /* register types for operators and gizmos */ - spacetypes = BKE_spacetypes_list(); - for (type = spacetypes->first; type; type = type->next) { - /* init gizmo types first, operator-types need them */ + /* Register types for operators and gizmos. */ + const ListBase *spacetypes = BKE_spacetypes_list(); + LISTBASE_FOREACH (const SpaceType *, type, spacetypes) { + /* Initialize gizmo types first, operator types need them. */ if (type->gizmos) { type->gizmos(); } @@ -159,11 +155,8 @@ void ED_spacetypes_init(void) void ED_spacemacros_init(void) { - const ListBase *spacetypes; - SpaceType *type; - - /* Macros's must go last since they reference other operators. - * We need to have them go after python operators too */ + /* Macros must go last since they reference other operators. + * They need to be registered after python operators too. */ ED_operatormacros_armature(); ED_operatormacros_mesh(); ED_operatormacros_uvedit(); @@ -180,24 +173,21 @@ void ED_spacemacros_init(void) ED_operatormacros_paint(); ED_operatormacros_gpencil(); - /* register dropboxes (can use macros) */ - spacetypes = BKE_spacetypes_list(); - for (type = spacetypes->first; type; type = type->next) { + /* Register dropboxes (can use macros). */ + const ListBase *spacetypes = BKE_spacetypes_list(); + LISTBASE_FOREACH (const SpaceType *, type, spacetypes) { if (type->dropboxes) { type->dropboxes(); } } } -/* called in wm.c */ -/* keymap definitions are registered only once per WM initialize, usually on file read, - * using the keymap the actual areas/regions add the handlers */ +/** + * \note Keymap definitions are registered only once per WM initialize, + * usually on file read, using the keymap the actual areas/regions add the handlers. + * \note Called in wm.c. */ void ED_spacetypes_keymap(wmKeyConfig *keyconf) { - const ListBase *spacetypes; - SpaceType *stype; - ARegionType *atype; - ED_keymap_screen(keyconf); ED_keymap_anim(keyconf); ED_keymap_animchannels(keyconf); @@ -219,20 +209,20 @@ void ED_spacetypes_keymap(wmKeyConfig *keyconf) ED_keymap_transform(keyconf); - spacetypes = BKE_spacetypes_list(); - for (stype = spacetypes->first; stype; stype = stype->next) { - if (stype->keymap) { - stype->keymap(keyconf); + const ListBase *spacetypes = BKE_spacetypes_list(); + LISTBASE_FOREACH (const SpaceType *, type, spacetypes) { + if (type->keymap) { + type->keymap(keyconf); } - for (atype = stype->regiontypes.first; atype; atype = atype->next) { - if (atype->keymap) { - atype->keymap(keyconf); + LISTBASE_FOREACH (ARegionType *, region_type, &type->regiontypes) { + if (region_type->keymap) { + region_type->keymap(keyconf); } } } } -/* ********************** custom drawcall api ***************** */ +/* ********************** Custom Draw Call API ***************** */ typedef struct RegionDrawCB { struct RegionDrawCB *next, *prev; @@ -261,9 +251,7 @@ void *ED_region_draw_cb_activate(ARegionType *art, void ED_region_draw_cb_exit(ARegionType *art, void *handle) { - RegionDrawCB *rdc; - - for (rdc = art->drawcalls.first; rdc; rdc = rdc->next) { + LISTBASE_FOREACH (RegionDrawCB *, rdc, &art->drawcalls) { if (rdc == (RegionDrawCB *)handle) { BLI_remlink(&art->drawcalls, rdc); MEM_freeN(rdc); @@ -274,9 +262,7 @@ void ED_region_draw_cb_exit(ARegionType *art, void *handle) void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type) { - RegionDrawCB *rdc; - - for (rdc = region->type->drawcalls.first; rdc; rdc = rdc->next) { + LISTBASE_FOREACH (RegionDrawCB *, rdc, ®ion->type->drawcalls) { if (rdc->type == type) { rdc->draw(C, region, rdc->customdata); @@ -301,7 +287,7 @@ static void xxx_free(SpaceLink *UNUSED(sl)) { } -/* spacetype; init callback for usage, should be redoable */ +/* spacetype; init callback for usage, should be re-doable. */ static void xxx_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area)) { diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index e2b889bece1..5f347451c4a 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -33,8 +33,6 @@ #include "DNA_armature_types.h" #include "DNA_brush_types.h" -#include "DNA_collection_types.h" -#include "DNA_light_types.h" #include "DNA_linestyle_types.h" #include "DNA_material_types.h" #include "DNA_node_types.h" @@ -53,7 +51,6 @@ #include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_screen.h" -#include "BKE_texture.h" #include "RNA_access.h" diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 6f743eb1a6b..4847e8738df 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -52,10 +52,7 @@ #include "BKE_node.h" #include "BKE_paint.h" #include "BKE_particle.h" -#include "BKE_scene.h" -#include "BKE_workspace.h" #ifdef WITH_FREESTYLE -# include "BKE_freestyle.h" #endif #include "RNA_access.h" diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index e50ca2ec92b..07bc1d42c3f 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -514,12 +514,11 @@ static void buttons_main_region_layout(const bContext *C, ARegion *region) sbuts->mainbo = sbuts->mainb; } -static void buttons_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void buttons_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCREEN: @@ -567,15 +566,13 @@ static void buttons_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void buttons_header_region_message_subscribe(const bContext *UNUSED(C), - WorkSpace *UNUSED(workspace), - Scene *UNUSED(scene), - bScreen *UNUSED(screen), - ScrArea *area, - ARegion *region, - struct wmMsgBus *mbus) +static void buttons_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ScrArea *area = params->area; + ARegion *region = params->region; SpaceProperties *sbuts = area->spacedata.first; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, @@ -621,14 +618,12 @@ static void buttons_navigation_bar_region_draw(const bContext *C, ARegion *regio ED_region_panels_draw(C, region); } -static void buttons_navigation_bar_region_message_subscribe(const bContext *UNUSED(C), - WorkSpace *UNUSED(workspace), - Scene *UNUSED(scene), - bScreen *UNUSED(screen), - ScrArea *UNUSED(area), - ARegion *region, - struct wmMsgBus *mbus) +static void buttons_navigation_bar_region_message_subscribe( + const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, @@ -657,11 +652,10 @@ static void buttons_area_redraw(ScrArea *area, short buttons) * \{ */ /* reused! */ -static void buttons_area_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void buttons_area_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceProperties *sbuts = area->spacedata.first; /* context changes */ diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 81bae26efeb..632f3c5147f 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -46,7 +46,6 @@ #include "DEG_depsgraph.h" #include "ED_clip.h" -#include "ED_gpencil.h" #include "ED_screen.h" #include "UI_interface.h" diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index bd11a746e11..af1d082d317 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -327,118 +327,18 @@ void ED_clip_update_frame(const Main *mainp, int cfra) } } -static bool selected_tracking_boundbox(SpaceClip *sc, float min[2], float max[2]) +bool ED_clip_view_selection(const bContext *C, ARegion *UNUSED(region), bool fit) { - MovieClip *clip = ED_space_clip_get_clip(sc); - MovieTrackingTrack *track; - int width, height; - bool ok = false; - ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); - int framenr = ED_space_clip_get_clip_frame_number(sc); - - INIT_MINMAX2(min, max); - - ED_space_clip_get_size(sc, &width, &height); - - track = tracksbase->first; - while (track) { - if (TRACK_VIEW_SELECTED(sc, track)) { - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); - - if (marker) { - float pos[3]; - - pos[0] = marker->pos[0] + track->offset[0]; - pos[1] = marker->pos[1] + track->offset[1]; - pos[2] = 0.0f; - - /* undistortion happens for normalized coords */ - if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) { - /* undistortion happens for normalized coords */ - ED_clip_point_undistorted_pos(sc, pos, pos); - } - - pos[0] *= width; - pos[1] *= height; - - mul_v3_m4v3(pos, sc->stabmat, pos); - - minmax_v2v2_v2(min, max, pos); - - ok = true; - } - } - - track = track->next; - } - - return ok; -} - -static bool selected_boundbox(const bContext *C, float min[2], float max[2]) -{ - SpaceClip *sc = CTX_wm_space_clip(C); - if (sc->mode == SC_MODE_TRACKING) { - return selected_tracking_boundbox(sc, min, max); - } - - if (ED_mask_selected_minmax(C, min, max)) { - MovieClip *clip = ED_space_clip_get_clip(sc); - int width, height; - ED_space_clip_get_size(sc, &width, &height); - BKE_mask_coord_to_movieclip(clip, &sc->user, min, min); - BKE_mask_coord_to_movieclip(clip, &sc->user, max, max); - min[0] *= width; - min[1] *= height; - max[0] *= width; - max[1] *= height; - return true; - } - return false; -} - -bool ED_clip_view_selection(const bContext *C, ARegion *region, bool fit) -{ - SpaceClip *sc = CTX_wm_space_clip(C); - int w, h, frame_width, frame_height; - float min[2], max[2]; - - ED_space_clip_get_size(sc, &frame_width, &frame_height); - - if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL)) { + float offset_x, offset_y; + float zoom; + if (!clip_view_calculate_view_selection(C, fit, &offset_x, &offset_y, &zoom)) { return false; } - if (!selected_boundbox(C, min, max)) { - return false; - } - - /* center view */ - clip_view_center_to_point( - sc, (max[0] + min[0]) / (2 * frame_width), (max[1] + min[1]) / (2 * frame_height)); - - w = max[0] - min[0]; - h = max[1] - min[1]; - - /* set zoom to see all selection */ - if (w > 0 && h > 0) { - int width, height; - float zoomx, zoomy, newzoom, aspx, aspy; - - ED_space_clip_get_aspect(sc, &aspx, &aspy); - - width = BLI_rcti_size_x(®ion->winrct) + 1; - height = BLI_rcti_size_y(®ion->winrct) + 1; - - zoomx = (float)width / w / aspx; - zoomy = (float)height / h / aspy; - - newzoom = 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)); - - if (fit || sc->zoom > newzoom) { - sc->zoom = newzoom; - } - } + SpaceClip *sc = CTX_wm_space_clip(C); + sc->xof = offset_x; + sc->yof = offset_y; + sc->zoom = zoom; return true; } @@ -1177,3 +1077,47 @@ void clip_start_prefetch_job(const bContext *C) /* and finally start the job */ WM_jobs_start(CTX_wm_manager(C), wm_job); } + +void ED_clip_view_lock_state_store(const bContext *C, ClipViewLockState *state) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + BLI_assert(space_clip != NULL); + + state->offset_x = space_clip->xof; + state->offset_y = space_clip->yof; + state->zoom = space_clip->zoom; + + state->lock_offset_x = 0.0f; + state->lock_offset_y = 0.0f; + + if ((space_clip->flag & SC_LOCK_SELECTION) == 0) { + return; + } + + if (!clip_view_calculate_view_selection( + C, false, &state->offset_x, &state->offset_y, &state->zoom)) { + return; + } + + state->lock_offset_x = space_clip->xlockof; + state->lock_offset_y = space_clip->ylockof; +} + +void ED_clip_view_lock_state_restore_no_jump(const bContext *C, const ClipViewLockState *state) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + BLI_assert(space_clip != NULL); + + if ((space_clip->flag & SC_LOCK_SELECTION) == 0) { + return; + } + + float offset_x, offset_y; + float zoom; + if (!clip_view_calculate_view_selection(C, false, &offset_x, &offset_y, &zoom)) { + return; + } + + space_clip->xlockof = state->offset_x + state->lock_offset_x - offset_x; + space_clip->ylockof = state->offset_y + state->lock_offset_y - offset_y; +} diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 4848ec72f79..202dc00e365 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -171,8 +171,15 @@ void clip_delete_plane_track(struct bContext *C, struct MovieClip *clip, struct MovieTrackingPlaneTrack *plane_track); +void clip_view_offset_for_center_to_point( + SpaceClip *sc, const float x, const float y, float *r_offset_x, float *r_offset_y); void clip_view_center_to_point(SpaceClip *sc, float x, float y); +bool clip_view_calculate_view_selection( + const struct bContext *C, bool fit, float *r_offset_x, float *r_offset_y, float *r_zoom); + +bool clip_view_has_locked_selection(const struct bContext *C); + void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene); /* tracking_ops.c */ @@ -191,6 +198,7 @@ void CLIP_OT_clear_solution(struct wmOperatorType *ot); void CLIP_OT_clear_track_path(struct wmOperatorType *ot); void CLIP_OT_join_tracks(struct wmOperatorType *ot); +void CLIP_OT_average_tracks(struct wmOperatorType *ot); void CLIP_OT_disable_markers(struct wmOperatorType *ot); void CLIP_OT_hide_tracks(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index cd4a1ffb526..38a05eef6e3 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -125,7 +125,7 @@ static void sclip_zoom_set(const bContext *C, dx = ((location[0] - 0.5f) * w - sc->xof) * (sc->zoom - oldzoom) / sc->zoom; dy = ((location[1] - 0.5f) * h - sc->yof) * (sc->zoom - oldzoom) / sc->zoom; - if (sc->flag & SC_LOCK_SELECTION) { + if (clip_view_has_locked_selection(C)) { sc->xlockof += dx; sc->ylockof += dy; } @@ -396,7 +396,7 @@ static void view_pan_init(bContext *C, wmOperator *op, const wmEvent *event) vpd->x = event->x; vpd->y = event->y; - if (sc->flag & SC_LOCK_SELECTION) { + if (clip_view_has_locked_selection(C)) { vpd->vec = &sc->xlockof; } else { @@ -434,7 +434,7 @@ static int view_pan_exec(bContext *C, wmOperator *op) RNA_float_get_array(op->ptr, "offset", offset); - if (sc->flag & SC_LOCK_SELECTION) { + if (clip_view_has_locked_selection(C)) { sc->xlockof += offset[0]; sc->ylockof += offset[1]; } @@ -569,7 +569,7 @@ static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event) WM_cursor_modal_set(win, WM_CURSOR_NSEW_SCROLL); } - if (U.viewzoom == USER_ZOOM_CONT) { + if (U.viewzoom == USER_ZOOM_CONTINUE) { /* needs a timer to continue redrawing */ vpd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); vpd->timer_lastdraw = PIL_check_seconds_timer(); @@ -662,7 +662,7 @@ static void view_zoom_apply( delta = -delta; } - if (U.viewzoom == USER_ZOOM_CONT) { + if (U.viewzoom == USER_ZOOM_CONTINUE) { SpaceClip *sclip = CTX_wm_space_clip(C); double time = PIL_check_seconds_timer(); float time_step = (float)(time - vpd->timer_lastdraw); @@ -1840,8 +1840,16 @@ void CLIP_OT_cursor_set(wmOperatorType *ot) static int lock_selection_togglee_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceClip *space_clip = CTX_wm_space_clip(C); + + ClipViewLockState lock_state; + ED_clip_view_lock_state_store(C, &lock_state); + space_clip->flag ^= SC_LOCK_SELECTION; + + ED_clip_view_lock_state_restore_no_jump(C, &lock_state); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CLIP, NULL); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c index b02f3fe16f6..da9e82043f0 100644 --- a/source/blender/editors/space_clip/clip_toolbar.c +++ b/source/blender/editors/space_clip/clip_toolbar.c @@ -23,29 +23,17 @@ #include <string.h> -#include "DNA_windowmanager_types.h" -#include "DNA_workspace_types.h" - #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BLT_translation.h" - #include "BKE_context.h" #include "BKE_screen.h" -#include "RNA_access.h" - -#include "WM_api.h" #include "WM_types.h" #include "ED_screen.h" -#include "ED_undo.h" - -#include "UI_interface.h" -#include "UI_resources.h" #include "clip_intern.h" /* own include */ diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index c7f2a027ba8..bb79eb34129 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -27,10 +27,12 @@ #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_rect.h" #include "BLI_utildefines.h" #include "BKE_animsys.h" #include "BKE_context.h" +#include "BKE_mask.h" #include "BKE_movieclip.h" #include "BKE_tracking.h" @@ -44,6 +46,7 @@ #include "WM_types.h" #include "ED_clip.h" +#include "ED_mask.h" #include "ED_screen.h" #include "UI_interface.h" @@ -395,16 +398,232 @@ void clip_delete_plane_track(bContext *C, MovieClip *clip, MovieTrackingPlaneTra DEG_id_tag_update(&clip->id, 0); } -void clip_view_center_to_point(SpaceClip *sc, float x, float y) +/* Calculate space clip offset to be centered at the given point. */ +void clip_view_offset_for_center_to_point( + SpaceClip *sc, const float x, const float y, float *r_offset_x, float *r_offset_y) { int width, height; + ED_space_clip_get_size(sc, &width, &height); + float aspx, aspy; + ED_space_clip_get_aspect(sc, &aspx, &aspy); + + *r_offset_x = (x - 0.5f) * width * aspx; + *r_offset_y = (y - 0.5f) * height * aspy; +} + +void clip_view_center_to_point(SpaceClip *sc, float x, float y) +{ + clip_view_offset_for_center_to_point(sc, x, y, &sc->xof, &sc->yof); +} + +static bool selected_tracking_boundbox(SpaceClip *sc, float min[2], float max[2]) +{ + MovieClip *clip = ED_space_clip_get_clip(sc); + MovieTrackingTrack *track; + int width, height; + bool ok = false; + ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); + int framenr = ED_space_clip_get_clip_frame_number(sc); + + INIT_MINMAX2(min, max); ED_space_clip_get_size(sc, &width, &height); - ED_space_clip_get_aspect(sc, &aspx, &aspy); - sc->xof = (x - 0.5f) * width * aspx; - sc->yof = (y - 0.5f) * height * aspy; + track = tracksbase->first; + while (track) { + if (TRACK_VIEW_SELECTED(sc, track)) { + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); + + if (marker) { + float pos[3]; + + pos[0] = marker->pos[0] + track->offset[0]; + pos[1] = marker->pos[1] + track->offset[1]; + pos[2] = 0.0f; + + /* undistortion happens for normalized coords */ + if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) { + /* undistortion happens for normalized coords */ + ED_clip_point_undistorted_pos(sc, pos, pos); + } + + pos[0] *= width; + pos[1] *= height; + + mul_v3_m4v3(pos, sc->stabmat, pos); + + minmax_v2v2_v2(min, max, pos); + + ok = true; + } + } + + track = track->next; + } + + return ok; +} + +static bool tracking_has_selection(SpaceClip *space_clip) +{ + MovieClip *clip = ED_space_clip_get_clip(space_clip); + ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); + const int framenr = ED_space_clip_get_clip_frame_number(space_clip); + + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { + if (!TRACK_VIEW_SELECTED(space_clip, track)) { + continue; + } + const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); + if (marker != NULL) { + return true; + } + } + + return false; +} + +static bool mask_has_selection(const bContext *C) +{ + Mask *mask = CTX_data_edit_mask(C); + if (mask == NULL) { + return false; + } + + LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { + if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) { + for (int i = 0; i < spline->tot_point; i++) { + const MaskSplinePoint *point = &spline->points[i]; + const BezTriple *bezt = &point->bezt; + if (!MASKPOINT_ISSEL_ANY(point)) { + continue; + } + if (bezt->f2 & SELECT) { + return true; + } + + if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) { + return true; + } + else { + if ((bezt->f1 & SELECT) && (bezt->h1 != HD_VECT)) { + return true; + } + if ((bezt->f3 & SELECT) && (bezt->h2 != HD_VECT)) { + return true; + } + } + } + } + } + + return false; +} + +static bool selected_boundbox(const bContext *C, + float min[2], + float max[2], + bool handles_as_control_point) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + if (sc->mode == SC_MODE_TRACKING) { + return selected_tracking_boundbox(sc, min, max); + } + + if (ED_mask_selected_minmax(C, min, max, handles_as_control_point)) { + MovieClip *clip = ED_space_clip_get_clip(sc); + int width, height; + ED_space_clip_get_size(sc, &width, &height); + BKE_mask_coord_to_movieclip(clip, &sc->user, min, min); + BKE_mask_coord_to_movieclip(clip, &sc->user, max, max); + min[0] *= width; + min[1] *= height; + max[0] *= width; + max[1] *= height; + return true; + } + return false; +} + +bool clip_view_calculate_view_selection( + const bContext *C, bool fit, float *r_offset_x, float *r_offset_y, float *r_zoom) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + int frame_width, frame_height; + ED_space_clip_get_size(sc, &frame_width, &frame_height); + + if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL)) { + return false; + } + + /* NOTE: The `fit` argument is set to truth when doing "View to Selected" operator, and it set to + * false when this function is used for Lock-to-Selection functionality. When locking to + * selection the handles are to use control point position. So we can derive the + * `handles_as_control_point` from `fit`. + * + * TODO(sergey): Make such decision more explicit. Maybe pass use-case for the calculation to + * tell operator from lock-to-selection apart. */ + float min[2], max[2]; + if (!selected_boundbox(C, min, max, !fit)) { + return false; + } + + /* center view */ + clip_view_offset_for_center_to_point(sc, + (max[0] + min[0]) / (2 * frame_width), + (max[1] + min[1]) / (2 * frame_height), + r_offset_x, + r_offset_y); + + const int w = max[0] - min[0]; + const int h = max[1] - min[1]; + + /* set zoom to see all selection */ + *r_zoom = sc->zoom; + if (w > 0 && h > 0) { + ARegion *region = CTX_wm_region(C); + + int width, height; + float zoomx, zoomy, newzoom, aspx, aspy; + + ED_space_clip_get_aspect(sc, &aspx, &aspy); + + width = BLI_rcti_size_x(®ion->winrct) + 1; + height = BLI_rcti_size_y(®ion->winrct) + 1; + + zoomx = (float)width / w / aspx; + zoomy = (float)height / h / aspy; + + newzoom = 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)); + + if (fit) { + *r_zoom = newzoom; + } + } + + return true; +} + +/* Returns truth if lock-to-selection is enabled and possible. + * Locking to selection is not possible if there is no selection. */ +bool clip_view_has_locked_selection(const bContext *C) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + + if ((space_clip->flag & SC_LOCK_SELECTION) == 0) { + return false; + } + + if (space_clip->mode == SC_MODE_TRACKING) { + return tracking_has_selection(space_clip); + } + + return mask_has_selection(C); } void clip_draw_sfra_efra(View2D *v2d, Scene *scene) diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 3bdf016b64c..2a7c64a83f7 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -47,15 +47,12 @@ #include "ED_clip.h" #include "ED_mask.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "ED_space_api.h" #include "ED_time_scrub_ui.h" -#include "ED_transform.h" #include "ED_uvedit.h" /* just for ED_image_draw_cursor */ #include "IMB_imbuf.h" -#include "GPU_framebuffer.h" #include "GPU_matrix.h" #include "WM_api.h" @@ -229,7 +226,7 @@ static void clip_scopes_check_gpencil_change(ScrArea *area) } } -static void clip_area_sync_frame_from_scene(ScrArea *area, Scene *scene) +static void clip_area_sync_frame_from_scene(ScrArea *area, const Scene *scene) { SpaceClip *space_clip = (SpaceClip *)area->spacedata.first; BKE_movieclip_user_set_frame(&space_clip->user, scene->r.cfra); @@ -334,8 +331,12 @@ static SpaceLink *clip_duplicate(SpaceLink *sl) return (SpaceLink *)scn; } -static void clip_listener(wmWindow *UNUSED(win), ScrArea *area, wmNotifier *wmn, Scene *scene) +static void clip_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + const Scene *scene = params->scene; + /* context changes */ switch (wmn->category) { case NC_SCENE: @@ -514,6 +515,7 @@ static void clip_operatortypes(void) /* clean-up */ WM_operatortype_append(CLIP_OT_clear_track_path); WM_operatortype_append(CLIP_OT_join_tracks); + WM_operatortype_append(CLIP_OT_average_tracks); WM_operatortype_append(CLIP_OT_track_copy_color); WM_operatortype_append(CLIP_OT_clean_tracks); @@ -988,7 +990,14 @@ static void clip_main_region_draw(const bContext *C, ARegion *region) } /* callback */ + /* TODO(sergey): For being consistent with space image the projection needs to be configured + * the way how the commented out code does it. This works correct for tracking data, but it + * causes wrong aspect correction for mask editor (see T84990). */ + // GPU_matrix_push_projection(); + // wmOrtho2(region->v2d.cur.xmin, region->v2d.cur.xmax, region->v2d.cur.ymin, + // region->v2d.cur.ymax); ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW); + // GPU_matrix_pop_projection(); /* reset view matrix */ UI_view2d_view_restore(C); @@ -1001,12 +1010,11 @@ static void clip_main_region_draw(const bContext *C, ARegion *region) WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D); } -static void clip_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void clip_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_GPENCIL: @@ -1137,11 +1145,7 @@ static void clip_preview_region_draw(const bContext *C, ARegion *region) } } -static void clip_preview_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void clip_preview_region_listener(const wmRegionListenerParams *UNUSED(params)) { } @@ -1182,11 +1186,7 @@ static void clip_channels_region_draw(const bContext *C, ARegion *region) UI_view2d_view_restore(C); } -static void clip_channels_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void clip_channels_region_listener(const wmRegionListenerParams *UNUSED(params)) { } @@ -1203,12 +1203,11 @@ static void clip_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void clip_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void clip_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCENE: @@ -1246,12 +1245,11 @@ static void clip_tools_region_draw(const bContext *C, ARegion *region) /****************** tool properties region ******************/ -static void clip_props_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void clip_props_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_WM: @@ -1299,12 +1297,11 @@ static void clip_properties_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void clip_properties_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void clip_properties_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_GPENCIL: diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 49313005c43..a903aeed380 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -88,17 +88,16 @@ static int add_marker_exec(bContext *C, wmOperator *op) MovieClip *clip = ED_space_clip_get_clip(sc); float pos[2]; + ClipViewLockState lock_state; + ED_clip_view_lock_state_store(C, &lock_state); + RNA_float_get_array(op->ptr, "location", pos); if (!add_marker(C, pos[0], pos[1])) { return OPERATOR_CANCELLED; } - /* Reset offset from locked position, so frame jumping wouldn't be so - * confusing. - */ - sc->xlockof = 0; - sc->ylockof = 0; + ED_clip_view_lock_state_restore_no_jump(C, &lock_state); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); @@ -244,8 +243,6 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op)) changed = true; } } - /* Nothing selected now, unlock view so it can be scrolled nice again. */ - sc->flag &= ~SC_LOCK_SELECTION; if (changed) { WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); } @@ -314,11 +311,6 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op)) } } - if (!has_selection) { - /* Nothing selected now, unlock view so it can be scrolled nice again. */ - sc->flag &= ~SC_LOCK_SELECTION; - } - if (!changed) { return OPERATOR_CANCELLED; } @@ -1225,13 +1217,6 @@ static int hide_tracks_exec(bContext *C, wmOperator *op) clip->tracking.act_plane_track = NULL; } - if (unselected == 0) { - /* No selection on screen now, unlock view so it can be - * scrolled nice again. - */ - sc->flag &= ~SC_LOCK_SELECTION; - } - BKE_tracking_dopesheet_tag_update(tracking); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, NULL); @@ -1490,6 +1475,97 @@ void CLIP_OT_join_tracks(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/********************** Average tracks operator *********************/ + +static int average_tracks_exec(bContext *C, wmOperator *op) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(space_clip); + MovieTracking *tracking = &clip->tracking; + + /* Collect source tracks. */ + int num_source_tracks; + MovieTrackingTrack **source_tracks = BKE_tracking_selected_tracks_in_active_object( + tracking, &num_source_tracks); + if (num_source_tracks == 0) { + return OPERATOR_CANCELLED; + } + + /* Create new empty track, which will be the averaged result. + * Makes it simple to average all selection to it. */ + ListBase *tracks_list = BKE_tracking_get_active_tracks(tracking); + MovieTrackingTrack *result_track = BKE_tracking_track_add_empty(tracking, tracks_list); + + /* Perform averaging. */ + BKE_tracking_tracks_average(result_track, source_tracks, num_source_tracks); + + const bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); + if (!keep_original) { + for (int i = 0; i < num_source_tracks; i++) { + clip_delete_track(C, clip, source_tracks[i]); + } + } + + /* Update selection, making the result track active and selected. */ + /* TODO(sergey): Should become some sort of utility function available for all operators. */ + + BKE_tracking_track_select(tracks_list, result_track, TRACK_AREA_ALL, 0); + ListBase *plane_tracks_list = BKE_tracking_get_active_plane_tracks(tracking); + BKE_tracking_plane_tracks_deselect_all(plane_tracks_list); + + clip->tracking.act_track = result_track; + clip->tracking.act_plane_track = NULL; + + /* Inform the dependency graph and interface about changes. */ + DEG_id_tag_update(&clip->id, 0); + WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); + + /* Free memory. */ + MEM_freeN(source_tracks); + + return OPERATOR_FINISHED; +} + +static int average_tracks_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + PropertyRNA *prop_keep_original = RNA_struct_find_property(op->ptr, "keep_original"); + if (!RNA_property_is_set(op->ptr, prop_keep_original)) { + SpaceClip *space_clip = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(space_clip); + MovieTracking *tracking = &clip->tracking; + + const int num_selected_tracks = BKE_tracking_count_selected_tracks_in_active_object(tracking); + + if (num_selected_tracks == 1) { + RNA_property_boolean_set(op->ptr, prop_keep_original, false); + } + } + + return average_tracks_exec(C, op); +} + +void CLIP_OT_average_tracks(wmOperatorType *ot) +{ + /* Identifiers. */ + ot->name = "Average Tracks"; + ot->description = "Average selected tracks into active"; + ot->idname = "CLIP_OT_average_tracks"; + + /* API callbacks. */ + ot->exec = average_tracks_exec; + ot->invoke = average_tracks_invoke; + ot->poll = ED_space_clip_tracking_poll; + + /* Flags. */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* Properties. */ + PropertyRNA *prop; + + prop = RNA_def_boolean(ot->srna, "keep_original", 1, "Keep Original", "Keep original tracks"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} + /********************** lock tracks operator *********************/ enum { diff --git a/source/blender/editors/space_clip/tracking_ops_detect.c b/source/blender/editors/space_clip/tracking_ops_detect.c index 54ec439471d..86ee94df731 100644 --- a/source/blender/editors/space_clip/tracking_ops_detect.c +++ b/source/blender/editors/space_clip/tracking_ops_detect.c @@ -21,14 +21,10 @@ * \ingroup spclip */ -#include "MEM_guardedalloc.h" - #include "DNA_gpencil_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" -#include "BLI_utildefines.h" - #include "BKE_context.h" #include "BKE_movieclip.h" #include "BKE_report.h" diff --git a/source/blender/editors/space_clip/tracking_ops_stabilize.c b/source/blender/editors/space_clip/tracking_ops_stabilize.c index 5e43b7c7ec6..d0b4d18c6d9 100644 --- a/source/blender/editors/space_clip/tracking_ops_stabilize.c +++ b/source/blender/editors/space_clip/tracking_ops_stabilize.c @@ -21,8 +21,6 @@ * \ingroup spclip */ -#include "MEM_guardedalloc.h" - #include "DNA_screen_types.h" #include "DNA_space_types.h" diff --git a/source/blender/editors/space_clip/tracking_ops_track.c b/source/blender/editors/space_clip/tracking_ops_track.c index 585b13b426e..e480ec2db05 100644 --- a/source/blender/editors/space_clip/tracking_ops_track.c +++ b/source/blender/editors/space_clip/tracking_ops_track.c @@ -30,7 +30,6 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_movieclip.h" -#include "BKE_report.h" #include "BKE_tracking.h" #include "WM_api.h" diff --git a/source/blender/editors/space_clip/tracking_ops_utils.c b/source/blender/editors/space_clip/tracking_ops_utils.c index 1f959e94309..0f6bd6e039a 100644 --- a/source/blender/editors/space_clip/tracking_ops_utils.c +++ b/source/blender/editors/space_clip/tracking_ops_utils.c @@ -21,12 +21,8 @@ * \ingroup spclip */ -#include "MEM_guardedalloc.h" - #include "DNA_space_types.h" -#include "BLI_utildefines.h" - #include "BKE_context.h" #include "BKE_tracking.h" diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c index 063ea9592aa..558c0bec11d 100644 --- a/source/blender/editors/space_clip/tracking_select.c +++ b/source/blender/editors/space_clip/tracking_select.c @@ -304,6 +304,9 @@ static int mouse_select(bContext *C, const float co[2], const bool extend, const track = find_nearest_track(sc, tracksbase, co, &distance_to_track); plane_track = find_nearest_plane_track(sc, plane_tracks_base, co, &distance_to_plane_track); + ClipViewLockState lock_state; + ED_clip_view_lock_state_store(C, &lock_state); + /* Do not select beyond some reasonable distance, that is useless and * prevents the 'deselect on nothing' behavior. */ if (distance_to_track > 0.05f) { @@ -377,10 +380,7 @@ static int mouse_select(bContext *C, const float co[2], const bool extend, const ED_mask_deselect_all(C); } - if (!extend) { - sc->xlockof = 0.0f; - sc->ylockof = 0.0f; - } + ED_clip_view_lock_state_restore_no_jump(C, &lock_state); BKE_tracking_dopesheet_tag_update(tracking); @@ -867,14 +867,16 @@ static int select_all_exec(bContext *C, wmOperator *op) MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; - int action = RNA_enum_get(op->ptr, "action"); + const int action = RNA_enum_get(op->ptr, "action"); - bool has_selection = false; + ClipViewLockState lock_state; + ED_clip_view_lock_state_store(C, &lock_state); + bool has_selection = false; ED_clip_select_all(sc, action, &has_selection); - if (!has_selection) { - sc->flag &= ~SC_LOCK_SELECTION; + if (has_selection) { + ED_clip_view_lock_state_restore_no_jump(C, &lock_state); } BKE_tracking_dopesheet_tag_update(tracking); diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index 77f1111624d..05595e0b393 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -18,7 +18,7 @@ * \ingroup spconsole */ -#include <ctype.h> /* ispunct */ +#include <ctype.h> /* #ispunct */ #include <stdlib.h> #include <string.h> #include <sys/stat.h> @@ -749,7 +749,7 @@ static int console_clear_exec(bContext *C, wmOperator *op) /*ConsoleLine *ci = */ console_history_verify(C); - if (scrollback) { /* last item in mistory */ + if (scrollback) { /* Last item in history. */ while (sc->scrollback.first) { console_scrollback_free(sc, sc->scrollback.first); } diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index 9b8e9e0e871..b24579d9871 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -41,7 +41,6 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "GPU_framebuffer.h" #include "console_intern.h" /* own include */ /* ******************** default callbacks for console space ***************** */ @@ -216,7 +215,7 @@ static void console_main_region_draw(const bContext *C, ARegion *region) /* clear and setup matrix */ UI_ThemeClearColor(TH_BACK); - /* worlks best with no view2d matrix set */ + /* Works best with no view2d matrix set. */ UI_view2d_view_ortho(v2d); /* data... */ @@ -273,13 +272,11 @@ static void console_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void console_main_region_listener(wmWindow *UNUSED(win), - ScrArea *area, - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void console_main_region_listener(const wmRegionListenerParams *params) { - // SpaceInfo *sinfo = area->spacedata.first; + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 8e9093151ba..c1dcf2e56d3 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -131,7 +131,15 @@ static void draw_tile(int sx, int sy, int width, int height, int colorid, int sh UI_GetThemeColorShade4fv(colorid, shade, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_aa( - true, (float)sx, (float)(sy - height), (float)(sx + width), (float)sy, 5.0f, color); + &(const rctf){ + .xmin = (float)sx, + .xmax = (float)(sx + width), + .ymin = (float)(sy - height), + .ymax = (float)sy, + }, + true, + 5.0f, + color); } static void file_draw_icon(uiBlock *block, @@ -465,7 +473,7 @@ static void file_draw_preview(uiBlock *block, but = uiDefBut(block, UI_BTYPE_LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, NULL); - /* dragregion */ + /* Drag-region. */ if (drag) { ID *id; @@ -546,7 +554,7 @@ static void draw_background(FileLayout *layout, View2D *v2d) for (i = 2; (i <= layout->rows + 1); i += 2) { sy = (int)v2d->cur.ymax - layout->offset_top - i * item_height - layout->tile_border_y; - /* Offsett pattern slightly to add scroll effect. */ + /* Offset pattern slightly to add scroll effect. */ sy += round_fl_to_int(item_height * (v2d->tot.ymax - v2d->cur.ymax) / item_height); immRectf(pos, diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c index 9d85996c559..186bc04fafe 100644 --- a/source/blender/editors/space_file/file_utils.c +++ b/source/blender/editors/space_file/file_utils.c @@ -19,7 +19,6 @@ */ #include "BLI_fileops.h" -#include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_rect.h" #include "BLI_string.h" diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index d66219c7549..33c37875372 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -276,6 +276,7 @@ typedef struct FileListInternEntry { char *redirection_path; /** not strictly needed, but used during sorting, avoids to have to recompute it there... */ char *name; + bool free_name; /** * This is data from the current main, represented by this file. It's crucial that this is @@ -1366,7 +1367,7 @@ static bool filelist_checkdir_main_assets(struct FileList *UNUSED(filelist), static void filelist_entry_clear(FileDirEntry *entry) { - if (entry->name) { + if (entry->name && ((entry->flags & FILE_ENTRY_NAME_FREE) != 0)) { MEM_freeN(entry->name); } if (entry->description) { @@ -1451,7 +1452,7 @@ static void filelist_intern_entry_free(FileListInternEntry *entry) if (entry->redirection_path) { MEM_freeN(entry->redirection_path); } - if (entry->name) { + if (entry->name && entry->free_name) { MEM_freeN(entry->name); } /* If we own the asset-data (it was generated from external file data), free it. */ @@ -1953,7 +1954,13 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in ret->entry = rev; ret->relpath = BLI_strdup(entry->relpath); - ret->name = BLI_strdup(entry->name); + if (entry->free_name) { + ret->name = BLI_strdup(entry->name); + ret->flags |= FILE_ENTRY_NAME_FREE; + } + else { + ret->name = entry->name; + } ret->description = BLI_strdupcat(filelist->filelist.root, entry->relpath); memcpy(ret->uuid, entry->uuid, sizeof(ret->uuid)); ret->blentype = entry->blentype; @@ -3175,6 +3182,7 @@ static void filelist_readjob_do(const bool do_lib, entry->relpath = BLI_strdup(dir + 2); /* + 2 to remove '//' * added by BLI_path_rel to rel_subdir. */ entry->name = BLI_strdup(fileentry_uiname(root, entry->relpath, entry->typeflag, dir)); + entry->free_name = true; /* Here we decide whether current filedirentry is to be listed too, or not. */ if (max_recursion && (is_lib || (recursion_level <= max_recursion))) { @@ -3288,7 +3296,8 @@ static void filelist_readjob_main_assets(Main *current_main, entry = MEM_callocN(sizeof(*entry), __func__); entry->relpath = BLI_strdup(id_code_name); - entry->name = BLI_strdup(id_iter->name + 2); + entry->name = id_iter->name + 2; + entry->free_name = false; entry->typeflag |= FILE_TYPE_BLENDERLIB | FILE_TYPE_ASSET; entry->blentype = GS(id_iter->name); *((uint32_t *)entry->uuid) = atomic_add_and_fetch_uint32( diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 6b74b344375..6e5791cad52 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -460,7 +460,7 @@ bool ED_fileselect_is_asset_browser(const SpaceFile *sfile) void ED_fileselect_window_params_get(const wmWindow *win, int win_size[2], bool *is_maximized) { - /* Get DPI/pixelsize independent size to be stored in preferences. */ + /* Get DPI/pixel-size independent size to be stored in preferences. */ WM_window_set_dpi(win); /* Ensure the DPI is taken from the right window. */ win_size[0] = WM_window_pixels_x(win) / UI_DPI_FAC; diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 7f33b0212d6..178ca264182 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -104,6 +104,7 @@ static ARegion *file_tool_props_region_ensure(ScrArea *area, ARegion *region_pre BLI_insertlinkafter(&area->regionbase, region_prev, region); region->regiontype = RGN_TYPE_TOOL_PROPS; region->alignment = RGN_ALIGN_RIGHT; + region->flag = RGN_FLAG_HIDDEN; return region; } @@ -246,13 +247,13 @@ static void file_ensure_valid_region_state(bContext *C, BLI_assert(region_tools); if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) { - ARegion *region_execute = file_execute_region_ensure(area, region_tools); - ARegion *region_props = file_tool_props_region_ensure(area, region_execute); - - /* Hide specific regions by default. */ - region_props->flag |= RGN_FLAG_HIDDEN; - region_execute->flag |= RGN_FLAG_HIDDEN; + file_tool_props_region_ensure(area, region_tools); + ARegion *region_execute = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE); + if (region_execute) { + ED_region_remove(C, area, region_execute); + needs_init = true; + } ARegion *region_ui = BKE_area_find_region_type(area, RGN_TYPE_UI); if (region_ui) { ED_region_remove(C, area, region_ui); @@ -260,7 +261,7 @@ static void file_ensure_valid_region_state(bContext *C, } } /* If there's an file-operation, ensure we have the option and execute region */ - else if (sfile->op) { + else if (sfile->op && !BKE_area_find_region_type(area, RGN_TYPE_TOOL_PROPS)) { ARegion *region_ui = file_ui_region_ensure(area, region_tools); ARegion *region_execute = file_execute_region_ensure(area, region_ui); ARegion *region_props = file_tool_props_region_ensure(area, region_execute); @@ -275,17 +276,18 @@ static void file_ensure_valid_region_state(bContext *C, needs_init = true; } /* If there's _no_ file-operation, ensure we _don't_ have the option and execute region */ - else { + else if (!sfile->op) { ARegion *region_props = BKE_area_find_region_type(area, RGN_TYPE_TOOL_PROPS); ARegion *region_execute = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE); ARegion *region_ui = file_ui_region_ensure(area, region_tools); UNUSED_VARS(region_ui); + if (region_execute) { + ED_region_remove(C, area, region_execute); + needs_init = true; + } if (region_props) { - BLI_assert(region_execute); - ED_region_remove(C, area, region_props); - ED_region_remove(C, area, region_execute); needs_init = true; } } @@ -390,11 +392,10 @@ static void file_refresh(const bContext *C, ScrArea *area) ED_area_tag_redraw(area); } -static void file_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void file_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceFile *sfile = (SpaceFile *)area->spacedata.first; /* context changes */ @@ -445,12 +446,11 @@ static void file_main_region_init(wmWindowManager *wm, ARegion *region) WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap); } -static void file_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void file_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SPACE: @@ -463,19 +463,24 @@ static void file_main_region_listener(wmWindow *UNUSED(win), break; } break; + case NC_ID: + if (ELEM(wmn->action, NA_RENAME)) { + /* In case the filelist shows ID names. */ + ED_region_tag_redraw(region); + } + break; } } -static void file_main_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void file_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; SpaceFile *sfile = area->spacedata.first; - FileSelectParams *params = ED_fileselect_ensure_active_params(sfile); + + FileSelectParams *file_params = ED_fileselect_ensure_active_params(sfile); /* This is a bit odd that a region owns the subscriber for an area, * keep for now since all subscribers for WM are regions. * May be worth re-visiting later. */ @@ -497,7 +502,7 @@ static void file_main_region_message_subscribe(const struct bContext *UNUSED(C), /* FileSelectParams */ { PointerRNA ptr; - RNA_pointer_create(&screen->id, &RNA_FileSelectParams, params, &ptr); + RNA_pointer_create(&screen->id, &RNA_FileSelectParams, file_params, &ptr); /* All properties for this space type. */ WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_area_tag_refresh, __func__); @@ -647,18 +652,23 @@ static void file_tools_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void file_tools_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void file_tools_region_listener(const wmRegionListenerParams *UNUSED(params)) { -#if 0 - /* context changes */ +} + +static void file_tool_props_region_listener(const wmRegionListenerParams *params) +{ + const wmNotifier *wmn = params->notifier; + ARegion *region = params->region; + switch (wmn->category) { - /* pass */ + case NC_ID: + if (ELEM(wmn->action, NA_RENAME)) { + /* In case the filelist shows ID names. */ + ED_region_tag_redraw(region); + } + break; } -#endif } /* add handlers, stuff you only do once or on area/region changes */ @@ -715,12 +725,11 @@ static void file_execution_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void file_ui_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void file_ui_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SPACE: @@ -928,7 +937,7 @@ void ED_spacetype_file(void) art->prefsizex = 240; art->prefsizey = 60; art->keymapflag = ED_KEYMAP_UI; - art->listener = file_tools_region_listener; + art->listener = file_tool_props_region_listener; art->init = file_tools_region_init; art->draw = file_tools_region_draw; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index fac38ef7b91..31f606e515d 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -178,7 +178,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode) x = (float)CFRA; } - /* Normalise units of cursor's value. */ + /* Normalize units of cursor's value. */ if (sipo) { y = (sipo->cursorVal / unit_scale) - offset; } @@ -2263,7 +2263,7 @@ static void snap_graph_keys(bAnimContext *ac, short mode) for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); - /* Normalise cursor value (for normalised F-Curves display). */ + /* Normalize cursor value (for normalized F-Curves display). */ if (mode == GRAPHKEYS_SNAP_VALUE) { short mapping_flag = ANIM_get_normalization_flags(ac); float offset; diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 63acc2a1774..32396a70cce 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -32,15 +32,11 @@ #include "BKE_context.h" #include "BKE_global.h" -#include "BKE_main.h" #include "UI_view2d.h" #include "ED_anim_api.h" -#include "ED_markers.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "ED_transform.h" #include "graph_intern.h" diff --git a/source/blender/editors/space_graph/graph_slider_ops.c b/source/blender/editors/space_graph/graph_slider_ops.c index 4cda6b34a01..3e52dc7377b 100644 --- a/source/blender/editors/space_graph/graph_slider_ops.c +++ b/source/blender/editors/space_graph/graph_slider_ops.c @@ -380,7 +380,7 @@ static int graphkeys_decimate_modal(bContext *C, wmOperator *op, const wmEvent * break; } - /* Unhandled event - maybe it was some view manip? */ + /* Unhandled event - maybe it was some view manipulation? */ /* Allow to pass through. */ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; } @@ -505,15 +505,15 @@ void GRAPH_OT_decimate(wmOperatorType *ot) "Mode", "Which mode to use for decimation"); - RNA_def_float_percentage(ot->srna, - "remove_ratio", - 1.0f / 3.0f, - 0.0f, - 1.0f, - "Remove", - "The percentage of keyframes to remove", - 0.0f, - 1.0f); + RNA_def_float_factor(ot->srna, + "remove_ratio", + 1.0f / 3.0f, + 0.0f, + 1.0f, + "Remove", + "The ratio of remaining keyframes after the operation", + 0.0f, + 1.0f); RNA_def_float(ot->srna, "remove_error_margin", 0.0f, diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c index 8463c21b1ad..c37d9f42c12 100644 --- a/source/blender/editors/space_graph/graph_utils.c +++ b/source/blender/editors/space_graph/graph_utils.c @@ -38,8 +38,6 @@ #include "BKE_fcurve.h" #include "BKE_screen.h" -#include "WM_api.h" - #include "ED_anim_api.h" #include "ED_screen.h" #include "UI_interface.h" diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 791039498e8..9f01773eadf 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -403,12 +403,11 @@ static void graph_buttons_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void graph_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void graph_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -470,14 +469,14 @@ static void graph_region_listener(wmWindow *UNUSED(win), } } -static void graph_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void graph_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + Scene *scene = params->scene; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceGraphEditor, area->spacedata.first, &ptr); @@ -546,11 +545,10 @@ static void graph_region_message_subscribe(const struct bContext *UNUSED(C), } /* editor level listener */ -static void graph_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void graph_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceGraph *sipo = (SpaceGraph *)area->spacedata.first; /* context changes */ diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 63e5ae64a8c..67d5055ec65 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -466,7 +466,7 @@ static void sima_draw_zbuf_pixels( { const float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; - /* Slowwww */ + /* Very slow! */ float *rectf = MEM_mallocN(rectx * recty * sizeof(float), "temp"); for (int a = rectx * recty - 1; a >= 0; a--) { /* zbuffer values are signed, so we need to shift color range */ @@ -874,7 +874,7 @@ void draw_image_main(const bContext *C, ARegion *region) if (show_stereo3d) { if (show_multilayer) { - /* update multiindex and pass for the current eye */ + /* Update multi-index and pass for the current eye. */ BKE_image_multilayer_index(ima->rr, &sima->iuser); } else { diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index 100556ad29a..0044c6072a4 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -71,6 +71,7 @@ void IMAGE_OT_save_all_modified(struct wmOperatorType *ot); void IMAGE_OT_pack(struct wmOperatorType *ot); void IMAGE_OT_unpack(struct wmOperatorType *ot); +void IMAGE_OT_flip(struct wmOperatorType *ot); void IMAGE_OT_invert(struct wmOperatorType *ot); void IMAGE_OT_resize(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 86e52814d6f..4008ca228ac 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -36,9 +36,7 @@ #include "BLI_blenlib.h" #include "BLI_fileops.h" -#include "BLI_fileops_types.h" #include "BLI_ghash.h" -#include "BLI_linklist.h" #include "BLI_math.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -48,7 +46,6 @@ #include "DNA_camera_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" -#include "DNA_packedFile_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -62,14 +59,10 @@ #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_packedFile.h" -#include "BKE_paint.h" #include "BKE_report.h" -#include "BKE_scene.h" -#include "BKE_screen.h" #include "DEG_depsgraph.h" -#include "GPU_immediate.h" #include "GPU_state.h" #include "IMB_colormanagement.h" @@ -467,7 +460,7 @@ static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *eve UI_view2d_region_to_view( ®ion->v2d, event->mval[0], event->mval[1], &vpd->location[0], &vpd->location[1]); - if (U.viewzoom == USER_ZOOM_CONT) { + if (U.viewzoom == USER_ZOOM_CONTINUE) { /* needs a timer to continue redrawing */ vpd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); vpd->timer_lastdraw = PIL_check_seconds_timer(); @@ -579,12 +572,10 @@ static void image_zoom_apply(ViewZoomData *vpd, delta = -delta; } - if (viewzoom == USER_ZOOM_CONT) { + if (viewzoom == USER_ZOOM_CONTINUE) { double time = PIL_check_seconds_timer(); float time_step = (float)(time - vpd->timer_lastdraw); float zfac; - - /* oldstyle zoom */ zfac = 1.0f + ((delta / 20.0f) * time_step); vpd->timer_lastdraw = time; /* this is the final zoom, but instead make it into a factor */ @@ -900,7 +891,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) } } else if (ED_space_image_check_show_maskedit(sima, obedit)) { - if (!ED_mask_selected_minmax(C, min, max)) { + if (!ED_mask_selected_minmax(C, min, max, false)) { return OPERATOR_CANCELLED; } } @@ -2663,6 +2654,126 @@ void IMAGE_OT_new(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Flip Operator + * \{ */ + +static int image_flip_exec(bContext *C, wmOperator *op) +{ + Image *ima = image_from_context(C); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); + SpaceImage *sima = CTX_wm_space_image(C); + const bool is_paint = ((sima != NULL) && (sima->mode == SI_MODE_PAINT)); + + if (ibuf == NULL) { + /* TODO: this should actually never happen, but does for render-results -> cleanup. */ + return OPERATOR_CANCELLED; + } + + const bool flip_horizontal = RNA_boolean_get(op->ptr, "use_flip_horizontal"); + const bool flip_vertical = RNA_boolean_get(op->ptr, "use_flip_vertical"); + + if (!flip_horizontal && !flip_vertical) { + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_FINISHED; + } + + ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &sima->iuser); + + if (is_paint) { + ED_imapaint_clear_partial_redraw(); + } + + const int size_x = ibuf->x; + const int size_y = ibuf->y; + + if (ibuf->rect_float) { + float *float_pixels = (float *)ibuf->rect_float; + + float *orig_float_pixels = MEM_dupallocN(float_pixels); + for (int x = 0; x < size_x; x++) { + for (int y = 0; y < size_y; y++) { + const int source_pixel_x = flip_horizontal ? size_x - x - 1 : x; + const int source_pixel_y = flip_vertical ? size_y - y - 1 : y; + + float *source_pixel = &orig_float_pixels[4 * (source_pixel_x + source_pixel_y * size_x)]; + float *target_pixel = &float_pixels[4 * (x + y * size_x)]; + + copy_v4_v4(target_pixel, source_pixel); + } + } + MEM_freeN(orig_float_pixels); + + if (ibuf->rect) { + IMB_rect_from_float(ibuf); + } + } + else if (ibuf->rect) { + char *char_pixels = (char *)ibuf->rect; + char *orig_char_pixels = MEM_dupallocN(char_pixels); + for (int x = 0; x < size_x; x++) { + for (int y = 0; y < size_y; y++) { + const int source_pixel_x = flip_horizontal ? size_x - x - 1 : x; + const int source_pixel_y = flip_vertical ? size_y - y - 1 : y; + + char *source_pixel = &orig_char_pixels[4 * (source_pixel_x + source_pixel_y * size_x)]; + char *target_pixel = &char_pixels[4 * (x + y * size_x)]; + + copy_v4_v4_char(target_pixel, source_pixel); + } + } + MEM_freeN(orig_char_pixels); + } + else { + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_CANCELLED; + } + + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + BKE_image_mark_dirty(ima, ibuf); + + if (ibuf->mipmap[0]) { + ibuf->userflags |= IB_MIPMAP_INVALID; + } + + ED_image_undo_push_end(); + + /* force GPU re-upload, all image is invalid. */ + BKE_image_free_gputextures(ima); + + WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); + + BKE_image_release_ibuf(ima, ibuf, NULL); + + return OPERATOR_FINISHED; +} + +void IMAGE_OT_flip(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Flip Image"; + ot->idname = "IMAGE_OT_flip"; + ot->description = "Flip the image"; + + /* api callbacks */ + ot->exec = image_flip_exec; + ot->poll = image_from_context_has_data_poll_no_image_user; + + /* properties */ + PropertyRNA *prop; + prop = RNA_def_boolean( + ot->srna, "use_flip_horizontal", false, "Horizontal", "Flip the image horizontally"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "use_flip_vertical", false, "Vertical", "Flip the image vertically"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + /* flags */ + ot->flag = OPTYPE_REGISTER; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Invert Operators * \{ */ @@ -2747,7 +2858,7 @@ static int image_invert_exec(bContext *C, wmOperator *op) ED_image_undo_push_end(); - /* force GPU reupload, all image is invalid */ + /* Force GPU re-upload, all image is invalid. */ BKE_image_free_gputextures(ima); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); @@ -2838,7 +2949,7 @@ static int image_scale_exec(bContext *C, wmOperator *op) ED_image_undo_push_end(); - /* force GPU reupload, all image is invalid */ + /* Force GPU re-upload, all image is invalid. */ BKE_image_free_gputextures(ima); DEG_id_tag_update(&ima->id, 0); diff --git a/source/blender/editors/space_image/image_sequence.c b/source/blender/editors/space_image/image_sequence.c index 81f2ced7dee..02546e3e3b3 100644 --- a/source/blender/editors/space_image/image_sequence.c +++ b/source/blender/editors/space_image/image_sequence.c @@ -27,7 +27,6 @@ #include "BLI_fileops.h" #include "BLI_fileops_types.h" -#include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_math_base.h" #include "BLI_path_util.h" @@ -35,7 +34,6 @@ #include "BLI_utildefines.h" #include "DNA_image_types.h" -#include "DNA_space_types.h" #include "DNA_windowmanager_types.h" #include "RNA_access.h" @@ -45,8 +43,6 @@ #include "ED_image.h" -#include "WM_types.h" - typedef struct ImageFrame { struct ImageFrame *next, *prev; int framenr; diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c index 1d5725033e0..391c68f4231 100644 --- a/source/blender/editors/space_image/image_undo.c +++ b/source/blender/editors/space_image/image_undo.c @@ -947,13 +947,15 @@ static void image_undosys_step_decode_redo(ImageUndoStep *us) } static void image_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir, bool is_final) + struct bContext *C, struct Main *bmain, UndoStep *us_p, const eUndoStepDir dir, bool is_final) { + BLI_assert(dir != STEP_INVALID); + ImageUndoStep *us = (ImageUndoStep *)us_p; - if (dir < 0) { + if (dir == STEP_UNDO) { image_undosys_step_decode_undo(us, is_final); } - else { + else if (dir == STEP_REDO) { image_undosys_step_decode_redo(us); } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 186f2d3a5a8..69976bc088c 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -24,8 +24,6 @@ #include "DNA_gpencil_types.h" #include "DNA_image_types.h" #include "DNA_mask_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -37,14 +35,9 @@ #include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_editmesh.h" #include "BKE_image.h" -#include "BKE_layer.h" #include "BKE_lib_id.h" -#include "BKE_material.h" -#include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_workspace.h" #include "RNA_access.h" #include "RNA_define.h" @@ -56,7 +49,6 @@ #include "ED_image.h" #include "ED_mask.h" -#include "ED_mesh.h" #include "ED_node.h" #include "ED_render.h" #include "ED_screen.h" @@ -65,19 +57,13 @@ #include "ED_uvedit.h" #include "WM_api.h" -#include "WM_message.h" #include "WM_types.h" #include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" -#include "GPU_batch_presets.h" -#include "GPU_framebuffer.h" -#include "GPU_viewport.h" - #include "DRW_engine.h" -#include "DRW_engine_types.h" #include "image_intern.h" @@ -234,6 +220,7 @@ static void image_operatortypes(void) WM_operatortype_append(IMAGE_OT_pack); WM_operatortype_append(IMAGE_OT_unpack); + WM_operatortype_append(IMAGE_OT_flip); WM_operatortype_append(IMAGE_OT_invert); WM_operatortype_append(IMAGE_OT_resize); @@ -320,8 +307,11 @@ static void image_refresh(const bContext *C, ScrArea *area) } } -static void image_listener(wmWindow *win, ScrArea *area, wmNotifier *wmn, Scene *UNUSED(scene)) +static void image_listener(const wmSpaceTypeListenerParams *params) { + wmWindow *win = params->window; + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceImage *sima = (SpaceImage *)area->spacedata.first; /* context changes */ @@ -728,12 +718,12 @@ static void image_main_region_draw(const bContext *C, ARegion *region) draw_image_cache(C, region); } -static void image_main_region_listener(wmWindow *UNUSED(win), - ScrArea *area, - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void image_main_region_listener(const wmRegionListenerParams *params) { + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_GEOM: @@ -843,12 +833,11 @@ static void image_buttons_region_draw(const bContext *C, ARegion *region) ED_region_panels_draw(C, region); } -static void image_buttons_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void image_buttons_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_TEXTURE: @@ -906,12 +895,11 @@ static void image_tools_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void image_tools_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void image_tools_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_GPENCIL: @@ -963,12 +951,11 @@ static void image_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void image_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void image_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCENE: diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c index 414bce29502..be3b60d581b 100644 --- a/source/blender/editors/space_info/info_draw.c +++ b/source/blender/editors/space_info/info_draw.c @@ -35,7 +35,6 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "GPU_framebuffer.h" #include "info_intern.h" #include "textview.h" @@ -56,47 +55,11 @@ static enum eTextViewContext_LineFlag report_line_data(TextViewContext *tvc, int shade = (tvc->iter_tmp % 2) ? 4 : -4; UI_GetThemeColorShade4ubv(bg_id, shade, bg); - /* Icon color and backgound depend of report type. */ + /* Don't show icon on subsequent rows of multi-row report. */ + *r_icon = (tvc->iter_char_begin != 0) ? ICON_NONE : UI_icon_from_report_type(report->type); - int icon_fg_id; - int icon_bg_id; - - if (tvc->iter_char_begin != 0) { - *r_icon = ICON_NONE; - } - else if (report->type & RPT_ERROR_ALL) { - icon_fg_id = TH_INFO_ERROR_TEXT; - icon_bg_id = TH_INFO_ERROR; - *r_icon = ICON_CANCEL; - } - else if (report->type & RPT_WARNING_ALL) { - icon_fg_id = TH_INFO_WARNING_TEXT; - icon_bg_id = TH_INFO_WARNING; - *r_icon = ICON_ERROR; - } - else if (report->type & RPT_INFO_ALL) { - icon_fg_id = TH_INFO_INFO_TEXT; - icon_bg_id = TH_INFO_INFO; - *r_icon = ICON_INFO; - } - else if (report->type & RPT_DEBUG_ALL) { - icon_fg_id = TH_INFO_DEBUG_TEXT; - icon_bg_id = TH_INFO_DEBUG; - *r_icon = ICON_SYSTEM; - } - else if (report->type & RPT_PROPERTY) { - icon_fg_id = TH_INFO_PROPERTY_TEXT; - icon_bg_id = TH_INFO_PROPERTY; - *r_icon = ICON_OPTIONS; - } - else if (report->type & RPT_OPERATOR) { - icon_fg_id = TH_INFO_OPERATOR_TEXT; - icon_bg_id = TH_INFO_OPERATOR; - *r_icon = ICON_CHECKMARK; - } - else { - *r_icon = ICON_NONE; - } + int icon_fg_id = UI_text_colorid_from_report_type(report->type); + int icon_bg_id = UI_icon_colorid_from_report_type(report->type); if (report->flag & SELECT) { icon_fg_id = TH_INFO_SELECTED; @@ -105,6 +68,8 @@ static enum eTextViewContext_LineFlag report_line_data(TextViewContext *tvc, if (*r_icon != ICON_NONE) { UI_GetThemeColor4ubv(icon_fg_id, r_icon_fg); + /* This theme color is RGB only, so set alpha. */ + r_icon_fg[3] = 255; UI_GetThemeColor4ubv(icon_bg_id, r_icon_bg); return TVC_LINE_FG | TVC_LINE_BG | TVC_LINE_ICON | TVC_LINE_ICON_FG | TVC_LINE_ICON_BG; } diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 3bd23eab836..0583628be43 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -24,7 +24,6 @@ #include <stdio.h> #include <string.h> -#include "DNA_packedFile_types.h" #include "DNA_space_types.h" #include "DNA_windowmanager_types.h" @@ -52,8 +51,6 @@ #include "UI_interface.h" #include "UI_resources.h" -#include "IMB_imbuf_types.h" - #include "RNA_access.h" #include "RNA_define.h" @@ -567,15 +564,7 @@ static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), co } /* set target color based on report type */ - if (report->type & RPT_ERROR_ALL) { - UI_GetThemeColorType3fv(TH_INFO_ERROR, SPACE_INFO, target_col); - } - else if (report->type & RPT_WARNING_ALL) { - UI_GetThemeColorType3fv(TH_INFO_WARNING, SPACE_INFO, target_col); - } - else if (report->type & RPT_INFO_ALL) { - UI_GetThemeColorType3fv(TH_INFO_INFO, SPACE_INFO, target_col); - } + UI_GetThemeColorType3fv(UI_icon_colorid_from_report_type(report->type), SPACE_INFO, target_col); target_col[3] = 0.65f; if (rti->widthfac == 0.0f) { diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c index 8d3f21aefeb..dfc0abee704 100644 --- a/source/blender/editors/space_info/space_info.c +++ b/source/blender/editors/space_info/space_info.c @@ -29,8 +29,6 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BLT_translation.h" - #include "BKE_context.h" #include "BKE_screen.h" @@ -43,12 +41,9 @@ #include "RNA_access.h" -#include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" -#include "BLO_readfile.h" -#include "GPU_framebuffer.h" #include "info_intern.h" /* own include */ /* ******************** default callbacks for info space ***************** */ @@ -150,7 +145,7 @@ static void info_main_region_draw(const bContext *C, ARegion *region) info_textview_update_rect(C, region); - /* worlks best with no view2d matrix set */ + /* Works best with no view2d matrix set. */ UI_view2d_view_ortho(v2d); info_textview_main(sinfo, region, CTX_wm_reports(C)); @@ -204,13 +199,10 @@ static void info_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void info_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void info_main_region_listener(const wmRegionListenerParams *params) { - // SpaceInfo *sinfo = area->spacedata.first; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -223,12 +215,11 @@ static void info_main_region_listener(wmWindow *UNUSED(win), } } -static void info_header_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void info_header_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCREEN: @@ -259,14 +250,11 @@ static void info_header_listener(wmWindow *UNUSED(win), } } -static void info_header_region_message_subscribe(const bContext *UNUSED(C), - WorkSpace *UNUSED(workspace), - Scene *UNUSED(scene), - bScreen *UNUSED(screen), - ScrArea *UNUSED(area), - ARegion *region, - struct wmMsgBus *mbus) +static void info_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index a489216afd1..aef59e89325 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -225,13 +225,16 @@ static bool textview_draw_string(TextViewDrawState *tds, rgba_uchar_to_float(col, icon_bg); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, - hpadding, - line_top - bg_size - vpadding, - bg_size + hpadding, - line_top - vpadding, - 4 * UI_DPI_FAC, - col); + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = hpadding, + .xmax = bg_size + hpadding, + .ymin = line_top - bg_size - vpadding, + .ymax = line_top - vpadding, + }, + true, + 4 * UI_DPI_FAC, + col); } if (icon) { diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 6fe980cf657..eea81e425c2 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -493,7 +493,18 @@ static void nla_draw_strip(SpaceNla *snla, /* strip is in normal track */ UI_draw_roundbox_corner_set(UI_CNR_ALL); /* all corners rounded */ - UI_draw_roundbox_shade_x(true, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1, color); + UI_draw_roundbox_shade_x( + &(const rctf){ + .xmin = strip->start, + .xmax = strip->end, + .ymin = yminc, + .ymax = ymaxc, + }, + true, + 0.0, + 0.5, + 0.1, + color); /* restore current vertex format & program (roundbox trashes it) */ shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); @@ -547,7 +558,18 @@ static void nla_draw_strip(SpaceNla *snla, } else { /* non-muted - draw solid, rounded outline */ - UI_draw_roundbox_shade_x(false, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1, color); + UI_draw_roundbox_shade_x( + &(const rctf){ + .xmin = strip->start, + .xmax = strip->end, + .ymin = yminc, + .ymax = ymaxc, + }, + false, + 0.0, + 0.0, + 0.1, + color); /* restore current vertex format & program (roundbox trashes it) */ shdr_pos = nla_draw_use_dashed_outlines(color, muted); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index d7bf6c324ac..893d2c0e2c8 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -62,7 +62,6 @@ #include "DEG_depsgraph_build.h" #include "UI_interface.h" -#include "UI_resources.h" #include "UI_view2d.h" #include "nla_intern.h" /* own include */ @@ -215,7 +214,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) return false; } - /* for each AnimData block with NLA-data, try exitting tweak-mode */ + /* For each AnimData block with NLA-data, try exiting tweak-mode. */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ale->data; @@ -418,7 +417,7 @@ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, floa int filter; SpaceNla *snla = (SpaceNla *)ac->sl; - /* NOTE: not bool, since we want prioritise individual channels over expanders */ + /* NOTE: not bool, since we want prioritize individual channels over expanders. */ short found = 0; /* get all items - we need to do it this way */ @@ -442,7 +441,7 @@ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, floa found = acf->channel_role; /* only stop our search when we've found an actual channel - * - datablock expanders get less priority so that we don't abort prematurely + * - data-block expanders get less priority so that we don't abort prematurely */ if (found == ACHANNEL_ROLE_CHANNEL) { break; @@ -1532,11 +1531,11 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op) const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { - /* No re-ordering of strips whithin non-local tracks of override data. */ + /* No re-ordering of strips within non-local tracks of override data. */ continue; } - /* make temporary metastrips so that entire islands of selections can be moved around */ + /* Make temporary meta-strips so that entire islands of selections can be moved around. */ BKE_nlastrips_make_metas(&nlt->strips, 1); /* special case: if there is only 1 island diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 2e32c496170..631dc2e550c 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -30,16 +30,11 @@ #include "BKE_screen.h" #include "ED_anim_api.h" -#include "ED_markers.h" #include "ED_screen.h" -#include "ED_select_utils.h" -#include "ED_transform.h" #include "WM_api.h" #include "WM_types.h" -#include "RNA_access.h" - #include "nla_intern.h" /* own include */ /* ************************** poll callbacks for operators **********************************/ diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index c6fe1b8539e..011cd7e2651 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -24,7 +24,6 @@ #include <stdio.h> #include <string.h> -#include "DNA_anim_types.h" #include "DNA_collection_types.h" #include "DNA_scene_types.h" @@ -52,7 +51,6 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "GPU_framebuffer.h" #include "nla_intern.h" /* own include */ /* ******************** default callbacks for nla space ***************** */ @@ -324,12 +322,11 @@ static void nla_buttons_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void nla_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void nla_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -364,12 +361,11 @@ static void nla_region_listener(wmWindow *UNUSED(win), } } -static void nla_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void nla_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -423,14 +419,14 @@ static void nla_main_region_listener(wmWindow *UNUSED(win), } } -static void nla_main_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void nla_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + Scene *scene = params->scene; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceNLA, area->spacedata.first, &ptr); @@ -465,12 +461,11 @@ static void nla_main_region_message_subscribe(const struct bContext *UNUSED(C), } } -static void nla_channel_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void nla_channel_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -508,14 +503,13 @@ static void nla_channel_region_listener(wmWindow *UNUSED(win), } } -static void nla_channel_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void nla_channel_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceNLA, area->spacedata.first, &ptr); @@ -543,11 +537,11 @@ static void nla_channel_region_message_subscribe(const struct bContext *UNUSED(C } /* editor level listener */ -static void nla_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void nla_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index f2ee94af9b3..4716f1c29ea 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -190,7 +190,7 @@ static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA cumap->flag &= ~CUMA_DRAW_SAMPLE; } - /* "Tone" (Standard/Filmlike) only used in the Compositor. */ + /* "Tone" (Standard/Film-like) only used in the Compositor. */ bNodeTree *ntree = (bNodeTree *)ptr->owner_id; uiTemplateCurveMapping( layout, ptr, "mapping", 'c', false, false, false, (ntree->type == NTREE_COMPOSIT)); @@ -441,7 +441,7 @@ static void node_draw_frame(const bContext *C, const rctf *rct = &node->totr; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); + UI_draw_roundbox_aa(rct, true, BASIS_RAD, color); /* outline active and selected emphasis */ if (node->flag & SELECT) { @@ -452,11 +452,11 @@ static void node_draw_frame(const bContext *C, UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -40, color); } - UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); + UI_draw_roundbox_aa(rct, false, BASIS_RAD, color); } /* label */ - node_draw_frame_label(ntree, node, snode->aspect); + node_draw_frame_label(ntree, node, snode->runtime->aspect); UI_block_end(C, node->block); UI_block_draw(C, node->block); @@ -559,7 +559,7 @@ static void node_draw_reroute(const bContext *C, if (node->flag & SELECT) { GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); - /* using different shades of TH_TEXT_HI for the empasis, like triangle */ + /* Using different shades of #TH_TEXT_HI for the emphasis, like triangle. */ if (node->flag & NODE_ACTIVE) { UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, 0, -40, debug_color); } @@ -3126,270 +3126,6 @@ static void node_texture_set_butfunc(bNodeType *ntype) } } -/* ****************** BUTTON CALLBACKS FOR GEOMETRY NODES ***************** */ - -static void node_geometry_buts_boolean_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_geometry_buts_attribute_compare(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "input_type_a", DEFAULT_FLAGS, IFACE_("Type A"), ICON_NONE); - uiItemR(layout, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("Type B"), ICON_NONE); -} - -static void node_geometry_buts_subdivision_surface(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *UNUSED(ptr)) -{ -#ifndef WITH_OPENSUBDIV - uiItemL(layout, IFACE_("Disabled, built without OpenSubdiv"), ICON_ERROR); -#else - UNUSED_VARS(layout); -#endif -} - -static void node_geometry_buts_triangulate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "quad_method", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "ngon_method", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_geometry_buts_random_attribute(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_geometry_buts_attribute_math(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "input_type_a", DEFAULT_FLAGS, IFACE_("Type A"), ICON_NONE); - uiItemR(layout, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("Type B"), ICON_NONE); -} - -static void node_geometry_buts_attribute_vector_math(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - bNode *node = (bNode *)ptr->data; - NodeAttributeVectorMath *node_storage = (NodeAttributeVectorMath *)node->storage; - - uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "input_type_a", DEFAULT_FLAGS, IFACE_("Type A"), ICON_NONE); - - /* These "use input b / c" checks are copied from the node's code. - * They could be de-duplicated if the drawing code was moved to the node's file. */ - if (!ELEM(node_storage->operation, - NODE_VECTOR_MATH_NORMALIZE, - NODE_VECTOR_MATH_FLOOR, - NODE_VECTOR_MATH_CEIL, - NODE_VECTOR_MATH_FRACTION, - NODE_VECTOR_MATH_ABSOLUTE, - NODE_VECTOR_MATH_SINE, - NODE_VECTOR_MATH_COSINE, - NODE_VECTOR_MATH_TANGENT, - NODE_VECTOR_MATH_LENGTH)) { - uiItemR(layout, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("Type B"), ICON_NONE); - } - if (ELEM(node_storage->operation, NODE_VECTOR_MATH_WRAP)) { - uiItemR(layout, ptr, "input_type_c", DEFAULT_FLAGS, IFACE_("Type C"), ICON_NONE); - } -} - -static void node_geometry_buts_point_instance(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "instance_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); - if (RNA_enum_get(ptr, "instance_type") == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION) { - uiItemR(layout, ptr, "use_whole_collection", DEFAULT_FLAGS, NULL, ICON_NONE); - } -} - -static void node_geometry_buts_attribute_fill(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); - // uiItemR(layout, ptr, "domain", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_geometry_buts_attribute_mix(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE); - uiLayout *col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "input_type_factor", DEFAULT_FLAGS, IFACE_("Factor"), ICON_NONE); - uiItemR(col, ptr, "input_type_a", DEFAULT_FLAGS, IFACE_("A"), ICON_NONE); - uiItemR(col, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("B"), ICON_NONE); -} - -static void node_geometry_buts_attribute_point_distribute(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "distribute_method", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_geometry_buts_attribute_color_ramp(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiTemplateColorRamp(layout, ptr, "color_ramp", 0); -} - -static void node_geometry_buts_point_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - NodeGeometryRotatePoints *storage = (NodeGeometryRotatePoints *)((bNode *)ptr->data)->storage; - - uiItemR(layout, ptr, "type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(layout, ptr, "space", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); - - uiLayout *col = uiLayoutColumn(layout, false); - if (storage->type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE) { - uiItemR(col, ptr, "input_type_axis", DEFAULT_FLAGS, IFACE_("Axis"), ICON_NONE); - uiItemR(col, ptr, "input_type_angle", DEFAULT_FLAGS, IFACE_("Angle"), ICON_NONE); - } - else { - uiItemR(col, ptr, "input_type_rotation", DEFAULT_FLAGS, IFACE_("Rotation"), ICON_NONE); - } -} - -static void node_geometry_buts_align_rotation_to_vector(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiLayout *col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "input_type_factor", DEFAULT_FLAGS, IFACE_("Factor"), ICON_NONE); - uiItemR(col, ptr, "input_type_vector", DEFAULT_FLAGS, IFACE_("Vector"), ICON_NONE); -} -static void node_geometry_buts_point_translate(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "input_type", DEFAULT_FLAGS, IFACE_("Type"), ICON_NONE); -} - -static void node_geometry_buts_point_scale(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "input_type", DEFAULT_FLAGS, IFACE_("Type"), ICON_NONE); -} - -static void node_geometry_buts_object_info(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "transform_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE); -} - -static void node_geometry_set_butfunc(bNodeType *ntype) -{ - switch (ntype->type) { - case GEO_NODE_BOOLEAN: - ntype->draw_buttons = node_geometry_buts_boolean_math; - break; - case GEO_NODE_SUBDIVISION_SURFACE: - ntype->draw_buttons = node_geometry_buts_subdivision_surface; - break; - case GEO_NODE_TRIANGULATE: - ntype->draw_buttons = node_geometry_buts_triangulate; - break; - case GEO_NODE_ATTRIBUTE_RANDOMIZE: - ntype->draw_buttons = node_geometry_buts_random_attribute; - break; - case GEO_NODE_ATTRIBUTE_MATH: - ntype->draw_buttons = node_geometry_buts_attribute_math; - break; - case GEO_NODE_ATTRIBUTE_COMPARE: - ntype->draw_buttons = node_geometry_buts_attribute_compare; - break; - case GEO_NODE_POINT_INSTANCE: - ntype->draw_buttons = node_geometry_buts_point_instance; - break; - case GEO_NODE_ATTRIBUTE_FILL: - ntype->draw_buttons = node_geometry_buts_attribute_fill; - break; - case GEO_NODE_ATTRIBUTE_MIX: - ntype->draw_buttons = node_geometry_buts_attribute_mix; - break; - case GEO_NODE_ATTRIBUTE_VECTOR_MATH: - ntype->draw_buttons = node_geometry_buts_attribute_vector_math; - break; - case GEO_NODE_POINT_DISTRIBUTE: - ntype->draw_buttons = node_geometry_buts_attribute_point_distribute; - break; - case GEO_NODE_ATTRIBUTE_COLOR_RAMP: - ntype->draw_buttons = node_geometry_buts_attribute_color_ramp; - break; - case GEO_NODE_POINT_ROTATE: - ntype->draw_buttons = node_geometry_buts_point_rotate; - break; - case GEO_NODE_ALIGN_ROTATION_TO_VECTOR: - ntype->draw_buttons = node_geometry_buts_align_rotation_to_vector; - break; - case GEO_NODE_POINT_TRANSLATE: - ntype->draw_buttons = node_geometry_buts_point_translate; - break; - case GEO_NODE_POINT_SCALE: - ntype->draw_buttons = node_geometry_buts_point_scale; - break; - case GEO_NODE_OBJECT_INFO: - ntype->draw_buttons = node_geometry_buts_object_info; - break; - } -} - -/* ****************** BUTTON CALLBACKS FOR FUNCTION NODES ***************** */ - -static void node_function_buts_boolean_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_function_buts_float_compare(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_function_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_function_buts_input_vector(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayout *col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "vector", UI_ITEM_R_EXPAND, "", ICON_NONE); -} - -static void node_function_set_butfunc(bNodeType *ntype) -{ - switch (ntype->type) { - case FN_NODE_BOOLEAN_MATH: - ntype->draw_buttons = node_function_buts_boolean_math; - break; - case FN_NODE_FLOAT_COMPARE: - ntype->draw_buttons = node_function_buts_float_compare; - break; - case FN_NODE_SWITCH: - ntype->draw_buttons = node_function_buts_switch; - break; - case FN_NODE_INPUT_VECTOR: - ntype->draw_buttons = node_function_buts_input_vector; - break; - } -} - /* ****** init draw callbacks for all tree types, only called in usiblender.c, once ************ */ static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) @@ -3489,8 +3225,6 @@ void ED_node_init_butfuncs(void) ntype->draw_nodetype_prepare = node_update_default; ntype->select_area_func = node_select_area_default; ntype->tweak_area_func = node_tweak_area_default; - ntype->draw_buttons = NULL; - ntype->draw_buttons_ex = NULL; ntype->resize_area_func = node_resize_area_default; node_common_set_butfunc(ntype); @@ -3498,8 +3232,6 @@ void ED_node_init_butfuncs(void) node_composit_set_butfunc(ntype); node_shader_set_butfunc(ntype); node_texture_set_butfunc(ntype); - node_geometry_set_butfunc(ntype); - node_function_set_butfunc(ntype); /* define update callbacks for socket properties */ node_template_properties_update(ntype); @@ -3828,18 +3560,18 @@ void draw_nodespace_back_pix(const bContext *C, } /* return quadratic beziers points for a given nodelink and clip if v2d is not NULL. */ -static bool node_link_bezier_handles(View2D *v2d, - SpaceNode *snode, - bNodeLink *link, - float vec[4][2]) +bool node_link_bezier_handles(const View2D *v2d, + const SpaceNode *snode, + const bNodeLink *link, + float vec[4][2]) { float cursor[2] = {0.0f, 0.0f}; /* this function can be called with snode null (via cut_links_intersect) */ - /* XXX map snode->cursor back to view space */ + /* XXX map snode->runtime->cursor back to view space */ if (snode) { - cursor[0] = snode->cursor[0] * UI_DPI_FAC; - cursor[1] = snode->cursor[1] * UI_DPI_FAC; + cursor[0] = snode->runtime->cursor[0] * UI_DPI_FAC; + cursor[1] = snode->runtime->cursor[1] * UI_DPI_FAC; } /* in v0 and v3 we put begin/end points */ @@ -3859,6 +3591,9 @@ static bool node_link_bezier_handles(View2D *v2d, if (link->tosock) { vec[3][0] = link->tosock->locx; vec[3][1] = link->tosock->locy; + if (!(link->tonode->flag & NODE_HIDDEN) && link->tosock->flag & SOCK_MULTI_INPUT) { + node_link_calculate_multi_input_position(link, vec[3]); + } toreroute = (link->tonode && link->tonode->type == NODE_REROUTE); } else { @@ -3923,8 +3658,11 @@ static bool node_link_bezier_handles(View2D *v2d, } /* if v2d not NULL, it clips and returns 0 if not visible */ -bool node_link_bezier_points( - View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol) +bool node_link_bezier_points(const View2D *v2d, + const SpaceNode *snode, + const bNodeLink *link, + float coord_array[][2], + const int resol) { float vec[4][2]; @@ -4087,7 +3825,7 @@ static char nodelink_get_color_id(int th_col) return 0; } -static void nodelink_batch_draw(SpaceNode *snode) +static void nodelink_batch_draw(const SpaceNode *snode) { if (g_batch_link.count == 0) { return; @@ -4107,7 +3845,7 @@ static void nodelink_batch_draw(SpaceNode *snode) GPU_batch_program_set_builtin(g_batch_link.batch, GPU_SHADER_2D_NODELINK_INST); GPU_batch_uniform_4fv_array(g_batch_link.batch, "colors", 6, colors); - GPU_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->aspect * LINK_WIDTH); + GPU_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->runtime->aspect * LINK_WIDTH); GPU_batch_uniform_1f(g_batch_link.batch, "arrowSize", ARROW_SIZE); GPU_batch_draw(g_batch_link.batch); @@ -4127,7 +3865,7 @@ void nodelink_batch_end(SpaceNode *snode) g_batch_link.enabled = false; } -static void nodelink_batch_add_link(SpaceNode *snode, +static void nodelink_batch_add_link(const SpaceNode *snode, const float p0[2], const float p1[2], const float p2[2], @@ -4159,11 +3897,15 @@ static void nodelink_batch_add_link(SpaceNode *snode, } /* don't do shadows if th_col3 is -1. */ -void node_draw_link_bezier( - View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int th_col2, int th_col3) +void node_draw_link_bezier(const View2D *v2d, + const SpaceNode *snode, + const bNodeLink *link, + int th_col1, + int th_col2, + int th_col3) { float vec[4][2]; - + const bool highlighted = link->flag & NODE_LINK_TEMP_HIGHLIGHT; if (node_link_bezier_handles(v2d, snode, link, vec)) { int drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) && (link->fromnode && (link->fromnode->type == NODE_REROUTE))); @@ -4172,7 +3914,7 @@ void node_draw_link_bezier( nodelink_batch_init(); } - if (g_batch_link.enabled) { + if (g_batch_link.enabled && !highlighted) { /* Add link to batch. */ nodelink_batch_add_link( snode, vec[0], vec[1], vec[2], vec[3], th_col1, th_col2, th_col3, drawarrow); @@ -4186,11 +3928,17 @@ void node_draw_link_bezier( UI_GetThemeColor4fv(th_col1, colors[1]); UI_GetThemeColor4fv(th_col2, colors[2]); + if (highlighted) { + float link_preselection_highlight_color[4]; + UI_GetThemeColor4fv(TH_SELECT, link_preselection_highlight_color); + copy_v4_v4(colors[2], link_preselection_highlight_color); + } + GPUBatch *batch = g_batch_link.batch_single; GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK); GPU_batch_uniform_2fv_array(batch, "bezierPts", 4, vec); GPU_batch_uniform_4fv_array(batch, "colors", 3, colors); - GPU_batch_uniform_1f(batch, "expandSize", snode->aspect * LINK_WIDTH); + GPU_batch_uniform_1f(batch, "expandSize", snode->runtime->aspect * LINK_WIDTH); GPU_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE); GPU_batch_uniform_1i(batch, "doArrow", drawarrow); GPU_batch_draw(batch); diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index 508c0a47e21..e665f7b1d52 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -104,9 +104,8 @@ static bool add_reroute_intersect_check(bNodeLink *link, if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) { for (int i = 0; i < tot - 1; i++) { for (int b = 0; b < NODE_LINK_RESOL; b++) { - if (isect_seg_seg_v2(mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1]) > 0) { - result[0] = (mcoords[i][0] + mcoords[i + 1][0]) / 2.0f; - result[1] = (mcoords[i][1] + mcoords[i + 1][1]) / 2.0f; + if (isect_seg_seg_v2_point( + mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1], result) > 0) { return true; } } @@ -312,6 +311,13 @@ void NODE_OT_add_reroute(wmOperatorType *ot) /* ****************** Add File Node Operator ******************* */ +static bool node_add_file_poll(bContext *C) +{ + const SpaceNode *snode = CTX_wm_space_node(C); + return ED_operator_node_editable(C) && + ELEM(snode->nodetree->type, NTREE_SHADER, NTREE_TEXTURE, NTREE_COMPOSIT); +} + static int node_add_file_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -341,7 +347,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); - node = node_add_node(C, NULL, type, snode->cursor[0], snode->cursor[1]); + node = node_add_node(C, NULL, type, snode->runtime->cursor[0], snode->runtime->cursor[1]); if (!node) { BKE_report(op->reports, RPT_WARNING, "Could not add an image node"); @@ -370,11 +376,14 @@ static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *even SpaceNode *snode = CTX_wm_space_node(C); /* convert mouse coordinates to v2d space */ - UI_view2d_region_to_view( - ®ion->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]); + UI_view2d_region_to_view(®ion->v2d, + event->mval[0], + event->mval[1], + &snode->runtime->cursor[0], + &snode->runtime->cursor[1]); - snode->cursor[0] /= UI_DPI_FAC; - snode->cursor[1] /= UI_DPI_FAC; + snode->runtime->cursor[0] /= UI_DPI_FAC; + snode->runtime->cursor[1] /= UI_DPI_FAC; if (RNA_struct_property_is_set(op->ptr, "filepath") || RNA_struct_property_is_set(op->ptr, "name")) { @@ -393,7 +402,7 @@ void NODE_OT_add_file(wmOperatorType *ot) /* callbacks */ ot->exec = node_add_file_exec; ot->invoke = node_add_file_invoke; - ot->poll = ED_operator_node_editable; + ot->poll = node_add_file_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -435,7 +444,8 @@ static int node_add_mask_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); - node = node_add_node(C, NULL, CMP_NODE_MASK, snode->cursor[0], snode->cursor[1]); + node = node_add_node( + C, NULL, CMP_NODE_MASK, snode->runtime->cursor[0], snode->runtime->cursor[1]); if (!node) { BKE_report(op->reports, RPT_WARNING, "Could not add a mask node"); diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index c9a0c827a09..fa4d6997c83 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -40,7 +40,6 @@ #include "RNA_access.h" -#include "ED_gpencil.h" #include "ED_screen.h" #include "UI_resources.h" diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index d3fec7257f5..c7be5f848f7 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -22,6 +22,8 @@ * \brief higher level node drawing for the node editor. */ +#include "MEM_guardedalloc.h" + #include "DNA_light_types.h" #include "DNA_linestyle_types.h" #include "DNA_material_types.h" @@ -317,14 +319,14 @@ static void node_uiblocks_init(const bContext *C, bNodeTree *ntree) } } -void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry) +void node_to_view(const bNode *node, float x, float y, float *rx, float *ry) { nodeToView(node, x, y, rx, ry); *rx *= UI_DPI_FAC; *ry *= UI_DPI_FAC; } -void node_to_updated_rect(struct bNode *node, rctf *r_rect) +void node_to_updated_rect(const bNode *node, rctf *r_rect) { node_to_view(node, node->offsetx, node->offsety, &r_rect->xmin, &r_rect->ymax); node_to_view(node, @@ -334,7 +336,7 @@ void node_to_updated_rect(struct bNode *node, rctf *r_rect) &r_rect->ymin); } -void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry) +void node_from_view(const bNode *node, float x, float y, float *rx, float *ry) { x /= UI_DPI_FAC; y /= UI_DPI_FAC; @@ -500,6 +502,16 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) PointerRNA sockptr; RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr); + /* Add the half the height of a multi-input socket to cursor Y + * to account for the increased height of the taller sockets. */ + float multi_input_socket_offset = 0.0f; + if (nsock->flag & SOCK_MULTI_INPUT) { + if (nsock->total_inputs > 2) { + multi_input_socket_offset = (nsock->total_inputs - 2) * NODE_MULTI_INPUT_LINK_GAP; + } + } + dy -= multi_input_socket_offset * 0.5f; + uiLayout *layout = UI_block_layout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, @@ -533,7 +545,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) /* place the socket circle in the middle of the layout */ nsock->locy = 0.5f * (dy + buty); - dy = buty; + dy = buty - multi_input_socket_offset * 0.5; if (nsock->next) { dy -= NODE_SOCKDY; } @@ -689,11 +701,11 @@ int node_get_colorid(bNode *node) /* note: in cmp_util.c is similar code, for node_compo_pass_on() * the same goes for shader and texture nodes. */ /* note: in node_edit.c is similar code, for untangle node */ -static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) +static void node_draw_mute_line(const View2D *v2d, const SpaceNode *snode, const bNode *node) { GPU_blend(GPU_BLEND_ALPHA); - LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) { + LISTBASE_FOREACH (const bNodeLink *, link, &node->internal_links) { node_draw_link_bezier(v2d, snode, link, TH_REDALERT, TH_REDALERT, -1); } @@ -751,6 +763,27 @@ static void node_socket_draw(const bNodeSocket *sock, immVertex2f(pos_id, locx, locy); } +static void node_socket_draw_multi_input(const float color[4], + const float color_outline[4], + const float width, + const float height, + const int locx, + const int locy) +{ + const float outline_width = 1.0f; + /* UI_draw_roundbox draws the outline on the outer side, so compensate for the outline width. */ + const rctf rect = { + .xmin = locx - width + outline_width * 0.5f, + .xmax = locx + width - outline_width * 0.5f, + .ymin = locy - height + outline_width * 0.5f, + .ymax = locy + height - outline_width * 0.5f, + }; + + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_4fv_ex( + &rect, color, NULL, 1.0f, color_outline, outline_width, width - outline_width * 0.5f); +} + static void node_socket_outline_color_get(bool selected, float r_outline_color[4]) { if (selected) { @@ -947,14 +980,14 @@ static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_ WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, NULL); } -void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha) +void node_draw_shadow(const SpaceNode *snode, const bNode *node, float radius, float alpha) { - rctf *rct = &node->totr; + const rctf *rct = &node->totr; UI_draw_roundbox_corner_set(UI_CNR_ALL); - ui_draw_dropshadow(rct, radius, snode->aspect, alpha, node->flag & SELECT); + ui_draw_dropshadow(rct, radius, snode->runtime->aspect, alpha, node->flag & SELECT); } -void node_draw_sockets(View2D *v2d, +void node_draw_sockets(const View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *node, @@ -1006,6 +1039,10 @@ void node_draw_sockets(View2D *v2d, selected_input_len++; continue; } + /* Don't draw multi-input sockets here since they are drawn in a different batch. */ + if (sock->flag & SOCK_MULTI_INPUT) { + continue; + } node_socket_draw_nested(C, ntree, @@ -1115,11 +1152,33 @@ void node_draw_sockets(View2D *v2d, GPU_program_point_size(false); GPU_blend(GPU_BLEND_NONE); + + /* Draw multi-input sockets after the others because they are drawn with `UI_draw_roundbox` + * rather than with `GL_POINT`. */ + LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { + if (nodeSocketIsHidden(socket)) { + continue; + } + if (!(socket->flag & SOCK_MULTI_INPUT)) { + continue; + } + + const bool is_node_hidden = (node->flag & NODE_HIDDEN); + const float width = NODE_SOCKSIZE; + float height = is_node_hidden ? width : node_socket_calculate_height(socket) - width; + + float color[4]; + float outline_color[4]; + node_socket_color_get((bContext *)C, ntree, &node_ptr, socket, color); + node_socket_outline_color_get(selected, outline_color); + + node_socket_draw_multi_input(color, outline_color, width, height, socket->locx, socket->locy); + } } static void node_draw_basis(const bContext *C, - ARegion *region, - SpaceNode *snode, + const View2D *v2d, + const SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key) @@ -1127,8 +1186,6 @@ static void node_draw_basis(const bContext *C, /* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */ float iconbutw = 0.8f * UI_UNIT_X; - View2D *v2d = ®ion->v2d; - /* skip if out of view */ if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) { UI_block_end(C, node->block); @@ -1157,7 +1214,15 @@ static void node_draw_basis(const bContext *C, rctf *rct = &node->totr; UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); UI_draw_roundbox_aa( - true, rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD, color); + &(const rctf){ + .xmin = rct->xmin, + .xmax = rct->xmax, + .ymin = rct->ymax - NODE_DY, + .ymax = rct->ymax, + }, + true, + BASIS_RAD, + color); /* show/hide icons */ float iconofs = rct->xmax - 0.35f * U.widget_unit; @@ -1308,7 +1373,15 @@ static void node_draw_basis(const bContext *C, UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT); UI_draw_roundbox_aa( - true, rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD, color); + &(const rctf){ + .xmin = rct->xmin, + .xmax = rct->xmax, + .ymin = rct->ymin, + .ymax = rct->ymax - NODE_DY, + }, + true, + BASIS_RAD, + color); /* outline active and selected emphasis */ if (node->flag & SELECT) { @@ -1316,7 +1389,16 @@ static void node_draw_basis(const bContext *C, (node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = rct->xmin, + .xmax = rct->xmax, + .ymin = rct->ymin, + .ymax = rct->ymax, + }, + false, + BASIS_RAD, + color); } /* disable lines */ @@ -1343,8 +1425,8 @@ static void node_draw_basis(const bContext *C, } static void node_draw_hidden(const bContext *C, - ARegion *region, - SpaceNode *snode, + const View2D *v2d, + const SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key)) @@ -1353,8 +1435,6 @@ static void node_draw_hidden(const bContext *C, float centy = BLI_rctf_cent_y(rct); float hiddenrad = BLI_rctf_size_y(rct) / 2.0f; - View2D *v2d = ®ion->v2d; - float scale; UI_view2d_scale_get(v2d, &scale, NULL); @@ -1373,14 +1453,14 @@ static void node_draw_hidden(const bContext *C, UI_GetThemeColor4fv(color_id, color); } - UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color); + UI_draw_roundbox_aa(rct, true, hiddenrad, color); /* outline active and selected emphasis */ if (node->flag & SELECT) { UI_GetThemeColorShadeAlpha4fv( (node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color); - UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color); + UI_draw_roundbox_aa(rct, false, hiddenrad, color); } /* custom color inline */ @@ -1388,14 +1468,17 @@ static void node_draw_hidden(const bContext *C, GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); - UI_draw_roundbox_3fv_alpha(false, - rct->xmin + 1, - rct->ymin + 1, - rct->xmax - 1, - rct->ymax - 1, - hiddenrad, - node->color, - 1.0f); + UI_draw_roundbox_3fv_alpha( + &(const rctf){ + .xmin = rct->xmin + 1, + .xmax = rct->xmax - 1, + .ymin = rct->ymin + 1, + .ymax = rct->ymax - 1, + }, + false, + hiddenrad, + node->color, + 1.0f); GPU_line_smooth(false); GPU_blend(GPU_BLEND_NONE); @@ -1438,7 +1521,7 @@ static void node_draw_hidden(const bContext *C, /* disable lines */ if (node->flag & NODE_MUTED) { - node_draw_mute_line(®ion->v2d, snode, node); + node_draw_mute_line(v2d, snode, node); } char showname[128]; /* 128 is used below */ @@ -1477,19 +1560,19 @@ static void node_draw_hidden(const bContext *C, immVertex2f(pos, rct->xmax - dx, centy - 4.0f); immVertex2f(pos, rct->xmax - dx, centy + 4.0f); - immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f); - immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy + 4.0f); immEnd(); immUniformThemeColorShade(color_id, 30); - dx -= snode->aspect; + dx -= snode->runtime->aspect; immBegin(GPU_PRIM_LINES, 4); immVertex2f(pos, rct->xmax - dx, centy - 4.0f); immVertex2f(pos, rct->xmax - dx, centy + 4.0f); - immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f); - immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy + 4.0f); immEnd(); immUnbindProgram(); @@ -1550,11 +1633,12 @@ void node_draw_default(const bContext *C, bNode *node, bNodeInstanceKey key) { + const View2D *v2d = ®ion->v2d; if (node->flag & NODE_HIDDEN) { - node_draw_hidden(C, region, snode, ntree, node, key); + node_draw_hidden(C, v2d, snode, ntree, node, key); } else { - node_draw_basis(C, region, snode, ntree, node, key); + node_draw_basis(C, v2d, snode, ntree, node, key); } } @@ -1565,17 +1649,67 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node) } } +static void count_mutli_input_socket_links(bNodeTree *ntree, SpaceNode *snode) +{ + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + LISTBASE_FOREACH (struct bNodeSocket *, socket, &node->inputs) { + if (socket->flag & SOCK_MULTI_INPUT) { + socket->total_inputs = 0; + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { + if (link->tosock == socket) { + socket->total_inputs++; + } + } + /* Count temporary links going into this socket. */ + LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) { + LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { + bNodeLink *link = (bNodeLink *)linkdata->data; + if (link->tosock == socket) { + socket->total_inputs++; + } + } + } + } + } + } +} + void node_update_nodetree(const bContext *C, bNodeTree *ntree) { /* make sure socket "used" tags are correct, for displaying value buttons */ + SpaceNode *snode = CTX_wm_space_node(C); ntreeTagUsedSockets(ntree); + count_mutli_input_socket_links(ntree, snode); + /* update nodes front to back, so children sizes get updated before parents */ LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree->nodes) { node_update(C, ntree, node); } } +static int compare_link_by_angle_to_node(const void *a, const void *b) +{ + const bNodeLink *link_a = *(const bNodeLink **)a; + const bNodeLink *link_b = *(const bNodeLink **)b; + + BLI_assert(link_a->tosock == link_b->tosock); + const float socket_location[2] = {link_a->tosock->locx, link_a->tosock->locy}; + const float up_direction[2] = {0.0f, 1.0f}; + + float delta_a[2] = {link_a->fromsock->locx - socket_location[0], + link_a->fromsock->locy - socket_location[1]}; + normalize_v2(delta_a); + const float angle_a = angle_normalized_v2v2(up_direction, delta_a); + + float delta_b[2] = {link_b->fromsock->locx - socket_location[0], + link_b->fromsock->locy - socket_location[1]}; + normalize_v2(delta_b); + const float angle_b = angle_normalized_v2v2(up_direction, delta_b); + + return angle_a < angle_b ? 1 : -1; +} + static void node_draw(const bContext *C, ARegion *region, SpaceNode *snode, @@ -1590,6 +1724,46 @@ static void node_draw(const bContext *C, #define USE_DRAW_TOT_UPDATE +/** + * Automatically sort the input links to multi-input sockets to avoid crossing noodles. + */ +static void sort_multi_input_socket_links(bNodeTree *ntree, SpaceNode *snode) +{ + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { + if (socket->flag & SOCK_MULTI_INPUT) { + /* The total is calculated in #node_update_nodetree, which runs before this draw step. */ + const int total_inputs = socket->total_inputs; + bNodeLink **input_links = MEM_malloc_arrayN(total_inputs, sizeof(bNodeLink *), __func__); + + int index = 0; + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { + if (link->tosock == socket) { + input_links[index] = (bNodeLink *)link; + index++; + } + } + LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) { + LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { + bNodeLink *link = (bNodeLink *)linkdata->data; + if (link->tosock == socket) { + input_links[index] = (bNodeLink *)link; + index++; + } + } + } + + qsort(input_links, total_inputs, sizeof(bNodeLink *), compare_link_by_angle_to_node); + for (int i = 0; i < total_inputs; i++) { + input_links[i]->multi_input_socket_index = i; + } + + MEM_freeN(input_links); + } + } + } +} + void node_draw_nodetree(const bContext *C, ARegion *region, SpaceNode *snode, @@ -1607,8 +1781,7 @@ void node_draw_nodetree(const bContext *C, #endif /* draw background nodes, last nodes in front */ - int a = 0; - LISTBASE_FOREACH_INDEX (bNode *, node, &ntree->nodes, a) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { #ifdef USE_DRAW_TOT_UPDATE /* unrelated to background nodes, update the v2d->tot, * can be anywhere before we draw the scroll bars */ @@ -1626,6 +1799,9 @@ void node_draw_nodetree(const bContext *C, /* node lines */ GPU_blend(GPU_BLEND_ALPHA); nodelink_batch_start(snode); + + sort_multi_input_socket_links(ntree, snode); + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { if (!nodeLinkIsHidden(link)) { node_draw_link(®ion->v2d, snode, link); @@ -1635,8 +1811,7 @@ void node_draw_nodetree(const bContext *C, GPU_blend(GPU_BLEND_NONE); /* draw foreground nodes, last nodes in front */ - a = 0; - LISTBASE_FOREACH_INDEX (bNode *, node, &ntree->nodes, a) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & NODE_BACKGROUND) { continue; } @@ -1666,7 +1841,7 @@ static void snode_setup_v2d(SpaceNode *snode, ARegion *region, const float cente UI_view2d_view_ortho(v2d); /* aspect+font, set each time */ - snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)region->winx; + snode->runtime->aspect = BLI_rctf_size_x(&v2d->cur) / (float)region->winx; // XXX snode->curfont = uiSetCurFont_ext(snode->aspect); } @@ -1686,8 +1861,8 @@ static void draw_nodetree(const bContext *C, /* shade the parent node group and add a uiBlock to clip mouse events */ static void draw_group_overlay(const bContext *C, ARegion *region) { - View2D *v2d = ®ion->v2d; - rctf rect = v2d->cur; + const View2D *v2d = ®ion->v2d; + const rctf rect = v2d->cur; float color[4]; /* shade node groups to separate them visually */ @@ -1695,7 +1870,7 @@ static void draw_group_overlay(const bContext *C, ARegion *region) UI_GetThemeColorShadeAlpha4fv(TH_NODE_GROUP, 0, 0, color); UI_draw_roundbox_corner_set(UI_CNR_NONE); - UI_draw_roundbox_4fv(true, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color); + UI_draw_roundbox_4fv(&rect, true, 0, color); GPU_blend(GPU_BLEND_NONE); /* set the block bounds to clip mouse events from underlying nodes */ @@ -1722,14 +1897,15 @@ void node_draw_space(const bContext *C, ARegion *region) GPU_depth_test(GPU_DEPTH_NONE); GPU_scissor_test(true); - /* XXX snode->cursor set in coordspace for placing new nodes, used for drawing noodles too */ + /* XXX snode->runtime->cursor set in coordspace for placing new nodes, used for drawing noodles + * too */ UI_view2d_region_to_view(®ion->v2d, win->eventstate->x - region->winrct.xmin, win->eventstate->y - region->winrct.ymin, - &snode->cursor[0], - &snode->cursor[1]); - snode->cursor[0] /= UI_DPI_FAC; - snode->cursor[1] /= UI_DPI_FAC; + &snode->runtime->cursor[0], + &snode->runtime->cursor[1]); + snode->runtime->cursor[0] /= UI_DPI_FAC; + snode->runtime->cursor[1] /= UI_DPI_FAC; int grid_levels = UI_GetThemeValueType(TH_NODE_GRID_LEVELS, SPACE_NODE); @@ -1819,7 +1995,7 @@ void node_draw_space(const bContext *C, ARegion *region) /* temporary links */ GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); - LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->linkdrag) { + LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) { LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { node_draw_link(v2d, snode, (bNodeLink *)linkdata->data); } @@ -1847,7 +2023,7 @@ void node_draw_space(const bContext *C, ARegion *region) if (snode->treepath.last) { if (snode->flag & SNODE_SHOW_GPENCIL) { - /* draw grease-pencil (screen strokes, and also paintbuffer) */ + /* Draw grease-pencil (screen strokes, and also paint-buffer). */ ED_annotation_draw_view2d(C, false); } } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 30eee416b12..04787748937 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -98,6 +98,25 @@ typedef struct CompoJob { float *progress; } CompoJob; +float node_socket_calculate_height(const bNodeSocket *socket) +{ + float sock_height = NODE_SOCKSIZE * 2.0f; + if (socket->flag & SOCK_MULTI_INPUT) { + sock_height += max_ii(NODE_MULTI_INPUT_LINK_GAP * 0.5f * socket->total_inputs, NODE_SOCKSIZE); + } + return sock_height; +} + +void node_link_calculate_multi_input_position(const bNodeLink *link, float r[2]) +{ + float offset = (link->tosock->total_inputs * NODE_MULTI_INPUT_LINK_GAP - + NODE_MULTI_INPUT_LINK_GAP) * + 0.5; + r[0] = link->tosock->locx - NODE_SOCKSIZE * 0.5f; + r[1] = link->tosock->locy - offset + + (link->multi_input_socket_index * NODE_MULTI_INPUT_LINK_GAP); +} + static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags) { LISTBASE_FOREACH (bNode *, node, &nodetree->nodes) { @@ -770,7 +789,7 @@ void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree)) * which only exists during actual drawing. Can we rely on valid totr rects? */ /* make sure nodes have correct bounding boxes after transform */ - /* node_update_nodetree(C, ntree, 0.0f, 0.0f); */ + // node_update_nodetree(C, ntree, 0.0f, 0.0f); } /* ***************** generic operator functions for nodes ***************** */ @@ -880,8 +899,8 @@ static void node_resize_init( NodeSizeWidget *nsw = MEM_callocN(sizeof(NodeSizeWidget), "size widget op data"); op->customdata = nsw; - nsw->mxstart = snode->cursor[0] * UI_DPI_FAC; - nsw->mystart = snode->cursor[1] * UI_DPI_FAC; + nsw->mxstart = snode->runtime->cursor[0] * UI_DPI_FAC; + nsw->mystart = snode->runtime->cursor[1] * UI_DPI_FAC; /* store old */ nsw->oldlocx = node->locx; @@ -1104,6 +1123,21 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) } /* checks snode->mouse position, and returns found node/socket */ +static bool cursor_isect_multi_input_socket(const float cursor[2], const bNodeSocket *socket) +{ + const float node_socket_height = node_socket_calculate_height(socket); + const rctf multi_socket_rect = { + .xmin = socket->locx - NODE_SOCKSIZE * 4, + .xmax = socket->locx + NODE_SOCKSIZE, + .ymin = socket->locy - node_socket_height * 0.5 - NODE_SOCKSIZE * 2.0f, + .ymax = socket->locy + node_socket_height * 0.5 + NODE_SOCKSIZE * 2.0f, + }; + if (BLI_rctf_isect_pt(&multi_socket_rect, cursor[0], cursor[1])) { + return true; + } + return false; +} + /* type is SOCK_IN and/or SOCK_OUT */ int node_find_indicated_socket( SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, float cursor[2], int in_out) @@ -1132,7 +1166,16 @@ int node_find_indicated_socket( if (in_out & SOCK_IN) { LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { if (!nodeSocketIsHidden(sock)) { - if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) { + if (sock->flag & SOCK_MULTI_INPUT && !(node->flag & NODE_HIDDEN)) { + if (cursor_isect_multi_input_socket(cursor, sock)) { + if (node == visible_node(snode, &rect)) { + *nodep = node; + *sockp = sock; + return 1; + } + } + } + else if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) { if (node == visible_node(snode, &rect)) { *nodep = node; *sockp = sock; @@ -1199,7 +1242,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) if (node->flag & SELECT) { BKE_node_copy_store_new_pointers(ntree, node, LIB_ID_COPY_DEFAULT); - /* to ensure redraws or rerenders happen */ + /* To ensure redraws or re-renders happen. */ ED_node_tag_update_id(snode->id); } diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index f2abe272f48..7f530408ec7 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -1039,7 +1039,7 @@ static int node_group_make_exec(bContext *C, wmOperator *op) snode_notify(C, snode); snode_dag_update(C, snode); - /* We broke relations in node tree, need to rebuild them in the grahes. */ + /* We broke relations in node tree, need to rebuild them in the graphs. */ DEG_relations_tag_update(bmain); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index aa59b7293a3..2f3fa6996af 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -37,6 +37,7 @@ struct bContext; struct bNode; struct bNodeLink; struct bNodeSocket; +struct NodeInsertOfsData; struct wmGizmoGroupType; struct wmKeyConfig; struct wmWindow; @@ -50,25 +51,49 @@ typedef struct bNodeLinkDrag { * This way the links can be added to the node tree while being stored in this list. */ ListBase links; + bool from_multi_input_socket; int in_out; } bNodeLinkDrag; +typedef struct SpaceNode_Runtime { + float aspect; + + /** Mouse position for drawing socket-less links and adding nodes. */ + float cursor[2]; + + /** For auto compositing. */ + bool recalc; + + /** Temporary data for modal linking operator. */ + struct ListBase linkdrag; + + /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */ + /** Temporary data for node insert offset (in UI called Auto-offset). */ + struct NodeInsertOfsData *iofsd; +} SpaceNode_Runtime; + /* space_node.c */ /* transform between View2Ds in the tree path */ void space_node_group_offset(struct SpaceNode *snode, float *x, float *y); /* node_draw.c */ +float node_socket_calculate_height(const bNodeSocket *socket); +void node_link_calculate_multi_input_position(const bNodeLink *link, float r[2]); + int node_get_colorid(struct bNode *node); int node_get_resize_cursor(int directions); -void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha); +void node_draw_shadow(const struct SpaceNode *snode, + const struct bNode *node, + float radius, + float alpha); void node_draw_default(const struct bContext *C, struct ARegion *region, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key); -void node_draw_sockets(struct View2D *v2d, +void node_draw_sockets(const struct View2D *v2d, const struct bContext *C, struct bNodeTree *ntree, struct bNode *node, @@ -92,9 +117,9 @@ void node_draw_space(const bContext *C, ARegion *region); void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]); /* DPI scaled coords */ -void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry); -void node_to_updated_rect(struct bNode *node, rctf *r_rect); -void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry); +void node_to_view(const struct bNode *node, float x, float y, float *rx, float *ry); +void node_to_updated_rect(const struct bNode *node, rctf *r_rect); +void node_from_view(const struct bNode *node, float x, float y, float *rx, float *ry); /* node_buttons.c */ void node_buttons_register(struct ARegionType *art); @@ -145,17 +170,21 @@ void nodelink_batch_start(struct SpaceNode *snode); void nodelink_batch_end(struct SpaceNode *snode); void node_draw_link(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link); -void node_draw_link_bezier(struct View2D *v2d, - struct SpaceNode *snode, - struct bNodeLink *link, +void node_draw_link_bezier(const struct View2D *v2d, + const struct SpaceNode *snode, + const struct bNodeLink *link, int th_col1, int th_col2, int th_col3); -bool node_link_bezier_points(struct View2D *v2d, - struct SpaceNode *snode, - struct bNodeLink *link, +bool node_link_bezier_points(const struct View2D *v2d, + const struct SpaceNode *snode, + const struct bNodeLink *link, float coord_array[][2], - int resol); + const int resol); +bool node_link_bezier_handles(const struct View2D *v2d, + const struct SpaceNode *snode, + const struct bNodeLink *link, + float vec[4][2]); void draw_nodespace_back_pix(const struct bContext *C, struct ARegion *region, struct SpaceNode *snode, @@ -268,6 +297,7 @@ extern const char *node_context_dir[]; #define NODE_HEIGHT(node) (node->height * UI_DPI_FAC) #define NODE_MARGIN_X (1.10f * U.widget_unit) #define NODE_SOCKSIZE (0.25f * U.widget_unit) +#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 diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 11933ef0811..d55fd06ddea 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -23,14 +23,10 @@ #include "DNA_node_types.h" -#include "BLI_utildefines.h" - #include "BKE_context.h" #include "ED_node.h" /* own include */ #include "ED_screen.h" -#include "ED_select_utils.h" -#include "ED_transform.h" #include "RNA_access.h" diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index ba1e752e276..d6edfcce8e8 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -32,6 +32,7 @@ #include "BKE_anim_data.h" #include "BKE_context.h" +#include "BKE_curve.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_node.h" @@ -58,7 +59,7 @@ static bool ntree_has_drivers(bNodeTree *ntree) { - AnimData *adt = BKE_animdata_from_id(&ntree->id); + const AnimData *adt = BKE_animdata_from_id(&ntree->id); if (adt == NULL) { return false; } @@ -179,6 +180,137 @@ typedef struct NodeInsertOfsData { float offset_x; /* offset to apply to node chain */ } NodeInsertOfsData; +static void clear_picking_highlight(ListBase *links) +{ + LISTBASE_FOREACH (bNodeLink *, link, links) { + link->flag &= ~NODE_LINK_TEMP_HIGHLIGHT; + } +} + +static LinkData *create_drag_link(Main *bmain, SpaceNode *snode, bNode *node, bNodeSocket *sock) +{ + LinkData *linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data"); + bNodeLink *oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); + linkdata->data = oplink; + if (sock->in_out == SOCK_OUT) { + oplink->fromnode = node; + oplink->fromsock = sock; + } + else { + oplink->tonode = node; + oplink->tosock = sock; + } + oplink->flag |= NODE_LINK_VALID; + oplink->flag &= ~NODE_LINK_TEST; + if (node_connected_to_output(bmain, snode->edittree, node)) { + oplink->flag |= NODE_LINK_TEST; + } + return linkdata; +} + +static void pick_link(const bContext *C, + wmOperator *op, + bNodeLinkDrag *nldrag, + SpaceNode *snode, + bNode *node, + bNodeLink *link_to_pick) +{ + clear_picking_highlight(&snode->edittree->links); + RNA_boolean_set(op->ptr, "has_link_picked", true); + + Main *bmain = CTX_data_main(C); + LinkData *linkdata = create_drag_link( + bmain, snode, link_to_pick->fromnode, link_to_pick->fromsock); + + BLI_addtail(&nldrag->links, linkdata); + nodeRemLink(snode->edittree, link_to_pick); + /* Send changed event to original link->tonode. */ + if (node) { + snode_update(snode, node); + } +} + +static void pick_input_link_by_link_intersect(const bContext *C, + wmOperator *op, + bNodeLinkDrag *nldrag, + const float *cursor) +{ + SpaceNode *snode = CTX_wm_space_node(C); + const ARegion *region = CTX_wm_region(C); + const View2D *v2d = ®ion->v2d; + + float drag_start[2]; + RNA_float_get_array(op->ptr, "drag_start", drag_start); + bNode *node; + bNodeSocket *socket; + node_find_indicated_socket(snode, &node, &socket, drag_start, SOCK_IN); + + const float trigger_drag_distance = 25.0f; + const float cursor_link_touch_distance = 25.0f; + + const float socket_height = node_socket_calculate_height(socket); + + float cursor_to_socket_relative[2]; + float socket_position[2] = {socket->locx, socket->locy}; + sub_v2_v2v2(cursor_to_socket_relative, cursor, socket_position); + float distance_from_socket_v2[2] = { + max_ff(0, fabs(cursor_to_socket_relative[0]) - NODE_SOCKSIZE * 0.5), + max_ff(0, fabs(cursor_to_socket_relative[1]) - socket_height)}; + const float distance_from_socket = len_v2(distance_from_socket_v2); + + const int resolution = NODE_LINK_RESOL; + + bNodeLink *link_to_pick = NULL; + clear_picking_highlight(&snode->edittree->links); + LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { + if (link->tosock == socket) { + /* Test if the cursor is near a link. */ + float vec[4][2]; + node_link_bezier_handles(v2d, snode, link, vec); + + float data[NODE_LINK_RESOL * 2 + 2]; + BKE_curve_forward_diff_bezier( + vec[0][0], vec[1][0], vec[2][0], vec[3][0], data, resolution, sizeof(float[2])); + BKE_curve_forward_diff_bezier( + vec[0][1], vec[1][1], vec[2][1], vec[3][1], data + 1, resolution, sizeof(float[2])); + + for (int i = 0; i < resolution * 2; i += 2) { + float *l1 = &data[i]; + float *l2 = &data[i + 2]; + float distance = dist_squared_to_line_segment_v2(cursor, l1, l2); + if (distance < cursor_link_touch_distance) { + link_to_pick = link; + RNA_int_set(op->ptr, "last_picked_link_index", link->multi_input_socket_index); + } + } + } + } + + /* If no linked was picked in this call, try using the one picked in the previous call. + * Not essential for the basic behavior, but can make interaction feel a bit better if + * the mouse moves to the right and loses the "selection." */ + if (!link_to_pick) { + int last_picked_link_index = RNA_int_get(op->ptr, "last_picked_link_index"); + if (last_picked_link_index > -1) { + LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { + if (link->multi_input_socket_index == last_picked_link_index) { + link_to_pick = link; + } + } + } + } + + if (link_to_pick) { + /* Highlight is set here and cleared in the next iteration or if the operation finishes. */ + link_to_pick->flag |= NODE_LINK_TEMP_HIGHLIGHT; + ED_area_tag_redraw(CTX_wm_area(C)); + + if (distance_from_socket > trigger_drag_distance) { + pick_link(C, op, nldrag, snode, node, link_to_pick); + } + } +} + static int sort_nodes_locx(const void *a, const void *b) { const bNodeListItem *nli1 = a; @@ -600,6 +732,13 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link) tlink = NULL; to_count--; } + else if (tlink->fromsock == from) { + /* Also remove link if it comes from the same output. */ + nodeRemLink(ntree, tlink); + tlink = NULL; + to_count--; + from_count--; + } } } } @@ -663,7 +802,7 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links) snode_dag_update(C, snode); } - BLI_remlink(&snode->linkdrag, nldrag); + BLI_remlink(&snode->runtime->linkdrag, nldrag); /* links->data pointers are either held by the tree or freed already */ BLI_freelistN(&nldrag->links); MEM_freeN(nldrag); @@ -736,7 +875,7 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2]) } } -/* loop that adds a nodelink, called by function below */ +/* Loop that adds a node-link, called by function below. */ /* in_out = starting socket */ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) { @@ -748,10 +887,15 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) switch (event->type) { case MOUSEMOVE: - node_link_find_socket(C, op, cursor); + if (nldrag->from_multi_input_socket && !RNA_boolean_get(op->ptr, "has_link_picked")) { + pick_input_link_by_link_intersect(C, op, nldrag, cursor); + } + else { + node_link_find_socket(C, op, cursor); - node_link_update_header(C, nldrag); - ED_region_tag_redraw(region); + node_link_update_header(C, nldrag); + ED_region_tag_redraw(region); + } break; case LEFTMOUSE: @@ -762,6 +906,8 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) ED_workspace_status_text(C, NULL); ED_region_tag_redraw(region); + SpaceNode *snode = CTX_wm_space_node(C); + clear_picking_highlight(&snode->edittree->links); return OPERATOR_FINISHED; } break; @@ -817,16 +963,7 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor /* dragged links are fixed on output side */ nldrag->in_out = SOCK_OUT; /* create a new link */ - LinkData *linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data"); - bNodeLink *oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); - linkdata->data = oplink; - oplink->fromnode = node; - oplink->fromsock = sock; - oplink->flag |= NODE_LINK_VALID; - oplink->flag &= ~NODE_LINK_TEST; - if (node_connected_to_output(bmain, snode->edittree, node)) { - oplink->flag |= NODE_LINK_TEST; - } + LinkData *linkdata = create_drag_link(bmain, snode, node, sock); BLI_addtail(&nldrag->links, linkdata); } @@ -836,31 +973,38 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata"); const int num_links = nodeCountSocketLinks(snode->edittree, sock); - int link_limit = nodeSocketLinkLimit(sock); - if (num_links > 0 && (num_links >= link_limit || detach)) { + if (num_links > 0) { /* dragged links are fixed on output side */ nldrag->in_out = SOCK_OUT; /* detach current links and store them in the operator data */ + bNodeLink *link_to_pick; LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &snode->edittree->links) { if (link->tosock == sock) { - LinkData *linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data"); - bNodeLink *oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); - linkdata->data = oplink; - *oplink = *link; - oplink->next = oplink->prev = NULL; - oplink->flag |= NODE_LINK_VALID; - oplink->flag &= ~NODE_LINK_TEST; - if (node_connected_to_output(bmain, snode->edittree, link->tonode)) { - oplink->flag |= NODE_LINK_TEST; + if (sock->flag & SOCK_MULTI_INPUT) { + nldrag->from_multi_input_socket = true; } + link_to_pick = link; + } + } - BLI_addtail(&nldrag->links, linkdata); - nodeRemLink(snode->edittree, link); + if (link_to_pick != NULL && !nldrag->from_multi_input_socket) { + LinkData *linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data"); + bNodeLink *oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); + linkdata->data = oplink; + *oplink = *link_to_pick; + oplink->next = oplink->prev = NULL; + oplink->flag |= NODE_LINK_VALID; + oplink->flag &= ~NODE_LINK_TEST; + if (node_connected_to_output(bmain, snode->edittree, link_to_pick->tonode)) { + oplink->flag |= NODE_LINK_TEST; + } - /* send changed event to original link->tonode */ - if (node) { - snode_update(snode, node); - } + BLI_addtail(&nldrag->links, linkdata); + nodeRemLink(snode->edittree, link_to_pick); + + /* send changed event to original link->tonode */ + if (node) { + snode_update(snode, node); } } } @@ -868,16 +1012,7 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor /* dragged links are fixed on input side */ nldrag->in_out = SOCK_IN; /* create a new link */ - LinkData *linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data"); - bNodeLink *oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); - linkdata->data = oplink; - oplink->tonode = node; - oplink->tosock = sock; - oplink->flag |= NODE_LINK_VALID; - oplink->flag &= ~NODE_LINK_TEST; - if (node_connected_to_output(bmain, snode->edittree, node)) { - oplink->flag |= NODE_LINK_TEST; - } + LinkData *linkdata = create_drag_link(bmain, snode, node, sock); BLI_addtail(&nldrag->links, linkdata); } @@ -896,6 +1031,9 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) float cursor[2]; UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]); + RNA_float_set_array(op->ptr, "drag_start", cursor); + RNA_int_set(op->ptr, "last_picked_link_index", -1); + RNA_boolean_set(op->ptr, "has_link_picked", false); ED_preview_kill_jobs(CTX_wm_manager(C), bmain); @@ -903,7 +1041,7 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (nldrag) { op->customdata = nldrag; - BLI_addtail(&snode->linkdrag, nldrag); + BLI_addtail(&snode->runtime->linkdrag, nldrag); /* add modal handler */ WM_event_add_modal_handler(C, op); @@ -918,10 +1056,11 @@ static void node_link_cancel(bContext *C, wmOperator *op) SpaceNode *snode = CTX_wm_space_node(C); bNodeLinkDrag *nldrag = op->customdata; - BLI_remlink(&snode->linkdrag, nldrag); + BLI_remlink(&snode->runtime->linkdrag, nldrag); BLI_freelistN(&nldrag->links); MEM_freeN(nldrag); + clear_picking_highlight(&snode->edittree->links); } void NODE_OT_link(wmOperatorType *ot) @@ -941,7 +1080,38 @@ void NODE_OT_link(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + PropertyRNA *prop; + RNA_def_boolean(ot->srna, "detach", false, "Detach", "Detach and redirect existing links"); + prop = RNA_def_boolean( + ot->srna, + "has_link_picked", + false, + "Has Link Picked", + "The operation has placed a link. Only used for multi-input sockets, where the " + "link is picked later"); + RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_float_array(ot->srna, + "drag_start", + 2, + 0, + -UI_PRECISION_FLOAT_MAX, + UI_PRECISION_FLOAT_MAX, + "Drag Start", + "The position of the mouse cursor at the start of the operation", + -UI_PRECISION_FLOAT_MAX, + UI_PRECISION_FLOAT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_int(ot->srna, + "last_picked_link_index", + -1, + -1, + 4095, + "Last Picked Link Index", + "The index of the last picked link on a multi-input socket", + -1, + 4095); + RNA_def_property_flag(prop, PROP_HIDDEN); } /* ********************** Make Link operator ***************** */ @@ -1513,7 +1683,7 @@ void ED_node_link_intersect_test(ScrArea *area, int test) /* loop over link coords to find shortest dist to * upper left node edge of a intersected line segment */ for (int i = 0; i < NODE_LINK_RESOL; i++) { - /* check if the node rect intersetcts the line from this point to next one */ + /* Check if the node rectangle intersects the line from this point to next one. */ if (BLI_rctf_isect_segment(&select->totr, coord_array[i], coord_array[i + 1])) { /* store the shortest distance to the upper left edge * of all intersections found so far */ @@ -1798,7 +1968,7 @@ static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd, static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); - NodeInsertOfsData *iofsd = snode->iofsd; + NodeInsertOfsData *iofsd = snode->runtime->iofsd; bool redraw = false; if (!snode || event->type != TIMER || iofsd == NULL || iofsd->anim_timer != event->customdata) { @@ -1837,7 +2007,7 @@ static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const w node->anim_init_locx = node->anim_ofsx = 0.0f; } - snode->iofsd = NULL; + snode->runtime->iofsd = NULL; MEM_freeN(iofsd); return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); @@ -1851,7 +2021,7 @@ static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const w static int node_insert_offset_invoke(bContext *C, wmOperator *op, const wmEvent *event) { const SpaceNode *snode = CTX_wm_space_node(C); - NodeInsertOfsData *iofsd = snode->iofsd; + NodeInsertOfsData *iofsd = snode->runtime->iofsd; if (!iofsd || !iofsd->insert) { return OPERATOR_CANCELLED; @@ -1927,7 +2097,7 @@ void ED_node_link_insert(Main *bmain, ScrArea *area) iofsd->prev = link->fromnode; iofsd->next = node; - snode->iofsd = iofsd; + snode->runtime->iofsd = iofsd; } ntreeUpdateTree(bmain, snode->edittree); /* needed for pointers */ diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index 5060ac0db8a..1e6ca66dd31 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -26,7 +26,6 @@ #include "DNA_node_types.h" #include "DNA_windowmanager_types.h" -#include "BLI_alloca.h" #include "BLI_lasso_2d.h" #include "BLI_listbase.h" #include "BLI_math.h" @@ -62,14 +61,15 @@ #include "node_intern.h" /* own include */ -/* Function to detect if there is a visible view3d that uses workbench in texture mode. +/** + * Function to detect if there is a visible view3d that uses workbench in texture mode. * This function is for fixing T76970 for Blender 2.83. The actual fix should add a mechanism in * the depsgraph that can be used by the draw engines to check if they need to be redrawn. * * We don't want to add these risky changes this close before releasing 2.83 without good testing * hence this workaround. There are still cases were too many updates happen. For example when you * have both a Cycles and workbench with textures viewport. - * */ + */ static bool has_workbench_in_texture_color(const wmWindowManager *wm, const Scene *scene, const Object *ob) diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 553971cd0a5..f0e3f5442cc 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -35,7 +35,6 @@ #include "BKE_context.h" #include "BKE_lib_id.h" #include "BKE_main.h" -#include "BKE_scene.h" #include "RNA_access.h" diff --git a/source/blender/editors/space_node/node_toolbar.c b/source/blender/editors/space_node/node_toolbar.c index 7afd3fef4db..2e7d6ab6cd5 100644 --- a/source/blender/editors/space_node/node_toolbar.c +++ b/source/blender/editors/space_node/node_toolbar.c @@ -29,9 +29,6 @@ #include "BKE_screen.h" #include "WM_api.h" -#include "WM_types.h" - -#include "ED_screen.h" #include "node_intern.h" /* own include */ diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index d938cb38270..8f1dc3c8c3e 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -52,7 +52,6 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "NOD_composite.h" #include "node_intern.h" /* own include */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index ad7632377a3..73c6a28a5dc 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -35,7 +35,6 @@ #include "BKE_context.h" #include "BKE_lib_id.h" #include "BKE_node.h" -#include "BKE_scene.h" #include "BKE_screen.h" #include "ED_node.h" @@ -321,18 +320,25 @@ static void node_free(SpaceLink *sl) LISTBASE_FOREACH_MUTABLE (bNodeTreePath *, path, &snode->treepath) { MEM_freeN(path); } + + MEM_SAFE_FREE(snode->runtime); } /* spacetype; init callback */ -static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area)) +static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *area) { + SpaceNode *snode = (SpaceNode *)area->spacedata.first; + + if (snode->runtime == NULL) { + snode->runtime = MEM_callocN(sizeof(SpaceNode_Runtime), __func__); + } } -static void node_area_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void node_area_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + /* note, ED_area_tag_refresh will re-execute compositor */ SpaceNode *snode = area->spacedata.first; /* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */ @@ -362,7 +368,7 @@ static void node_area_listener(wmWindow *UNUSED(win), case ND_TRANSFORM_DONE: if (ED_node_is_compositor(snode)) { if (snode->flag & SNODE_AUTO_RENDER) { - snode->recalc = 1; + snode->runtime->recalc = true; ED_area_tag_refresh(area); } } @@ -521,8 +527,8 @@ static void node_area_refresh(const struct bContext *C, ScrArea *area) Scene *scene = (Scene *)snode->id; if (scene->use_nodes) { /* recalc is set on 3d view changes for auto compo */ - if (snode->recalc) { - snode->recalc = 0; + if (snode->runtime->recalc) { + snode->runtime->recalc = false; node_render_changed_exec((struct bContext *)C, NULL); } else { @@ -546,8 +552,10 @@ static SpaceLink *node_duplicate(SpaceLink *sl) BLI_duplicatelist(&snoden->treepath, &snode->treepath); - /* clear or remove stuff from old */ - BLI_listbase_clear(&snoden->linkdrag); + if (snode->runtime != NULL) { + snoden->runtime = MEM_dupallocN(snode->runtime); + BLI_listbase_clear(&snoden->runtime->linkdrag); + } /* Note: no need to set node tree user counts, * the editor only keeps at least 1 (id_us_ensure_real), @@ -589,6 +597,16 @@ static void node_toolbar_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } +void ED_node_cursor_location_get(const SpaceNode *snode, float value[2]) +{ + copy_v2_v2(value, snode->runtime->cursor); +} + +void ED_node_cursor_location_set(SpaceNode *snode, const float value[2]) +{ + copy_v2_v2(snode->runtime->cursor, value); +} + static void node_cursor(wmWindow *win, ScrArea *area, ARegion *region) { SpaceNode *snode = area->spacedata.first; @@ -597,15 +615,15 @@ static void node_cursor(wmWindow *win, ScrArea *area, ARegion *region) UI_view2d_region_to_view(®ion->v2d, win->eventstate->x - region->winrct.xmin, win->eventstate->y - region->winrct.ymin, - &snode->cursor[0], - &snode->cursor[1]); + &snode->runtime->cursor[0], + &snode->runtime->cursor[1]); - /* here snode->cursor is used to detect the node edge for sizing */ - node_set_cursor(win, snode, snode->cursor); + /* here snode->runtime->cursor is used to detect the node edge for sizing */ + node_set_cursor(win, snode, snode->runtime->cursor); - /* XXX snode->cursor is in placing new nodes space */ - snode->cursor[0] /= UI_DPI_FAC; - snode->cursor[1] /= UI_DPI_FAC; + /* XXX snode->runtime->cursor is in placing new nodes space */ + snode->runtime->cursor[0] /= UI_DPI_FAC; + snode->runtime->cursor[1] /= UI_DPI_FAC; } /* Initialize main region, setting handlers. */ @@ -645,7 +663,7 @@ static bool node_ima_drop_poll(bContext *UNUSED(C), /* rule might not work? */ return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)); } - return WM_drag_get_local_ID(drag, ID_IM) != NULL; + return WM_drag_is_ID_type(drag, ID_IM); } static bool node_mask_drop_poll(bContext *UNUSED(C), @@ -653,19 +671,19 @@ static bool node_mask_drop_poll(bContext *UNUSED(C), const wmEvent *UNUSED(event), const char **UNUSED(r_tooltip)) { - return WM_drag_get_local_ID(drag, ID_MSK) != NULL; + return WM_drag_is_ID_type(drag, ID_MSK); } static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_get_local_ID(drag, 0); + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); RNA_string_set(drop->ptr, "name", id->name + 2); } static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_get_local_ID(drag, 0); + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); if (id) { RNA_string_set(drop->ptr, "name", id->name + 2); @@ -703,12 +721,10 @@ static void node_header_region_draw(const bContext *C, ARegion *region) } /* used for header + main region */ -static void node_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void node_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; wmGizmoMap *gzmap = region->gizmo_map; /* context changes */ diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index e0262371559..d54265aa292 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -27,6 +27,7 @@ set(INC ../../makesrna ../../sequencer ../../windowmanager + ../../../../intern/clog ../../../../intern/glew-mx ../../../../intern/guardedalloc ) diff --git a/source/blender/editors/space_outliner/outliner_context.c b/source/blender/editors/space_outliner/outliner_context.c index a314a640e42..e2b3b79e027 100644 --- a/source/blender/editors/space_outliner/outliner_context.c +++ b/source/blender/editors/space_outliner/outliner_context.c @@ -27,8 +27,6 @@ #include "DNA_space_types.h" -#include "RNA_access.h" - #include "outliner_intern.h" static void outliner_context_selected_ids_recursive(const ListBase *subtree, diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index ab515c0c3a8..70aeef76234 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -140,6 +140,11 @@ static TreeElement *outliner_drop_insert_find(bContext *C, TreeElement *te_hovered; float view_mval[2]; + /* Empty tree, e.g. while filtered. */ + if (BLI_listbase_is_empty(&space_outliner->tree)) { + return NULL; + } + UI_view2d_region_to_view( ®ion->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); te_hovered = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 8104c1e0d58..76c710b3db1 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -314,7 +314,7 @@ static void outliner_object_set_flag_recursive_fn(bContext *C, /** * Object properties. - * */ + */ static void outliner__object_set_flag_recursive_fn(bContext *C, void *poin, void *poin2) { Object *ob = poin; @@ -324,7 +324,7 @@ static void outliner__object_set_flag_recursive_fn(bContext *C, void *poin, void /** * Base properties. - * */ + */ static void outliner__base_set_flag_recursive_fn(bContext *C, void *poin, void *poin2) { Base *base = poin; @@ -697,13 +697,13 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); } DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); - WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); break; } default: - WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); break; } + WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); + /* Check the library target exists */ if (te->idcode == ID_LI) { Library *lib = (Library *)tselem->id; @@ -2287,12 +2287,6 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case TSE_R_LAYER: data.icon = ICON_RENDER_RESULT; break; - case TSE_LINKED_LAMP: - data.icon = ICON_LIGHT_DATA; - break; - case TSE_LINKED_MAT: - data.icon = ICON_MATERIAL_DATA; - break; case TSE_POSEGRP_BASE: case TSE_POSEGRP: data.icon = ICON_GROUP_BONE; @@ -2695,13 +2689,16 @@ static void outliner_draw_iconrow_number(const uiFontStyle *fstyle, float offset_x = (float)offsx + UI_UNIT_X * 0.35f; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, - offset_x + ufac, - (float)ys - UI_UNIT_Y * 0.2f + ufac, - offset_x + UI_UNIT_X - ufac, - (float)ys - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac, - (float)UI_UNIT_Y / 2.0f - ufac, - color); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = offset_x + ufac, + .xmax = offset_x + UI_UNIT_X - ufac, + .ymin = (float)ys - UI_UNIT_Y * 0.2f + ufac, + .ymax = (float)ys - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac, + }, + true, + (float)UI_UNIT_Y / 2.0f - ufac, + color); /* Now the numbers. */ uchar text_col[4]; @@ -2751,8 +2748,26 @@ static void outliner_draw_active_indicator(const float minx, const float radius = UI_UNIT_Y / 4.0f; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, minx, miny + ufac, maxx, maxy - ufac, radius, icon_color); - UI_draw_roundbox_aa(false, minx, miny + ufac, maxx, maxy - ufac, radius, icon_border); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = minx, + .xmax = maxx, + .ymin = miny + ufac, + .ymax = maxy - ufac, + }, + true, + radius, + icon_color); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = minx, + .xmax = maxx, + .ymin = miny + ufac, + .ymax = maxy - ufac, + }, + false, + radius, + icon_border); GPU_blend(GPU_BLEND_ALPHA); /* Roundbox disables. */ } @@ -3038,7 +3053,7 @@ static void outliner_draw_tree_element(bContext *C, } else { active = tree_element_type_active(C, tvc, space_outliner, te, tselem, OL_SETSEL_NONE, false); - /* active collection*/ + /* Active collection. */ } /* active circle */ @@ -3058,7 +3073,7 @@ static void outliner_draw_tree_element(bContext *C, } else if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) { - /* open/close icon, only when sublevels, except for scene */ + /* Open/close icon, only when sub-levels, except for scene. */ int icon_x = startx; /* Icons a bit higher. */ @@ -3496,7 +3511,7 @@ static void outliner_draw_tree(bContext *C, GPU_scissor(0, 0, mask_x, region->winy); } - /* Draw hierarhcy lines for collections and object children. */ + /* Draw hierarchy lines for collections and object children. */ starty = (int)region->v2d.tot.ymax - OL_Y_OFFSET; startx = mode_column_offset + UI_UNIT_X / 2 - (U.pixelsize + 1) / 2; outliner_draw_hierarchy_lines(space_outliner, &space_outliner->tree, startx, &starty); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index acda5ae82f0..7e5b0c90714 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -21,22 +21,9 @@ * \ingroup spoutliner */ -#include "MEM_guardedalloc.h" - -#include "DNA_collection_types.h" - -#include "BLT_translation.h" - -#include "RNA_access.h" - -#include "UI_interface.h" -#include "UI_view2d.h" - #include "WM_api.h" -#include "WM_types.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "outliner_intern.h" diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 600047c4b11..4a58736966c 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -927,25 +927,6 @@ static eOLDrawState tree_element_active_sequence_dup(Scene *scene, return OL_DRAWSEL_NONE; } -static eOLDrawState tree_element_active_keymap_item(bContext *UNUSED(C), - Scene *UNUSED(scene), - ViewLayer *UNUSED(sl), - TreeElement *te, - TreeStoreElem *UNUSED(tselem), - const eOLSetState set) -{ - wmKeyMapItem *kmi = te->directdata; - - if (set == OL_SETSEL_NONE) { - if (kmi->flag & KMI_INACTIVE) { - return OL_DRAWSEL_NONE; - } - return OL_DRAWSEL_NORMAL; - } - kmi->flag ^= KMI_INACTIVE; - return OL_DRAWSEL_NONE; -} - static eOLDrawState tree_element_active_master_collection(bContext *C, TreeElement *UNUSED(te), const eOLSetState set) @@ -1071,8 +1052,6 @@ eOLDrawState tree_element_type_active(bContext *C, return tree_element_active_sequence(C, tvc->scene, te, tselem, set); case TSE_SEQUENCE_DUP: return tree_element_active_sequence_dup(tvc->scene, te, tselem, set); - case TSE_KEYMAP_ITEM: - return tree_element_active_keymap_item(C, tvc->scene, tvc->view_layer, te, tselem, set); case TSE_GP_LAYER: return tree_element_active_gplayer(C, tvc->scene, te, tselem, set); break; @@ -1543,7 +1522,7 @@ static bool outliner_is_co_within_active_mode_column(bContext *C, * Action to run when clicking in the outliner, * * May expend/collapse branches or activate items. - * */ + */ static int outliner_item_do_activate_from_cursor(bContext *C, const int mval[2], const bool extend, diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c index 0b2d1ce34ec..8bd5e3a130a 100644 --- a/source/blender/editors/space_outliner/outliner_sync.c +++ b/source/blender/editors/space_outliner/outliner_sync.c @@ -38,7 +38,6 @@ #include "BKE_context.h" #include "BKE_layer.h" #include "BKE_main.h" -#include "BKE_object.h" #include "DEG_depsgraph.h" @@ -378,7 +377,7 @@ void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *space_out selected_items_free(&selected_items); - /* Tag for updates and clear dirty flag toprevent a sync to the outliner on draw */ + /* Tag for updates and clear dirty flag to prevent a sync to the outliner on draw. */ if (sync_types.object) { space_outliner->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_OBJECT; DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); @@ -545,7 +544,7 @@ static void get_sync_select_active_data(const bContext *C, SyncSelectActiveData active_data->sequence = SEQ_select_active_get(scene); } -/* If outliner is dirty sync selection from view layer and sequwncer */ +/* If outliner is dirty sync selection from view layer and sequencer. */ void outliner_sync_selection(const bContext *C, SpaceOutliner *space_outliner) { /* Set which types of data to sync from sync dirty flag and outliner display mode */ diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 2a2803c58dd..8b522d41af8 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -23,6 +23,8 @@ #include "MEM_guardedalloc.h" +#include "CLG_log.h" + #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_collection_types.h" @@ -92,6 +94,8 @@ #include "outliner_intern.h" +static CLG_LogRef LOG = {"ed.outliner.tools"}; + /* -------------------------------------------------------------------- */ /** \name ID/Library/Data Set/Un-link Utilities * \{ */ @@ -790,7 +794,7 @@ static void id_override_library_create_fn(bContext *C, id_root->tag |= LIB_TAG_DOIT; - /* For now, remapp all local usages of linked ID to local override one here. */ + /* For now, remap all local usages of linked ID to local override one here. */ ID *id_iter; FOREACH_MAIN_ID_BEGIN (bmain, id_iter) { if (ID_IS_LINKED(id_iter)) { @@ -824,6 +828,9 @@ static void id_override_library_create_fn(bContext *C, BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); } } + else { + CLOG_WARN(&LOG, "Could not create library override for data block '%s'", id_root->name); + } } static void id_override_library_reset_fn(bContext *C, @@ -852,6 +859,9 @@ static void id_override_library_reset_fn(bContext *C, WM_event_add_notifier(C, NC_WM | ND_DATACHANGED, NULL); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); } + else { + CLOG_WARN(&LOG, "Could not reset library override of data block '%s'", id_root->name); + } } static void id_override_library_resync_fn(bContext *C, @@ -883,6 +893,9 @@ static void id_override_library_resync_fn(bContext *C, BKE_lib_override_library_resync(bmain, scene, CTX_data_view_layer(C), id_root); } + else { + CLOG_WARN(&LOG, "Could not resync library override of data block '%s'", id_root->name); + } } static void id_override_library_delete_fn(bContext *C, @@ -914,6 +927,9 @@ static void id_override_library_delete_fn(bContext *C, BKE_lib_override_library_delete(bmain, id_root); } + else { + CLOG_WARN(&LOG, "Could not delete library override of data block '%s'", id_root->name); + } } static void id_fake_user_set_fn(bContext *UNUSED(C), @@ -1789,21 +1805,44 @@ static bool outliner_id_operation_item_poll(bContext *C, const int enum_value) { SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); + TreeElement *te = get_target_element(space_outliner); + TreeStoreElem *tselem = TREESTORE(te); + if (!TSE_IS_REAL_ID(tselem)) { + return false; + } + + Object *ob = NULL; + if (GS(tselem->id->name) == ID_OB) { + ob = (Object *)tselem->id; + } switch (enum_value) { case OUTLINER_IDOP_MARK_ASSET: case OUTLINER_IDOP_CLEAR_ASSET: return U.experimental.use_asset_browser; case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE: + if (ID_IS_OVERRIDABLE_LIBRARY(tselem->id)) { + return true; + } + return false; case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY: - return true; + if (ID_IS_OVERRIDABLE_LIBRARY(tselem->id) || (ID_IS_LINKED(tselem->id))) { + return true; + } + return false; + case OUTLINER_IDOP_OVERRIDE_LIBRARY_PROXY_CONVERT: + if (ob != NULL && ob->proxy != NULL) { + return true; + } + return false; case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY: - return true; case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY: - return true; case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY: - return true; + if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id)) { + return true; + } + return false; case OUTLINER_IDOP_SINGLE: if (!space_outliner || ELEM(space_outliner->outlinevis, SO_SCENES, SO_VIEW_LAYER)) { return true; diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index acfeccca175..f94f19246fa 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -167,8 +167,6 @@ static void outliner_storage_cleanup(SpaceOutliner *space_outliner) static void check_persistent( SpaceOutliner *space_outliner, TreeElement *te, ID *id, short type, short nr) { - TreeStoreElem *tselem; - if (space_outliner->treestore == NULL) { /* if treestore was not created in readfile.c, create it here */ space_outliner->treestore = BLI_mempool_create( @@ -181,7 +179,8 @@ static void check_persistent( /* find any unused tree element in treestore and mark it as used * (note that there may be multiple unused elements in case of linked objects) */ - tselem = BKE_outliner_treehash_lookup_unused(space_outliner->runtime->treehash, type, nr, id); + TreeStoreElem *tselem = BKE_outliner_treehash_lookup_unused( + space_outliner->runtime->treehash, type, nr, id); if (tselem) { te->store_elem = tselem; tselem->used = 1; @@ -204,8 +203,7 @@ static void check_persistent( void outliner_free_tree(ListBase *tree) { - for (TreeElement *element = tree->first, *element_next; element; element = element_next) { - element_next = element->next; + LISTBASE_FOREACH_MUTABLE (TreeElement *, element, tree) { outliner_free_tree_element(element, tree); } } @@ -271,8 +269,8 @@ static void outliner_add_bone(SpaceOutliner *space_outliner, te->name = curBone->name; te->directdata = curBone; - for (curBone = curBone->childbase.first; curBone; curBone = curBone->next) { - outliner_add_bone(space_outliner, &te->subtree, id, curBone, te, a); + LISTBASE_FOREACH (Bone *, child_bone, &curBone->childbase) { + outliner_add_bone(space_outliner, &te->subtree, id, child_bone, te, a); } } @@ -381,35 +379,30 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, if (ob->pose) { bArmature *arm = ob->data; - bPoseChannel *pchan; TreeElement *tenla = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_POSE_BASE, 0); - tenla->name = IFACE_("Pose"); /* channels undefined in editmode, but we want the 'tenla' pose icon itself */ if ((arm->edbo == NULL) && (ob->mode & OB_MODE_POSE)) { - TreeElement *ten; - int a = 0, const_index = 1000; /* ensure unique id for bone constraints */ - - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next, a++) { - ten = outliner_add_element( + int const_index = 1000; /* ensure unique id for bone constraints */ + int a; + LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob->pose->chanbase, a) { + TreeElement *ten = outliner_add_element( space_outliner, &tenla->subtree, ob, tenla, TSE_POSE_CHANNEL, a); ten->name = pchan->name; ten->directdata = pchan; pchan->temp = (void *)ten; - if (pchan->constraints.first) { + if (!BLI_listbase_is_empty(&pchan->constraints)) { /* Object *target; */ - bConstraint *con; - TreeElement *ten1; TreeElement *tenla1 = outliner_add_element( space_outliner, &ten->subtree, ob, ten, TSE_CONSTRAINT_BASE, 0); + tenla1->name = IFACE_("Constraints"); /* char *str; */ - tenla1->name = IFACE_("Constraints"); - for (con = pchan->constraints.first; con; con = con->next, const_index++) { - ten1 = outliner_add_element( + LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) { + TreeElement *ten1 = outliner_add_element( space_outliner, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index); #if 0 /* disabled as it needs to be reworked for recoded constraints system */ target = get_constraint_target(con, &str); @@ -427,15 +420,16 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, ten1->directdata = con; /* possible add all other types links? */ } + const_index++; } } /* make hierarchy */ - ten = tenla->subtree.first; + TreeElement *ten = tenla->subtree.first; while (ten) { TreeElement *nten = ten->next, *par; tselem = TREESTORE(ten); if (tselem->type == TSE_POSE_CHANNEL) { - pchan = (bPoseChannel *)ten->directdata; + bPoseChannel *pchan = (bPoseChannel *)ten->directdata; if (pchan->parent) { BLI_remlink(&tenla->subtree, ten); par = (TreeElement *)pchan->parent->temp; @@ -448,17 +442,15 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, } /* Pose Groups */ - if (ob->pose->agroups.first) { - bActionGroup *agrp; + if (!BLI_listbase_is_empty(&ob->pose->agroups)) { TreeElement *ten_bonegrp = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_POSEGRP_BASE, 0); - int a = 0; - ten_bonegrp->name = IFACE_("Bone Groups"); - for (agrp = ob->pose->agroups.first; agrp; agrp = agrp->next, a++) { - TreeElement *ten; - ten = outliner_add_element( - space_outliner, &ten_bonegrp->subtree, ob, ten_bonegrp, TSE_POSEGRP, a); + + int index; + LISTBASE_FOREACH_INDEX (bActionGroup *, agrp, &ob->pose->agroups, index) { + TreeElement *ten = outliner_add_element( + space_outliner, &ten_bonegrp->subtree, ob, ten_bonegrp, TSE_POSEGRP, index); ten->name = agrp->name; ten->directdata = agrp; } @@ -469,18 +461,15 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, outliner_add_element(space_outliner, &te->subtree, ob->mat[a], te, 0, a); } - if (ob->constraints.first) { - /* Object *target; */ - bConstraint *con; - TreeElement *ten; + if (!BLI_listbase_is_empty(&ob->constraints)) { TreeElement *tenla = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_CONSTRAINT_BASE, 0); - /* char *str; */ - int a; - tenla->name = IFACE_("Constraints"); - for (con = ob->constraints.first, a = 0; con; con = con->next, a++) { - ten = outliner_add_element(space_outliner, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, a); + + int index; + LISTBASE_FOREACH_INDEX (bConstraint *, con, &ob->constraints, index) { + TreeElement *ten = outliner_add_element( + space_outliner, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, index); #if 0 /* disabled due to constraints system targets recode... code here needs review */ target = get_constraint_target(con, &str); if (str && str[0]) { @@ -499,14 +488,13 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, } } - if (ob->modifiers.first) { - ModifierData *md; + if (!BLI_listbase_is_empty(&ob->modifiers)) { TreeElement *ten_mod = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0); - int index; - ten_mod->name = IFACE_("Modifiers"); - for (index = 0, md = ob->modifiers.first; md; index++, md = md->next) { + + int index; + LISTBASE_FOREACH_INDEX (ModifierData *, md, &ob->modifiers, index) { TreeElement *ten = outliner_add_element( space_outliner, &ten_mod->subtree, ob, ten_mod, TSE_MODIFIER, index); ten->name = md->name; @@ -559,8 +547,8 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, if (!BLI_listbase_is_empty(&ob->greasepencil_modifiers)) { TreeElement *ten_mod = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0); - ten_mod->name = IFACE_("Modifiers"); + int index; LISTBASE_FOREACH_INDEX (GpencilModifierData *, md, &ob->greasepencil_modifiers, index) { TreeElement *ten = outliner_add_element( @@ -599,8 +587,8 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, if (!BLI_listbase_is_empty(&ob->shader_fx)) { TreeElement *ten_fx = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_GPENCIL_EFFECT_BASE, 0); - ten_fx->name = IFACE_("Effects"); + int index; LISTBASE_FOREACH_INDEX (ShaderFxData *, fx, &ob->shader_fx, index) { TreeElement *ten = outliner_add_element( @@ -620,16 +608,15 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, } /* vertex groups */ - if (ob->defbase.first) { - bDeformGroup *defgroup; - TreeElement *ten; + if (!BLI_listbase_is_empty(&ob->defbase)) { TreeElement *tenla = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0); - int a; - tenla->name = IFACE_("Vertex Groups"); - for (defgroup = ob->defbase.first, a = 0; defgroup; defgroup = defgroup->next, a++) { - ten = outliner_add_element(space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, a); + + int index; + LISTBASE_FOREACH_INDEX (bDeformGroup *, defgroup, &ob->defbase, index) { + TreeElement *ten = outliner_add_element( + space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, index); ten->name = defgroup->name; ten->directdata = defgroup; } @@ -694,14 +681,13 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_ME: { Mesh *me = (Mesh *)id; - int a; if (outliner_animdata_test(me->adt)) { outliner_add_element(space_outliner, &te->subtree, me, te, TSE_ANIM_DATA, 0); } outliner_add_element(space_outliner, &te->subtree, me->key, te, 0, 0); - for (a = 0; a < me->totcol; a++) { + for (int a = 0; a < me->totcol; a++) { outliner_add_element(space_outliner, &te->subtree, me->mat[a], te, 0, a); } /* could do tfaces with image links, but the images are not grouped nicely. @@ -710,33 +696,30 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_CU: { Curve *cu = (Curve *)id; - int a; if (outliner_animdata_test(cu->adt)) { outliner_add_element(space_outliner, &te->subtree, cu, te, TSE_ANIM_DATA, 0); } - for (a = 0; a < cu->totcol; a++) { + for (int a = 0; a < cu->totcol; a++) { outliner_add_element(space_outliner, &te->subtree, cu->mat[a], te, 0, a); } break; } case ID_MB: { MetaBall *mb = (MetaBall *)id; - int a; if (outliner_animdata_test(mb->adt)) { outliner_add_element(space_outliner, &te->subtree, mb, te, TSE_ANIM_DATA, 0); } - for (a = 0; a < mb->totcol; a++) { + for (int a = 0; a < mb->totcol; a++) { outliner_add_element(space_outliner, &te->subtree, mb->mat[a], te, 0, a); } break; } case ID_MA: { Material *ma = (Material *)id; - if (outliner_animdata_test(ma->adt)) { outliner_add_element(space_outliner, &te->subtree, ma, te, TSE_ANIM_DATA, 0); } @@ -744,7 +727,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_TE: { Tex *tex = (Tex *)id; - if (outliner_animdata_test(tex->adt)) { outliner_add_element(space_outliner, &te->subtree, tex, te, TSE_ANIM_DATA, 0); } @@ -753,7 +735,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_CA: { Camera *ca = (Camera *)id; - if (outliner_animdata_test(ca->adt)) { outliner_add_element(space_outliner, &te->subtree, ca, te, TSE_ANIM_DATA, 0); } @@ -761,7 +742,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_CF: { CacheFile *cache_file = (CacheFile *)id; - if (outliner_animdata_test(cache_file->adt)) { outliner_add_element(space_outliner, &te->subtree, cache_file, te, TSE_ANIM_DATA, 0); } @@ -770,7 +750,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_LA: { Light *la = (Light *)id; - if (outliner_animdata_test(la->adt)) { outliner_add_element(space_outliner, &te->subtree, la, te, TSE_ANIM_DATA, 0); } @@ -778,7 +757,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_SPK: { Speaker *spk = (Speaker *)id; - if (outliner_animdata_test(spk->adt)) { outliner_add_element(space_outliner, &te->subtree, spk, te, TSE_ANIM_DATA, 0); } @@ -786,7 +764,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_LP: { LightProbe *prb = (LightProbe *)id; - if (outliner_animdata_test(prb->adt)) { outliner_add_element(space_outliner, &te->subtree, prb, te, TSE_ANIM_DATA, 0); } @@ -794,7 +771,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_WO: { World *wrld = (World *)id; - if (outliner_animdata_test(wrld->adt)) { outliner_add_element(space_outliner, &te->subtree, wrld, te, TSE_ANIM_DATA, 0); } @@ -802,7 +778,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_KE: { Key *key = (Key *)id; - if (outliner_animdata_test(key->adt)) { outliner_add_element(space_outliner, &te->subtree, key, te, TSE_ANIM_DATA, 0); } @@ -815,27 +790,25 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_AR: { bArmature *arm = (bArmature *)id; - int a = 0; if (outliner_animdata_test(arm->adt)) { outliner_add_element(space_outliner, &te->subtree, arm, te, TSE_ANIM_DATA, 0); } if (arm->edbo) { - EditBone *ebone; - TreeElement *ten; - - for (ebone = arm->edbo->first; ebone; ebone = ebone->next, a++) { - ten = outliner_add_element(space_outliner, &te->subtree, id, te, TSE_EBONE, a); + int a = 0; + LISTBASE_FOREACH_INDEX (EditBone *, ebone, arm->edbo, a) { + TreeElement *ten = outliner_add_element( + space_outliner, &te->subtree, id, te, TSE_EBONE, a); ten->directdata = ebone; ten->name = ebone->name; ebone->temp.p = ten; } /* make hierarchy */ - ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp.p : NULL; + TreeElement *ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp.p : NULL; while (ten) { TreeElement *nten = ten->next, *par; - ebone = (EditBone *)ten->directdata; + EditBone *ebone = (EditBone *)ten->directdata; if (ebone->parent) { BLI_remlink(&te->subtree, ten); par = ebone->parent->temp.p; @@ -852,9 +825,9 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, /* pass */ } else { - Bone *curBone; - for (curBone = arm->bonebase.first; curBone; curBone = curBone->next) { - outliner_add_bone(space_outliner, &te->subtree, id, curBone, te, &a); + int a = 0; + LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) { + outliner_add_bone(space_outliner, &te->subtree, id, bone, te, &a); } } } @@ -862,13 +835,12 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_LS: { FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id; - int a; if (outliner_animdata_test(linestyle->adt)) { outliner_add_element(space_outliner, &te->subtree, linestyle, te, TSE_ANIM_DATA, 0); } - for (a = 0; a < MAX_MTEX; a++) { + for (int a = 0; a < MAX_MTEX; a++) { if (linestyle->mtex[a]) { outliner_add_element(space_outliner, &te->subtree, linestyle->mtex[a]->tex, te, 0, a); } @@ -877,17 +849,16 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_GD: { bGPdata *gpd = (bGPdata *)id; - bGPDlayer *gpl; - int a = 0; if (outliner_animdata_test(gpd->adt)) { outliner_add_element(space_outliner, &te->subtree, gpd, te, TSE_ANIM_DATA, 0); } /* TODO: base element for layers? */ - for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) { - outliner_add_element(space_outliner, &te->subtree, gpl, te, TSE_GP_LAYER, a); - a++; + int index = 0; + LISTBASE_FOREACH_BACKWARD (bGPDlayer *, gpl, &gpd->layers) { + outliner_add_element(space_outliner, &te->subtree, gpl, te, TSE_GP_LAYER, index); + index++; } break; } @@ -957,8 +928,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, short type, short index) { - TreeElement *te; - TreeStoreElem *tselem; ID *id = idv; if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { @@ -985,12 +954,12 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, BLI_assert(TREESTORE_ID_TYPE(id)); } - te = MEM_callocN(sizeof(TreeElement), "tree elem"); + TreeElement *te = MEM_callocN(sizeof(TreeElement), __func__); /* add to the visual tree */ BLI_addtail(lb, te); /* add to the storage */ check_persistent(space_outliner, te, id, type, index); - tselem = TREESTORE(te); + TreeStoreElem *tselem = TREESTORE(te); /* if we are searching for something expand to see child elements */ if (SEARCHING_OUTLINER(space_outliner)) { @@ -1022,9 +991,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, else if (type == TSE_ID_BASE) { /* pass */ } - else if (ELEM(type, TSE_KEYMAP, TSE_KEYMAP_ITEM)) { - /* pass */ - } else { /* Other cases must be caught above. */ BLI_assert(TSE_IS_REAL_ID(tselem)); @@ -1062,7 +1028,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } else if (type == TSE_SEQUENCE) { Sequence *seq = (Sequence *)idv; - Sequence *p; /* * The idcode is a little hack, but the outliner @@ -1081,10 +1046,8 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, */ if (seq->type == SEQ_TYPE_META) { - p = seq->seqbase.first; - while (p) { + LISTBASE_FOREACH (Sequence *, p, &seq->seqbase) { outliner_add_element(space_outliner, &te->subtree, (void *)p, te, TSE_SEQUENCE, index); - p = p->next; } } else { @@ -1112,17 +1075,13 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, te->name = seq->strip->stripdata->name; } else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { - PointerRNA pptr, propptr, *ptr = (PointerRNA *)idv; - PropertyRNA *prop, *iterprop; - PropertyType proptype; + PointerRNA *ptr = (PointerRNA *)idv; /* Don't display arrays larger, weak but index is stored as a short, * also the outliner isn't intended for editing such large data-sets. */ BLI_STATIC_ASSERT(sizeof(te->index) == 2, "Index is no longer short!") const int tot_limit = SHRT_MAX; - int a, tot; - /* we do lazy build, for speed and to avoid infinite recursion */ if (ptr->data == NULL) { @@ -1144,8 +1103,8 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, tselem->flag &= ~TSE_CHILDSEARCH; } - iterprop = RNA_struct_iterator_property(ptr->type); - tot = RNA_property_collection_length(ptr, iterprop); + PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type); + int tot = RNA_property_collection_length(ptr, iterprop); CLAMP_MAX(tot, tot_limit); /* auto open these cases */ @@ -1156,7 +1115,8 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } if (TSELEM_OPEN(tselem, space_outliner)) { - for (a = 0; a < tot; a++) { + for (int a = 0; a < tot; a++) { + PointerRNA propptr; RNA_property_collection_lookup_int(ptr, iterprop, a, &propptr); if (!(RNA_property_flag(propptr.data) & PROP_HIDDEN)) { outliner_add_element( @@ -1172,11 +1132,12 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } else if (type == TSE_RNA_PROPERTY) { /* property */ - iterprop = RNA_struct_iterator_property(ptr->type); + PointerRNA propptr; + PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type); RNA_property_collection_lookup_int(ptr, iterprop, index, &propptr); - prop = propptr.data; - proptype = RNA_property_type(prop); + PropertyRNA *prop = propptr.data; + PropertyType proptype = RNA_property_type(prop); te->name = RNA_property_ui_name(prop); te->directdata = prop; @@ -1188,7 +1149,7 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } if (proptype == PROP_POINTER) { - pptr = RNA_property_pointer_get(ptr, prop); + PointerRNA pptr = RNA_property_pointer_get(ptr, prop); if (pptr.data) { if (TSELEM_OPEN(tselem, space_outliner)) { @@ -1201,11 +1162,12 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } } else if (proptype == PROP_COLLECTION) { - tot = RNA_property_collection_length(ptr, prop); + int tot = RNA_property_collection_length(ptr, prop); CLAMP_MAX(tot, tot_limit); if (TSELEM_OPEN(tselem, space_outliner)) { - for (a = 0; a < tot; a++) { + for (int a = 0; a < tot; a++) { + PointerRNA pptr; RNA_property_collection_lookup_int(ptr, prop, a, &pptr); outliner_add_element( space_outliner, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, a); @@ -1216,11 +1178,11 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } } else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) { - tot = RNA_property_array_length(ptr, prop); + int tot = RNA_property_array_length(ptr, prop); CLAMP_MAX(tot, tot_limit); if (TSELEM_OPEN(tselem, space_outliner)) { - for (a = 0; a < tot; a++) { + for (int a = 0; a < tot; a++) { outliner_add_element( space_outliner, &te->subtree, (void *)ptr, te, TSE_RNA_ARRAY_ELEM, a); } @@ -1231,15 +1193,13 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } } else if (type == TSE_RNA_ARRAY_ELEM) { - char c; - - prop = parent->directdata; + PropertyRNA *prop = parent->directdata; te->directdata = prop; te->rnaptr = *ptr; te->index = index; - c = RNA_property_array_item_char(prop, index); + char c = RNA_property_array_item_char(prop, index); te->name = MEM_callocN(sizeof(char[20]), "OutlinerRNAArrayName"); if (c) { @@ -1251,52 +1211,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, te->flag |= TE_FREE_NAME; } } - else if (type == TSE_KEYMAP) { - wmKeyMap *km = (wmKeyMap *)idv; - wmKeyMapItem *kmi; - char opname[OP_MAX_TYPENAME]; - - te->directdata = idv; - te->name = km->idname; - - if (TSELEM_OPEN(tselem, space_outliner)) { - int a = 0; - - for (kmi = km->items.first; kmi; kmi = kmi->next, a++) { - const char *key = WM_key_event_string(kmi->type, false); - - if (key[0]) { - wmOperatorType *ot = NULL; - - if (kmi->propvalue) { - /* pass */ - } - else { - ot = WM_operatortype_find(kmi->idname, 0); - } - - if (ot || kmi->propvalue) { - TreeElement *ten = outliner_add_element( - space_outliner, &te->subtree, kmi, te, TSE_KEYMAP_ITEM, a); - - ten->directdata = kmi; - - if (kmi->propvalue) { - ten->name = IFACE_("Modal map, not yet"); - } - else { - WM_operator_py_idname(opname, ot->idname); - ten->name = BLI_strdup(opname); - ten->flag |= TE_FREE_NAME; - } - } - } - } - } - else { - te->flag |= TE_LAZY_CLOSED; - } - } return te; } @@ -1344,21 +1258,18 @@ static TreeElement *outliner_add_collection_recursive(SpaceOutliner *space_outli /* make sure elements are correctly nested */ void outliner_make_object_parent_hierarchy(ListBase *lb) { - TreeElement *te, *ten, *tep; - TreeStoreElem *tselem; - /* build hierarchy */ /* XXX also, set extents here... */ - te = lb->first; + TreeElement *te = lb->first; while (te) { - ten = te->next; - tselem = TREESTORE(te); + TreeElement *ten = te->next; + TreeStoreElem *tselem = TREESTORE(te); if (tselem->type == 0 && te->idcode == ID_OB) { Object *ob = (Object *)tselem->id; if (ob->parent && ob->parent->id.newid) { BLI_remlink(lb, te); - tep = (TreeElement *)ob->parent->id.newid; + TreeElement *tep = (TreeElement *)ob->parent->id.newid; BLI_addtail(&tep->subtree, te); te->parent = tep; } @@ -1380,10 +1291,9 @@ typedef struct tTreeSort { static int treesort_alpha_ob(const void *v1, const void *v2) { const tTreeSort *x1 = v1, *x2 = v2; - int comp; /* first put objects last (hierarchy) */ - comp = (x1->idcode == ID_OB); + int comp = (x1->idcode == ID_OB); if (x2->idcode == ID_OB) { comp += 2; } @@ -1432,9 +1342,8 @@ static int treesort_child_not_in_collection(const void *v1, const void *v2) static int treesort_alpha(const void *v1, const void *v2) { const tTreeSort *x1 = v1, *x2 = v2; - int comp; - comp = BLI_strcasecmp_natural(x1->name, x2->name); + int comp = BLI_strcasecmp_natural(x1->name, x2->name); if (comp > 0) { return 1; @@ -1489,14 +1398,11 @@ static int treesort_obtype_alpha(const void *v1, const void *v2) /* sort happens on each subtree individual */ static void outliner_sort(ListBase *lb) { - TreeElement *te; - TreeStoreElem *tselem; - - te = lb->last; + TreeElement *te = lb->last; if (te == NULL) { return; } - tselem = TREESTORE(te); + TreeStoreElem *tselem = TREESTORE(te); /* sorting rules; only object lists, ID lists, or deformgroups */ if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || @@ -1558,14 +1464,11 @@ static void outliner_sort(ListBase *lb) static void outliner_collections_children_sort(ListBase *lb) { - TreeElement *te; - TreeStoreElem *tselem; - - te = lb->last; + TreeElement *te = lb->last; if (te == NULL) { return; } - tselem = TREESTORE(te); + TreeStoreElem *tselem = TREESTORE(te); /* Sorting rules: only object lists. */ if (tselem->type == 0 && te->idcode == ID_OB) { @@ -1687,8 +1590,7 @@ static TreeElement *outliner_find_first_desired_element_at_y(const SpaceOutliner const float view_co, const float view_co_limit) { - TreeElement *te, *te_sub; - te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_co); + TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_co); bool (*callback_test)(TreeElement *); if ((space_outliner->outlinevis == SO_VIEW_LAYER) && @@ -1700,7 +1602,7 @@ static TreeElement *outliner_find_first_desired_element_at_y(const SpaceOutliner } while (te != NULL) { - te_sub = outliner_find_first_desired_element_at_y_recursive( + TreeElement *te_sub = outliner_find_first_desired_element_at_y_recursive( space_outliner, te, view_co_limit, callback_test); if (te_sub != NULL) { /* Skip the element if it was not visible to start with. */ @@ -1742,12 +1644,12 @@ static void outliner_store_scrolling_position(SpaceOutliner *space_outliner, ARegion *region, OutlinerTreeElementFocus *focus) { - TreeElement *te; float limit = region->v2d.cur.ymin; outliner_set_coordinates(region, space_outliner); - te = outliner_find_first_desired_element_at_y(space_outliner, region->v2d.cur.ymax, limit); + TreeElement *te = outliner_find_first_desired_element_at_y( + space_outliner, region->v2d.cur.ymax, limit); if (te != NULL) { focus->tselem = TREESTORE(te); diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c index e0d63dfcf81..92178cfdfc9 100644 --- a/source/blender/editors/space_outliner/outliner_utils.c +++ b/source/blender/editors/space_outliner/outliner_utils.c @@ -169,7 +169,7 @@ TreeElement *outliner_find_item_at_x_in_row(const SpaceOutliner *space_outliner, return te; } -/* Find specific item from the treestore */ +/* Find specific item from the trees-tore. */ TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem) { LISTBASE_FOREACH (TreeElement *, te, lb) { diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 6c9d4433abd..87f81a2cc0e 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -31,9 +31,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" -#include "BKE_layer.h" #include "BKE_outliner_treehash.h" -#include "BKE_scene.h" #include "BKE_screen.h" #include "ED_screen.h" @@ -51,7 +49,6 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "GPU_framebuffer.h" #include "outliner_intern.h" #include "tree/tree_display.h" @@ -102,12 +99,11 @@ static void outliner_main_region_free(ARegion *UNUSED(region)) { } -static void outliner_main_region_listener(wmWindow *UNUSED(win), - ScrArea *area, - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void outliner_main_region_listener(const wmRegionListenerParams *params) { + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; SpaceOutliner *space_outliner = area->spacedata.first; /* context changes */ @@ -264,15 +260,13 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win), } } -static void outliner_main_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void outliner_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ScrArea *area = params->area; + ARegion *region = params->region; SpaceOutliner *space_outliner = area->spacedata.first; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, @@ -301,12 +295,11 @@ static void outliner_header_region_free(ARegion *UNUSED(region)) { } -static void outliner_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void outliner_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCENE: @@ -332,7 +325,7 @@ static SpaceLink *outliner_create(const ScrArea *UNUSED(area), const Scene *UNUS space_outliner = MEM_callocN(sizeof(SpaceOutliner), "initoutliner"); space_outliner->spacetype = SPACE_OUTLINER; space_outliner->filter_id_type = ID_GR; - space_outliner->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE; + space_outliner->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE | SO_RESTRICT_RENDER; space_outliner->outlinevis = SO_VIEW_LAYER; space_outliner->sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_ALL; space_outliner->flag = SO_SYNC_SELECT | SO_MODE_COLUMN; diff --git a/source/blender/editors/space_outliner/tree/tree_display.cc b/source/blender/editors/space_outliner/tree/tree_display.cc index d2070fb9b1c..6632c057814 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.cc +++ b/source/blender/editors/space_outliner/tree/tree_display.cc @@ -18,8 +18,6 @@ * \ingroup spoutliner */ -#include "BLI_listbase.h" - #include "DNA_listBase.h" #include "tree_display.hh" diff --git a/source/blender/editors/space_outliner/tree/tree_element.cc b/source/blender/editors/space_outliner/tree/tree_element.cc index ce2a8fa634d..27846614994 100644 --- a/source/blender/editors/space_outliner/tree/tree_element.cc +++ b/source/blender/editors/space_outliner/tree/tree_element.cc @@ -20,8 +20,6 @@ #include "DNA_listBase.h" -#include "../outliner_intern.h" - #include "tree_element_anim_data.hh" #include "tree_element_driver_base.hh" #include "tree_element_nla.hh" diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c index 3330ba14530..4ce0e454df8 100644 --- a/source/blender/editors/space_script/space_script.c +++ b/source/blender/editors/space_script/space_script.c @@ -36,7 +36,6 @@ #include "ED_space_api.h" #include "WM_api.h" -#include "WM_types.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -44,7 +43,6 @@ #ifdef WITH_PYTHON #endif -#include "GPU_framebuffer.h" #include "script_intern.h" /* own include */ // static script_run_python(char *funcname, ) @@ -156,13 +154,8 @@ static void script_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void script_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void script_main_region_listener(const wmRegionListenerParams *UNUSED(params)) { -/* context changes */ /* XXX - Todo, need the ScriptSpace accessible to get the python script to run. */ #if 0 BPY_run_script_space_listener() diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index f9076145f2f..e605cf4a889 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -66,8 +66,6 @@ #include "UI_interface.h" -#include "BKE_sound.h" - #ifdef WITH_AUDASPACE # include <AUD_Sequence.h> #endif @@ -1069,6 +1067,9 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) else if (seq->type == SEQ_TYPE_TEXT) { seq->blend_mode = SEQ_TYPE_ALPHAOVER; } + else if (SEQ_effect_get_num_inputs(seq->type) == 1) { + seq->blend_mode = seq1->blend_mode; + } /* Set channel. If unset, use lowest free one above strips. */ if (!RNA_struct_property_is_set(op->ptr, "channel")) { diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c index a8c13d63259..11614d94862 100644 --- a/source/blender/editors/space_sequencer/sequencer_buttons.c +++ b/source/blender/editors/space_sequencer/sequencer_buttons.c @@ -35,13 +35,9 @@ #include "BKE_global.h" #include "BKE_screen.h" -#include "ED_gpencil.h" #include "ED_screen.h" #include "ED_sequencer.h" -#include "WM_api.h" -#include "WM_types.h" - #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 72c3e43185b..201df1ceed6 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1447,15 +1447,24 @@ static void sequencer_draw_borders_overlay(const SpaceSeq *sseq, if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) { immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f); - UI_draw_safe_areas( - shdr_pos, x1, x2, y1, y2, scene->safe_areas.title, scene->safe_areas.action); + UI_draw_safe_areas(shdr_pos, + &(const rctf){ + .xmin = x1, + .xmax = x2, + .ymin = y1, + .ymax = y2, + }, + scene->safe_areas.title, + scene->safe_areas.action); if (sseq->flag & SEQ_SHOW_SAFE_CENTER) { UI_draw_safe_areas(shdr_pos, - x1, - x2, - y1, - y2, + &(const rctf){ + .xmin = x1, + .xmax = x2, + .ymin = y1, + .ymax = y2, + }, scene->safe_areas.title_center, scene->safe_areas.action_center); } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 7474f8034de..608e220c582 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -28,7 +28,6 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" -#include "BLI_ghash.h" #include "BLI_math.h" #include "BLI_timecode.h" #include "BLI_utildefines.h" diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index 7bfc8600544..48e6cfcdcd0 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -29,12 +29,7 @@ #include "WM_api.h" #include "WM_types.h" -#include "ED_markers.h" -#include "ED_select_utils.h" #include "ED_sequencer.h" -#include "ED_transform.h" /* Transform keymap. */ - -#include "SEQ_sequencer.h" #include "sequencer_intern.h" diff --git a/source/blender/editors/space_sequencer/sequencer_proxy.c b/source/blender/editors/space_sequencer/sequencer_proxy.c index b9698492aa5..24fa4ad7a17 100644 --- a/source/blender/editors/space_sequencer/sequencer_proxy.c +++ b/source/blender/editors/space_sequencer/sequencer_proxy.c @@ -25,7 +25,6 @@ #include "BLI_blenlib.h" #include "BLI_ghash.h" -#include "BLI_timecode.h" #include "DNA_scene_types.h" diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index f5707d1ea65..16768e09cb8 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -30,8 +30,6 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "atomic_ops.h" - #include "sequencer_intern.h" /* XXX, why is this function better than BLI_math version? diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 3b476fefe47..ffcb3d35d5a 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -26,6 +26,7 @@ #include <string.h> #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -771,69 +772,83 @@ void SEQUENCER_OT_select(wmOperatorType *ot) * \{ */ /* Run recursively to select linked. */ -static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool linked) +static bool select_linked_internal(Scene *scene) { Editing *ed = SEQ_editing_get(scene, false); - Sequence *seq, *neighbor; - bool changed = false; - int isel; if (ed == NULL) { - return changed; + return false; } - if (sel) { - sel = SELECT; - isel = 0; + bool changed = false; + + LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { + if ((seq->flag & SELECT) != 0) { + continue; + } + /* Only get unselected neighbors. */ + Sequence *neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, 0); + if (neighbor) { + neighbor->flag |= SELECT; + recurs_sel_seq(neighbor); + changed = true; + } + neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, 0); + if (neighbor) { + neighbor->flag |= SELECT; + recurs_sel_seq(neighbor); + changed = true; + } } - else { - sel = 0; - isel = SELECT; + + return changed; +} + +/* Select only one linked strip on each side. */ +static bool select_more_less_seq__internal(Scene *scene, bool select_more) +{ + Editing *ed = SEQ_editing_get(scene, false); + + if (ed == NULL) { + return false; } - if (!linked) { - /* If not linked we only want to touch each seq once, newseq. */ - for (seq = ed->seqbasep->first; seq; seq = seq->next) { - seq->tmp = NULL; + GSet *neighbors = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "Linked strips"); + const int neighbor_selection_filter = select_more ? 0 : SELECT; + const int selection_filter = select_more ? SELECT : 0; + + LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { + if ((seq->flag & SELECT) != selection_filter) { + continue; + } + Sequence *neighbor = find_neighboring_sequence( + scene, seq, SEQ_SIDE_LEFT, neighbor_selection_filter); + if (neighbor) { + BLI_gset_add(neighbors, neighbor); + } + neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, neighbor_selection_filter); + if (neighbor) { + BLI_gset_add(neighbors, neighbor); } } - for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if ((seq->flag & SELECT) == sel) { - if (linked || (seq->tmp == NULL)) { - /* Only get unselected neighbors. */ - neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel); - if (neighbor) { - if (sel) { - neighbor->flag |= SELECT; - recurs_sel_seq(neighbor); - } - else { - neighbor->flag &= ~SELECT; - } - if (!linked) { - neighbor->tmp = (Sequence *)1; - } - changed = true; - } - neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, isel); - if (neighbor) { - if (sel) { - neighbor->flag |= SELECT; - recurs_sel_seq(neighbor); - } - else { - neighbor->flag &= ~SELECT; - } - if (!linked) { - neighbor->tmp = (Sequence *)1; - } - changed = true; - } - } + bool changed = false; + GSetIterator gsi; + BLI_gsetIterator_init(&gsi, neighbors); + while (!BLI_gsetIterator_done(&gsi)) { + Sequence *neighbor = BLI_gsetIterator_getKey(&gsi); + if (select_more) { + neighbor->flag |= SELECT; + recurs_sel_seq(neighbor); + } + else { + neighbor->flag &= ~SELECT; } + changed = true; + BLI_gsetIterator_step(&gsi); } + BLI_gset_free(neighbors, NULL); return changed; } @@ -841,7 +856,7 @@ static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - if (!select_more_less_seq__internal(scene, true, false)) { + if (!select_more_less_seq__internal(scene, true)) { return OPERATOR_CANCELLED; } @@ -877,7 +892,7 @@ static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - if (!select_more_less_seq__internal(scene, false, false)) { + if (!select_more_less_seq__internal(scene, false)) { return OPERATOR_CANCELLED; } @@ -934,7 +949,7 @@ static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, cons selected = 1; while (selected) { - selected = select_more_less_seq__internal(scene, 1, 1); + selected = select_linked_internal(scene); } ED_outliner_select_sync_from_sequence_tag(C); @@ -975,7 +990,7 @@ static int sequencer_select_linked_exec(bContext *C, wmOperator *UNUSED(op)) selected = true; while (selected) { - selected = select_more_less_seq__internal(scene, true, true); + selected = select_linked_internal(scene); } ED_outliner_select_sync_from_sequence_tag(C); diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index b11e2a32b87..b17482cd3a4 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -51,7 +51,6 @@ #include "RNA_access.h" -#include "SEQ_sequencer.h" #include "SEQ_utils.h" #include "UI_interface.h" @@ -334,11 +333,11 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl) return (SpaceLink *)sseqn; } -static void sequencer_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void sequencer_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + /* Context changes. */ switch (wmn->category) { case NC_SCENE: @@ -534,12 +533,11 @@ static void sequencer_main_region_draw_overlay(const bContext *C, ARegion *regio draw_timeline_seq_display(C, region); } -static void sequencer_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void sequencer_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* Context changes. */ switch (wmn->category) { case NC_SCENE: @@ -579,14 +577,12 @@ static void sequencer_main_region_listener(wmWindow *UNUSED(win), } } -static void sequencer_main_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *scene, - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +static void sequencer_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + Scene *scene = params->scene; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, @@ -746,12 +742,11 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *region) } } -static void sequencer_preview_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void sequencer_preview_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* Context changes. */ switch (wmn->category) { case NC_GPENCIL: @@ -816,12 +811,11 @@ static void sequencer_buttons_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void sequencer_buttons_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void sequencer_buttons_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* Context changes. */ switch (wmn->category) { case NC_GPENCIL: @@ -959,7 +953,7 @@ void ED_spacetype_sequencer(void) art->listener = sequencer_main_region_listener; BLI_addhead(&st->regiontypes, art); - /* Hud. */ + /* HUD. */ art = ED_area_type_hud(st->spaceid); BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_statusbar/space_statusbar.c b/source/blender/editors/space_statusbar/space_statusbar.c index ae56b111360..0b4f483c114 100644 --- a/source/blender/editors/space_statusbar/space_statusbar.c +++ b/source/blender/editors/space_statusbar/space_statusbar.c @@ -34,7 +34,6 @@ #include "RNA_access.h" #include "UI_interface.h" -#include "UI_view2d.h" #include "WM_api.h" #include "WM_message.h" @@ -95,12 +94,11 @@ static void statusbar_keymap(struct wmKeyConfig *UNUSED(keyconf)) { } -static void statusbar_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void statusbar_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCREEN: @@ -131,14 +129,11 @@ static void statusbar_header_region_listener(wmWindow *UNUSED(win), } } -static void statusbar_header_region_message_subscribe(const bContext *UNUSED(C), - WorkSpace *UNUSED(workspace), - Scene *UNUSED(scene), - bScreen *UNUSED(screen), - ScrArea *UNUSED(area), - ARegion *region, - struct wmMsgBus *mbus) +static void statusbar_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 0f5ac5abe1d..ea55eaea388 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -33,7 +33,6 @@ #include "BKE_global.h" #include "BKE_lib_id.h" #include "BKE_screen.h" -#include "BKE_text.h" #include "ED_screen.h" #include "ED_space_api.h" @@ -47,7 +46,6 @@ #include "RNA_access.h" -#include "GPU_framebuffer.h" #include "text_format.h" #include "text_intern.h" /* own include */ @@ -122,11 +120,10 @@ static SpaceLink *text_duplicate(SpaceLink *sl) return (SpaceLink *)stextn; } -static void text_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void text_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceText *st = area->spacedata.first; /* context changes */ diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 849766851aa..883556948e2 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -722,7 +722,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *region) void text_drawcache_tag_update(SpaceText *st, int full) { - /* this happens if text editor ops are caled from python */ + /* This happens if text editor ops are called from Python. */ if (st == NULL) { return; } @@ -1010,13 +1010,16 @@ static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back) BLI_rcti_size_y(&st->runtime.scroll_region_select)); UI_GetThemeColor3fv(TH_HILITE, col); col[3] = 0.18f; - UI_draw_roundbox_aa(true, - st->runtime.scroll_region_select.xmin + 1, - st->runtime.scroll_region_select.ymin, - st->runtime.scroll_region_select.xmax - 1, - st->runtime.scroll_region_select.ymax, - rad, - col); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = st->runtime.scroll_region_select.xmin + 1, + .xmax = st->runtime.scroll_region_select.xmax - 1, + .ymin = st->runtime.scroll_region_select.ymin, + .ymax = st->runtime.scroll_region_select.ymax, + }, + true, + rad, + col); } /*********************** draw documentation *******************************/ @@ -1180,7 +1183,14 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc } /* not needed but stands out nicer */ - UI_draw_box_shadow(220, x, y - boxh, x + boxw, y); + UI_draw_box_shadow( + &(const rctf){ + .xmin = x, + .xmax = x + boxw, + .ymin = y - boxh, + .ymax = y, + }, + 220); uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c index d099f2a20d8..66765206fa6 100644 --- a/source/blender/editors/space_text/text_format.c +++ b/source/blender/editors/space_text/text_format.c @@ -237,7 +237,7 @@ bool ED_text_is_syntax_highlight_supported(Text *text) const char *text_ext = BLI_path_extension(text->id.name + 2); if (text_ext == NULL) { - /* Extensionless datablocks are considered highlightable as Python. */ + /* Extensionless data-blocks are considered highlightable as Python. */ return true; } text_ext++; /* skip the '.' */ diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 932bacfb8a0..526285c076a 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -3832,7 +3832,7 @@ static int text_resolve_conflict_invoke(bContext *C, wmOperator *op, const wmEve switch (BKE_text_file_modified_check(text)) { case 1: if (text->flags & TXT_ISDIRTY) { - /* modified locally and externally, ahhh. offer more possibilities. */ + /* Modified locally and externally, ah. offer more possibilities. */ pup = UI_popup_menu_begin( C, IFACE_("File Modified Outside and Inside Blender"), ICON_NONE); layout = UI_popup_menu_layout(pup); diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c index 61b786b2b13..f55db8c3cc9 100644 --- a/source/blender/editors/space_text/text_undo.c +++ b/source/blender/editors/space_text/text_undo.c @@ -196,14 +196,19 @@ static bool text_undosys_step_encode(struct bContext *C, return true; } -static void text_undosys_step_decode( - struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, int dir, bool is_final) +static void text_undosys_step_decode(struct bContext *C, + struct Main *UNUSED(bmain), + UndoStep *us_p, + const eUndoStepDir dir, + bool is_final) { + BLI_assert(dir != STEP_INVALID); + TextUndoStep *us = (TextUndoStep *)us_p; Text *text = us->text_ref.ptr; TextState *state; - if ((us->states[0].buf_array_state != NULL) && (dir == -1) && !is_final) { + if ((us->states[0].buf_array_state != NULL) && (dir == STEP_UNDO) && !is_final) { state = &us->states[0]; } else { diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c index dc357cdd355..419721cf89e 100644 --- a/source/blender/editors/space_topbar/space_topbar.c +++ b/source/blender/editors/space_topbar/space_topbar.c @@ -38,7 +38,6 @@ #include "ED_screen.h" #include "ED_space_api.h" -#include "ED_undo.h" #include "UI_interface.h" #include "UI_resources.h" @@ -129,12 +128,11 @@ static void topbar_header_region_init(wmWindowManager *UNUSED(wm), ARegion *regi ED_region_header_init(region); } -static void topbar_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void topbar_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_WM: @@ -160,12 +158,11 @@ static void topbar_main_region_listener(wmWindow *UNUSED(win), } } -static void topbar_header_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void topbar_header_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_WM: @@ -191,14 +188,12 @@ static void topbar_header_listener(wmWindow *UNUSED(win), } } -static void topbar_header_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *workspace, - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +static void topbar_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + WorkSpace *workspace = params->workspace; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index 3efdee9cec9..d4692f156d3 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -183,46 +183,20 @@ static void userpref_execute_region_init(wmWindowManager *wm, ARegion *region) region->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y; } -static void userpref_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void userpref_main_region_listener(const wmRegionListenerParams *UNUSED(params)) { - /* context changes */ } -static void userpref_header_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void userpref_header_listener(const wmRegionListenerParams *UNUSED(params)) { - /* context changes */ -#if 0 - switch (wmn->category) { - default: - break; - } -#endif } -static void userpref_navigation_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void userpref_navigation_region_listener(const wmRegionListenerParams *UNUSED(params)) { - /* context changes */ } -static void userpref_execute_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void userpref_execute_region_listener(const wmRegionListenerParams *UNUSED(params)) { - /* context changes */ } /* only called once, from space/spacetypes.c */ diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c index f05d6df9944..7c799f0d97b 100644 --- a/source/blender/editors/space_userpref/userpref_ops.c +++ b/source/blender/editors/space_userpref/userpref_ops.c @@ -28,10 +28,8 @@ #include "BLI_listbase.h" #include "BKE_context.h" -#include "BKE_global.h" #include "BKE_main.h" #include "BKE_preferences.h" -#include "BKE_report.h" #include "RNA_access.h" #include "RNA_define.h" @@ -39,8 +37,6 @@ #include "UI_interface.h" -#include "../interface/interface_intern.h" - #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 4c168c7a243..98e1d927daf 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -393,7 +393,7 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *region) keymap = WM_keymap_ensure(wm->defaultconf, "Paint Vertex Selection (Weight, Vertex)", 0, 0); WM_event_add_keymap_handler(®ion->handlers, keymap); - /* Before 'Weight/Vertex Paint' so adding curve points is not overriden. */ + /* Before 'Weight/Vertex Paint' so adding curve points is not overridden. */ keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0); WM_event_add_keymap_handler(®ion->handlers, keymap); @@ -469,16 +469,30 @@ static bool view3d_drop_in_main_region_poll(bContext *C, const wmEvent *event) return ED_region_overlap_isect_any_xy(area, &event->x) == false; } -static ID *view3d_drop_id_in_main_region_poll_id(bContext *C, - wmDrag *drag, - const wmEvent *event, - ID_Type id_type) +static ID_Type view3d_drop_id_in_main_region_poll_get_id_type(bContext *C, + wmDrag *drag, + const wmEvent *event) { - ScrArea *area = CTX_wm_area(C); + const ScrArea *area = CTX_wm_area(C); + if (ED_region_overlap_isect_any_xy(area, &event->x)) { - return NULL; + return 0; + } + if (!view3d_drop_in_main_region_poll(C, event)) { + return 0; + } + + ID *local_id = WM_drag_get_local_ID(drag, 0); + if (local_id) { + return GS(local_id->name); + } + + wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0); + if (asset_drag) { + return asset_drag->id_type; } - return view3d_drop_in_main_region_poll(C, event) ? WM_drag_get_local_ID(drag, id_type) : NULL; + + return 0; } static bool view3d_drop_id_in_main_region_poll(bContext *C, @@ -490,7 +504,7 @@ static bool view3d_drop_id_in_main_region_poll(bContext *C, return false; } - return WM_drag_get_local_ID(drag, id_type) || WM_drag_get_asset_data(drag, id_type); + return WM_drag_is_ID_type(drag, id_type); } static bool view3d_ob_drop_poll(bContext *C, @@ -522,9 +536,9 @@ static bool view3d_object_data_drop_poll(bContext *C, const wmEvent *event, const char **r_tooltip) { - ID *id = view3d_drop_id_in_main_region_poll_id(C, drag, event, 0); - if (id != NULL) { - if (BKE_object_obdata_to_type(id) != -1) { + ID_Type id_type = view3d_drop_id_in_main_region_poll_get_id_type(C, drag, event); + if (id_type) { + if (OB_DATA_SUPPORT_ID(id_type)) { *r_tooltip = TIP_("Create object instance from object-data"); return true; } @@ -545,7 +559,7 @@ static bool view3d_ima_drop_poll(bContext *C, return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)); } - return WM_drag_get_local_ID(drag, ID_IM) || WM_drag_get_asset_data(drag, ID_IM); + return WM_drag_is_ID_type(drag, ID_IM); } static bool view3d_ima_bg_is_camera_view(bContext *C) @@ -629,7 +643,7 @@ static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop) static void view3d_id_drop_copy_with_type(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_get_local_ID(drag, 0); + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); RNA_string_set(drop->ptr, "name", id->name + 2); RNA_enum_set(drop->ptr, "type", GS(id->name)); @@ -784,9 +798,13 @@ static void *view3d_main_region_duplicate(void *poin) return NULL; } -static void view3d_main_region_listener( - wmWindow *win, ScrArea *area, ARegion *region, wmNotifier *wmn, const Scene *scene) +static void view3d_main_region_listener(const wmRegionListenerParams *params) { + wmWindow *window = params->window; + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + const Scene *scene = params->scene; View3D *v3d = area->spacedata.first; RegionView3D *rv3d = region->regiondata; wmGizmoMap *gzmap = region->gizmo_map; @@ -1007,10 +1025,10 @@ static void view3d_main_region_listener( ED_view3d_xr_shading_update(G_MAIN->wm.first, v3d, scene); #endif - ViewLayer *view_layer = WM_window_get_active_view_layer(win); + ViewLayer *view_layer = WM_window_get_active_view_layer(window); Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer); if (depsgraph) { - ED_render_view3d_update(depsgraph, win, area, true); + ED_render_view3d_update(depsgraph, window, area, true); } } ED_region_tag_redraw(region); @@ -1048,14 +1066,13 @@ static void view3d_main_region_listener( } } -static void view3d_main_region_message_subscribe(const struct bContext *C, - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + const bContext *C = params->context; + ScrArea *area = params->area; + ARegion *region = params->region; + /* Developer note: there are many properties that impact 3D view drawing, * so instead of subscribing to individual properties, just subscribe to types * accepting some redundant redraws. @@ -1170,12 +1187,11 @@ static void view3d_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void view3d_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void view3d_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCENE: @@ -1240,14 +1256,11 @@ static void view3d_header_region_listener(wmWindow *UNUSED(win), #endif } -static void view3d_header_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +static void view3d_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgParams_RNA msg_key_params = {{0}}; /* Only subscribe to types. */ @@ -1385,12 +1398,11 @@ static void view3d_buttons_region_layout(const bContext *C, ARegion *region) ED_view3d_buttons_region_layout_ex(C, region, NULL); } -static void view3d_buttons_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void view3d_buttons_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -1509,11 +1521,10 @@ static void view3d_tools_region_draw(const bContext *C, ARegion *region) } /* area (not region) level listener */ -static void space_view3d_listener(wmWindow *UNUSED(win), - ScrArea *area, - struct wmNotifier *wmn, - Scene *UNUSED(scene)) +static void space_view3d_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; View3D *v3d = area->spacedata.first; /* context changes */ @@ -1580,7 +1591,8 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes if (view_layer->basact) { Object *ob = view_layer->basact->object; /* if hidden but in edit mode, we still display, can happen with animation */ - if ((view_layer->basact->flag & BASE_VISIBLE_DEPSGRAPH) != 0 || (ob->mode & OB_MODE_EDIT)) { + if ((view_layer->basact->flag & BASE_VISIBLE_DEPSGRAPH) != 0 || + (ob->mode != OB_MODE_OBJECT)) { CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact); } } @@ -1588,12 +1600,25 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes return 1; } else if (CTX_data_equals(member, "active_object")) { + /* In most cases the active object is the `view_layer->basact->object`. + * For the 3D view however it can be NULL when hidden. + * + * This is ignored in the case the object is in any mode (besides object-mode), + * since the object's mode impacts the current tool, cursor, gizmos etc. + * If we didn't have this exception, changing visibility would need to perform + * many of the the same updates as changing the objects mode. + * + * Further, there are multiple ways to hide objects - by collection, by object type, etc. + * it's simplest if all these methods behave consistently - respecting the object-mode + * without showing the object. + * + * See T85532 for alternatives that were considered. */ ViewLayer *view_layer = CTX_data_view_layer(C); if (view_layer->basact) { Object *ob = view_layer->basact->object; /* if hidden but in edit mode, we still display, can happen with animation */ if ((view_layer->basact->flag & BASE_VISIBLE_DEPSGRAPH) != 0 || - (ob->mode & OB_MODE_EDIT) != 0) { + (ob->mode != OB_MODE_OBJECT)) { CTX_data_id_pointer_set(result, &ob->id); } } diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c index 11643960595..0edd6aeb2ca 100644 --- a/source/blender/editors/space_view3d/view3d_camera_control.c +++ b/source/blender/editors/space_view3d/view3d_camera_control.c @@ -50,12 +50,8 @@ #include "DEG_depsgraph.h" -#include "ED_screen.h" - #include "view3d_intern.h" /* own include */ -#include "BLI_strict_flags.h" - typedef struct View3DCameraControl { /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 9982d44b6be..478f48700ea 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -165,7 +165,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph, rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f; } - /* calculate pixelsize factor once, is used for lights and obcenters */ + /* Calculate pixel-size factor once, this is used for lights and object-centers. */ { /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' * because of float point precision problems at large values T23908. */ @@ -723,15 +723,24 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region, } if (ca->flag & CAM_SHOW_SAFE_MARGINS) { - UI_draw_safe_areas( - shdr_pos, x1, x2, y1, y2, scene->safe_areas.title, scene->safe_areas.action); + UI_draw_safe_areas(shdr_pos, + &(const rctf){ + .xmin = x1, + .xmax = x2, + .ymin = y1, + .ymax = y2, + }, + scene->safe_areas.title, + scene->safe_areas.action); if (ca->flag & CAM_SHOW_SAFE_CENTER) { UI_draw_safe_areas(shdr_pos, - x1, - x2, - y1, - y2, + &(const rctf){ + .xmin = x1, + .xmax = x2, + .ymin = y1, + .ymax = y2, + }, scene->safe_areas.title_center, scene->safe_areas.action_center); } @@ -1960,13 +1969,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, /* XXX(jbakker): `do_color_management` should be controlled by the caller. Currently when doing a * viewport render animation and saving to an 8bit file format, color management would be applied * twice. Once here, and once when saving the saving to disk. In this case the Save As Render - * option cannot be controlled either. But when doing an offscreen render you want to do the + * option cannot be controlled either. But when doing an off-screen render you want to do the * color management here. * - * This option was added here to increase the performance when rendering for a playblast. When - * using workbench the color differences haven't been reported as a bug. But users also use the - * viewport rendering to render Eevee scenes. In the later situation the saved colors - * are totally wrong. */ + * This option was added here to increase the performance for quick view-port preview renders. + * When using workbench the color differences haven't been reported as a bug. But users also use + * the viewport rendering to render Eevee scenes. In the later situation the saved colors are + * totally wrong. */ const bool do_color_management = (ibuf->rect_float == NULL); ED_view3d_draw_offscreen(depsgraph, scene, @@ -2335,7 +2344,7 @@ void ED_view3d_depth_update(ARegion *region) } } -/* Utility function to find the closest Z value, use for autodepth. */ +/* Utility function to find the closest Z value, use for auto-depth. */ float view3d_depth_near(ViewDepths *d) { /* Convert to float for comparisons. */ diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index ab4e7be88fe..2f8cd5a7517 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -2025,7 +2025,7 @@ static float viewzoom_scale_value(const rcti *winrct, { float zfac; - if (viewzoom == USER_ZOOM_CONT) { + if (viewzoom == USER_ZOOM_CONTINUE) { double time = PIL_check_seconds_timer(); float time_step = (float)(time - *r_timer_lastdraw); float fac; @@ -2043,7 +2043,6 @@ static float viewzoom_scale_value(const rcti *winrct, fac = -fac; } - /* oldstyle zoom */ zfac = 1.0f + ((fac / 20.0f) * time_step); *r_timer_lastdraw = time; } @@ -2405,7 +2404,7 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_FINISHED; } - if (U.viewzoom == USER_ZOOM_CONT) { + if (U.viewzoom == USER_ZOOM_CONTINUE) { /* needs a timer to continue redrawing */ vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); vod->prev.time = PIL_check_seconds_timer(); @@ -2888,7 +2887,7 @@ static void view3d_from_minmax(bContext *C, }); } - /* smooth view does viewlock RV3D_BOXVIEW copy */ + /* Smooth-view does view-lock #RV3D_BOXVIEW copy. */ } /** @@ -3021,7 +3020,6 @@ void VIEW3D_OT_view_all(wmOperatorType *ot) * Move & Zoom the view to fit selected contents. * \{ */ -/* like a localview without local!, was centerview() in 2.4x */ static int viewselected_exec(bContext *C, wmOperator *op) { ARegion *region = CTX_wm_region(C); @@ -3282,7 +3280,7 @@ static int viewcenter_cursor_exec(bContext *C, wmOperator *op) ED_view3d_smooth_view( C, v3d, region, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs}); - /* smooth view does viewlock RV3D_BOXVIEW copy */ + /* Smooth view does view-lock #RV3D_BOXVIEW copy. */ } return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 6824c526888..2d499cf85c7 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -48,7 +48,7 @@ #include "ED_screen.h" #include "ED_space_api.h" -#include "PIL_time.h" /* smoothview */ +#include "PIL_time.h" /* Smooth-view. */ #include "UI_interface.h" #include "UI_resources.h" @@ -84,7 +84,7 @@ enum { FLY_MODAL_PRECISION_DISABLE, FLY_MODAL_FREELOOK_ENABLE, FLY_MODAL_FREELOOK_DISABLE, - FLY_MODAL_SPEED, /* mousepan typically */ + FLY_MODAL_SPEED, /* mouse-pan typically. */ }; /* relative view axis locking - xlock, zlock */ @@ -537,7 +537,7 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event) fly->state = FLY_CONFIRM; break; - /* speed adjusting with mousepan (trackpad) */ + /* Speed adjusting with mouse-pan (track-pad). */ case FLY_MODAL_SPEED: { float fac = 0.02f * (event->prevy - event->y); @@ -768,7 +768,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm) /* this is the direction that's added to the view offset per redraw */ float dvec[3] = {0, 0, 0}; - /* Camera Uprighting variables */ + /* Camera Up-righting variables. */ float moffset[2]; /* mouse offset from the views center */ float tmp_quat[4]; /* used for rotating the view */ @@ -950,7 +950,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm) } } - /* only apply xcorrect when mouse isn't applying x rot */ + /* Only apply X-axis correction when mouse isn't applying x rotation. */ if (fly->xlock == FLY_AXISLOCK_STATE_ACTIVE && moffset[1] == 0) { float upvec[3]; copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c index 242a0a802a6..98597cb2986 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c @@ -22,7 +22,6 @@ #include "BKE_context.h" #include "BKE_layer.h" -#include "BKE_object.h" #include "DNA_object_force_types.h" #include "DNA_object_types.h" diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c index 7a201d8841c..6fa974cdb09 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c @@ -22,7 +22,6 @@ #include "BLI_utildefines.h" #include "BKE_context.h" -#include "BKE_object.h" #include "DNA_object_types.h" @@ -45,14 +44,17 @@ /** \name View3D Navigation Gizmo Group * \{ */ -/* Offset from screen edge. */ -#define GIZMO_OFFSET_FAC 1.2f /* Size of main icon. */ -#define GIZMO_SIZE 80 -/* Factor for size of smaller button. */ -#define GIZMO_MINI_FAC 0.35f -/* How much mini buttons offset from the primary. */ -#define GIZMO_MINI_OFFSET_FAC 0.38f +#define GIZMO_SIZE U.gizmo_size_navigate_v3d + +/* Main gizmo offset from screen edges in unscaled pixels. */ +#define GIZMO_OFFSET 10.0f + +/* Width of smaller buttons in unscaled pixels. */ +#define GIZMO_MINI_SIZE 28.0f + +/* Margin around the smaller buttons. */ +#define GIZMO_MINI_OFFSET 2.0f enum { GZ_INDEX_MOVE = 0, @@ -174,7 +176,7 @@ static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup) } /* may be overwritten later */ - gz->scale_basis = (GIZMO_SIZE * GIZMO_MINI_FAC) / 2; + gz->scale_basis = GIZMO_MINI_SIZE / 2.0f; if (info->icon != 0) { PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon"); RNA_property_enum_set(gz->ptr, prop, info->icon); @@ -212,7 +214,7 @@ static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup) { wmGizmo *gz = navgroup->gz_array[GZ_INDEX_ROTATE]; - gz->scale_basis = GIZMO_SIZE / 2; + gz->scale_basis = GIZMO_SIZE / 2.0f; const char mapping[6] = { RV3D_VIEW_LEFT, RV3D_VIEW_RIGHT, @@ -263,9 +265,8 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g const bool show_navigate = (U.uiflag & USER_SHOW_GIZMO_NAVIGATE) != 0; const bool show_rotate_gizmo = (U.mini_axis_type == USER_MINI_AXIS_TYPE_GIZMO); - const float icon_size = GIZMO_SIZE; - const float icon_offset = (icon_size * 0.52f) * GIZMO_OFFSET_FAC * UI_DPI_FAC; - const float icon_offset_mini = icon_size * GIZMO_MINI_OFFSET_FAC * UI_DPI_FAC; + const float icon_offset = ((GIZMO_SIZE / 2.0f) + GIZMO_OFFSET) * UI_DPI_FAC; + const float icon_offset_mini = (GIZMO_MINI_SIZE + GIZMO_MINI_OFFSET) * UI_DPI_FAC; const float co_rotate[2] = { rect_visible->xmax - icon_offset, rect_visible->ymax - icon_offset, diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c index 8f3d40584aa..4ac16e8fbe8 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c @@ -40,6 +40,8 @@ #include "GPU_matrix.h" #include "GPU_state.h" +#include "BLF_api.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -53,169 +55,34 @@ #include "view3d_intern.h" -#define USE_AXIS_FONT -#define USE_FADE_BACKGROUND - -#ifdef USE_AXIS_FONT -# include "BLF_api.h" -#endif - -#define DIAL_RESOLUTION 32 - -/* Sizes of axis spheres containing XYZ characters. */ -#define AXIS_HANDLE_SIZE_FG 0.19f -/* When pointing away from the view. */ -#define AXIS_HANDLE_SIZE_BG 0.15f -/* How far axis handles are away from the center. */ -#define AXIS_HANDLE_OFFSET (1.0f - AXIS_HANDLE_SIZE_FG) - -struct AxisDrawInfo { - /* Matrix is needed for screen-aligned font drawing. */ -#ifdef USE_AXIS_FONT - float matrix_final[4][4]; -#endif -#ifdef USE_FADE_BACKGROUND - float color_bg[3]; -#endif -}; - -#ifndef USE_AXIS_FONT -/** - * \param viewmat_local_unit: is typically the 'rv3d->viewmatob' - * copied into a 3x3 matrix and normalized. - */ -static void draw_xyz_wire( - uint pos_id, const float viewmat_local_unit[3][3], const float c[3], float size, int axis) -{ - int line_type; - float buffer[4][3]; - int n = 0; - - float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3] = {0.0f, 0.0f, 0.0f}; - float dim = size * 0.1f; - float dx[3], dy[3]; - - dx[0] = dim; - dx[1] = 0.0f; - dx[2] = 0.0f; - dy[0] = 0.0f; - dy[1] = dim; - dy[2] = 0.0f; - - switch (axis) { - case 0: /* x axis */ - line_type = GPU_PRIM_LINES; - - /* bottom left to top right */ - negate_v3_v3(v1, dx); - sub_v3_v3(v1, dy); - copy_v3_v3(v2, dx); - add_v3_v3(v2, dy); - - copy_v3_v3(buffer[n++], v1); - copy_v3_v3(buffer[n++], v2); - - /* top left to bottom right */ - mul_v3_fl(dy, 2.0f); - add_v3_v3(v1, dy); - sub_v3_v3(v2, dy); - - copy_v3_v3(buffer[n++], v1); - copy_v3_v3(buffer[n++], v2); - - break; - case 1: /* y axis */ - line_type = GPU_PRIM_LINES; - - /* bottom left to top right */ - mul_v3_fl(dx, 0.75f); - negate_v3_v3(v1, dx); - sub_v3_v3(v1, dy); - copy_v3_v3(v2, dx); - add_v3_v3(v2, dy); - - copy_v3_v3(buffer[n++], v1); - copy_v3_v3(buffer[n++], v2); - - /* top left to center */ - mul_v3_fl(dy, 2.0f); - add_v3_v3(v1, dy); - zero_v3(v2); - - copy_v3_v3(buffer[n++], v1); - copy_v3_v3(buffer[n++], v2); - - break; - case 2: /* z axis */ - line_type = GPU_PRIM_LINE_STRIP; - - /* start at top left */ - negate_v3_v3(v1, dx); - add_v3_v3(v1, dy); - - copy_v3_v3(buffer[n++], v1); - - mul_v3_fl(dx, 2.0f); - add_v3_v3(v1, dx); +/* Radius of the entire background. */ +#define WIDGET_RADIUS ((U.gizmo_size_navigate_v3d / 2.0f) * UI_DPI_FAC) - copy_v3_v3(buffer[n++], v1); +/* Sizes of axis spheres containing XYZ characters in relation to above. */ +#define AXIS_HANDLE_SIZE 0.20f - mul_v3_fl(dy, 2.0f); - sub_v3_v3(v1, dx); - sub_v3_v3(v1, dy); +#define AXIS_LINE_WIDTH ((U.gizmo_size_navigate_v3d / 40.0f) * U.pixelsize) +#define AXIS_RING_WIDTH ((U.gizmo_size_navigate_v3d / 60.0f) * U.pixelsize) +#define AXIS_TEXT_SIZE (WIDGET_RADIUS * AXIS_HANDLE_SIZE * 1.25f) - copy_v3_v3(buffer[n++], v1); +/* distance within this from center is considered positive. */ +#define AXIS_DEPTH_BIAS 0.01f - add_v3_v3(v1, dx); - - copy_v3_v3(buffer[n++], v1); - - break; - default: - BLI_assert(0); - return; - } - - for (int i = 0; i < n; i++) { - mul_transposed_m3_v3((float(*)[3])viewmat_local_unit, buffer[i]); - add_v3_v3(buffer[i], c); - } - - immBegin(line_type, n); - for (int i = 0; i < n; i++) { - immVertex3fv(pos_id, buffer[i]); - } - immEnd(); -} -#endif /* !USE_AXIS_FONT */ - -/** - * \param draw_info: Extra data needed for drawing. - */ -static void axis_geom_draw(const wmGizmo *gz, - const float color[4], - const bool select, - const struct AxisDrawInfo *draw_info) +static void gizmo_axis_draw(const bContext *C, wmGizmo *gz) { - float viewport[4]; - GPU_viewport_size_get_f(viewport); - - GPUVertFormat *format = immVertexFormat(); - const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - struct { float depth; char index; char axis; + char axis_opposite; bool is_pos; } axis_order[6] = { - {-gz->matrix_offset[0][2], 0, 0, false}, - {+gz->matrix_offset[0][2], 1, 0, true}, - {-gz->matrix_offset[1][2], 2, 1, false}, - {+gz->matrix_offset[1][2], 3, 1, true}, - {-gz->matrix_offset[2][2], 4, 2, false}, - {+gz->matrix_offset[2][2], 5, 2, true}, + {-gz->matrix_offset[0][2], 0, 0, 1, false}, + {+gz->matrix_offset[0][2], 1, 0, 0, true}, + {-gz->matrix_offset[1][2], 2, 1, 3, false}, + {+gz->matrix_offset[1][2], 3, 1, 2, true}, + {-gz->matrix_offset[2][2], 4, 2, 5, false}, + {+gz->matrix_offset[2][2], 5, 2, 4, true}, }; int axis_align = -1; @@ -226,25 +93,35 @@ static void axis_geom_draw(const wmGizmo *gz, } } - /* Show backwards pointing highlight on-top (else we can't see it at all). */ - if ((select == false) && (gz->highlight_part > 0) && (axis_align != -1)) { - if (axis_order[gz->highlight_part - 1].is_pos == false) { - axis_order[gz->highlight_part - 1].depth = FLT_MAX; - } - } - qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float); - static const float axis_highlight[4] = {1, 1, 1, 1}; - static const float axis_black[4] = {0, 0, 0, 1}; - static float axis_color[3][4]; + /* When the cursor is over any of the gizmos (show circle backdrop). */ + const bool is_active = ((gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0); - const float axis_depth_bias = 0.01f; - const float sphere_scale = 1.15f; - /* TODO(fclem): Is there a way to get the widget radius? */ - const float widget_pix_size = 40.0f * U.dpi_fac; + /* Background color of the View3D, used to mix colors. */ + float view_color[4]; + ED_view3d_background_color_get(CTX_data_scene(C), CTX_wm_view3d(C), view_color); + view_color[3] = 1.0f; + + float matrix_screen[4][4]; + float matrix_unit[4][4]; + unit_m4(matrix_unit); + WM_gizmo_calc_matrix_final_params(gz, + &((struct WM_GizmoMatrixParams){ + .matrix_offset = matrix_unit, + }), + matrix_screen); + GPU_matrix_push(); + GPU_matrix_mul(matrix_screen); + + GPUVertFormat *format = immVertexFormat(); + const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + const uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + + static float axis_color[3][4]; -#ifdef USE_AXIS_FONT struct { float matrix[4][4]; float matrix_m3[3][3]; @@ -252,38 +129,29 @@ static void axis_geom_draw(const wmGizmo *gz, int id; } font; - if (select == false) { - font.id = blf_mono_font; - BLF_disable(font.id, BLF_ROTATION | BLF_SHADOW | BLF_MATRIX | BLF_ASPECT | BLF_WORD_WRAP); - BLF_color4fv(font.id, axis_black); - BLF_size(font.id, 12 * U.dpi_fac, 72); - - /* The view matrix is used to position the text. */ - BLF_position(font.id, 0, 0, 0); - - /* Calculate the inverse of the (matrix_final * matrix_offset). - * This allows us to use the final location, while reversing the rotation so fonts - * show without any rotation. */ - float m3[3][3]; - float m3_offset[3][3]; - copy_m3_m4(m3, draw_info->matrix_final); - copy_m3_m4(m3_offset, gz->matrix_offset); - mul_m3_m3m3(m3, m3, m3_offset); - copy_m3_m3(font.matrix_m3_invert, m3); - invert_m3(m3); - copy_m3_m3(font.matrix_m3, m3); - copy_m4_m3(font.matrix, m3); - } -#endif - - /* When the cursor is over any of the gizmos (show circle backdrop). */ - const bool is_active = (color[3] != 0.0f); - - const float clip_range = gz->scale_final * sphere_scale; - bool use_project_matrix = (clip_range >= -GPU_MATRIX_ORTHO_CLIP_NEAR_DEFAULT); + font.id = BLF_default(); + BLF_disable(font.id, BLF_ROTATION | BLF_SHADOW | BLF_MATRIX | BLF_ASPECT | BLF_WORD_WRAP); + BLF_enable(font.id, BLF_BOLD); + BLF_size(font.id, AXIS_TEXT_SIZE, 72); + BLF_position(font.id, 0, 0, 0); + + /* Calculate the inverse of the (matrix_final * matrix_offset). + * This allows us to use the final location, while reversing the rotation so fonts + * show without any rotation. */ + float m3[3][3]; + float m3_offset[3][3]; + copy_m3_m4(m3, matrix_screen); + copy_m3_m4(m3_offset, gz->matrix_offset); + mul_m3_m3m3(m3, m3, m3_offset); + copy_m3_m3(font.matrix_m3_invert, m3); + invert_m3(m3); + copy_m3_m3(font.matrix_m3, m3); + copy_m4_m3(font.matrix, m3); + + bool use_project_matrix = (gz->scale_final >= -GPU_MATRIX_ORTHO_CLIP_NEAR_DEFAULT); if (use_project_matrix) { GPU_matrix_push_projection(); - GPU_matrix_ortho_set_z(-clip_range, clip_range); + GPU_matrix_ortho_set_z(-gz->scale_final, gz->scale_final); } UI_draw_roundbox_corner_set(UI_CNR_ALL); @@ -291,263 +159,161 @@ static void axis_geom_draw(const wmGizmo *gz, /* Circle defining active area. */ if (is_active) { - immUnbindProgram(); - - float rad = widget_pix_size; + const float rad = WIDGET_RADIUS; GPU_matrix_push(); GPU_matrix_scale_1f(1.0f / rad); - - UI_draw_roundbox_4fv(true, -rad, -rad, rad, rad, rad, color); - + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = -rad, + .xmax = rad, + .ymin = -rad, + .ymax = rad, + }, + true, + rad, + gz->color_hi); GPU_matrix_pop(); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); } - GPU_matrix_push(); GPU_matrix_mul(gz->matrix_offset); for (int axis_index = 0; axis_index < ARRAY_SIZE(axis_order); axis_index++) { const int index = axis_order[axis_index].index; const int axis = axis_order[axis_index].axis; const bool is_pos = axis_order[axis_index].is_pos; - const bool is_highlight = index + 1 == gz->highlight_part; + const float depth = axis_order[axis_index].depth; + const bool is_behind = (depth <= (AXIS_DEPTH_BIAS * (is_pos ? -1 : 1))); + bool is_aligned_front = (axis_align != -1 && axis_align == axis && !is_behind); + bool is_aligned_back = (axis_align != -1 && axis_align == axis && is_behind); + + const float v[3] = {0, 0, (1.0f - AXIS_HANDLE_SIZE) * (is_pos ? 1 : -1)}; + const float v_final[3] = {v[(axis + 2) % 3], v[(axis + 1) % 3], v[axis]}; + + bool is_highlight = index + 1 == gz->highlight_part; + /* Check if highlight part is the other side when axis aligned. */ + if (is_aligned_front && (axis_order[axis_index].axis_opposite + 1 == gz->highlight_part)) { + is_highlight = true; + } UI_GetThemeColor3fv(TH_AXIS_X + axis, axis_color[axis]); axis_color[axis][3] = 1.0f; - const int index_z = axis; - const int index_y = (axis + 1) % 3; - const int index_x = (axis + 2) % 3; - - bool ok = true; - - /* Skip view align axis when selecting (allows to switch to opposite side). */ - if (select && ((axis_align == axis) && (gz->matrix_offset[axis][2] > 0.0f) == is_pos)) { - ok = false; + /* Color that is full at front, but 50% view background when in back. */ + float fading_color[4]; + interp_v4_v4v4(fading_color, view_color, axis_color[axis], ((depth + 1) * 0.25) + 0.5); + + /* Color that is midway between front and back. */ + float middle_color[4]; + interp_v4_v4v4(middle_color, view_color, axis_color[axis], 0.75f); + + GPU_blend(GPU_BLEND_ALPHA); + + /* Axis Line. */ + if (is_pos || axis_align != -1) { + + /* Extend slightly to meet better at the center. */ + float v_start[3] = {0.0f, 0.0f, 0.0f}; + mul_v3_v3fl(v_start, v_final, -(AXIS_LINE_WIDTH / WIDGET_RADIUS * 0.66f)); + + /* Decrease length of line by ball radius. */ + float v_end[3] = {0.0f, 0.0f, 0.0f}; + mul_v3_v3fl(v_end, v_final, 1.0f - AXIS_HANDLE_SIZE); + + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR); + immUniform2fv("viewportSize", &viewport_size[2]); + immUniform1f("lineWidth", AXIS_LINE_WIDTH); + immBegin(GPU_PRIM_LINES, 2); + immAttr4fv(color_id, middle_color); + immVertex3fv(pos_id, v_start); + immAttr4fv(color_id, fading_color); + immVertex3fv(pos_id, v_end); + immEnd(); + immUnbindProgram(); } - if (ok) { - /* Check aligned, since the front axis won't display in this case, - * and we want to make sure all 3 axes have a character at all times. */ - const bool show_axis_char = (is_pos || (axis == axis_align)); - const float v[3] = {0, 0, AXIS_HANDLE_OFFSET * (is_pos ? 1 : -1)}; - const float v_final[3] = {v[index_x], v[index_y], v[index_z]}; - const float *color_current = is_highlight ? axis_highlight : axis_color[axis]; - float color_current_fade[4]; - - /* Flip the faded state when axis aligned, since we're hiding the front-mode axis - * otherwise we see the color for the back-most axis, which is useful for - * click-to-rotate 180d but not useful to visualize. - * - * Use depth bias so axis-aligned views show the positive axis as being in-front. - * This is a detail so primary axes show as dominant. - */ - const bool is_pos_color = (axis_order[axis_index].depth > - (axis_depth_bias * (is_pos ? -1 : 1))); - - if (select == false) { -#ifdef USE_FADE_BACKGROUND - interp_v3_v3v3( - color_current_fade, draw_info->color_bg, color_current, is_highlight ? 1.0 : 0.5f); - color_current_fade[3] = color_current[3]; -#else - copy_v4_v4(color_current_fade, color_current); - color_current_fade[3] *= 0.2; -#endif - } - else { - copy_v4_fl(color_current_fade, 1.0f); - } - - /* Axis Line. */ - if (is_pos) { - float v_start[3]; - immUnbindProgram(); - - GPU_blend(GPU_BLEND_ALPHA); - - immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); - immUniform2fv("viewportSize", &viewport[2]); - immUniform1f("lineWidth", 2.0f * U.pixelsize); - immUniformColor4fv(is_pos_color ? color_current : color_current_fade); - immBegin(GPU_PRIM_LINES, 2); - if (axis_align == -1) { - zero_v3(v_start); + /* Axis Ball. */ + if (!is_aligned_back) { + float *inner_color = fading_color; + float *outline_color = fading_color; + float negative_color[4]; + if (!is_pos) { + if (is_aligned_front) { + interp_v4_v4v4( + negative_color, (float[4]){1.0f, 1.0f, 1.0f, 1.0f}, axis_color[axis], 0.5f); + negative_color[3] = MIN2(depth + 1, 1.0f); + outline_color = negative_color; } else { - /* When axis aligned we don't draw the front most axis - * (allowing us to switch to the opposite side). - * In this case don't draw lines over axis pointing away from us - * because it obscures character and looks noisy. - */ - mul_v3_v3fl(v_start, v_final, 0.3f); + interp_v4_v4v4(negative_color, view_color, axis_color[axis], 0.25f); + negative_color[3] = MIN2(depth + 1, 1.0f); + inner_color = negative_color; } - immVertex3fv(pos_id, v_start); - immVertex3fv(pos_id, v_final); - immEnd(); - - immUnbindProgram(); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); } - /* Axis Ball. */ -#ifdef USE_AXIS_FONT - if (select == false) { - immUnbindProgram(); - - GPU_matrix_push(); - GPU_matrix_translate_3fv(v_final); - GPU_matrix_mul(font.matrix); - - float rad = widget_pix_size * (is_pos ? AXIS_HANDLE_SIZE_FG : AXIS_HANDLE_SIZE_BG); - - /* Black outlines for negative axis balls, otherwise they can be hard to see since - * they use a faded color which can be similar to the circle backdrop in tone. */ - if (is_active && !is_highlight && !is_pos && !select && !(axis_align == axis)) { - static const float axis_black_faded[4] = {0.0f, 0.0f, 0.0f, 0.2f}; - float outline = rad * sphere_scale; - UI_draw_roundbox_4fv( - true, -outline, -outline, outline, outline, outline, axis_black_faded); - } - - const float *col = is_pos_color ? color_current : color_current_fade; - UI_draw_roundbox_4fv(true, -rad, -rad, rad, rad, rad, col); - - GPU_matrix_pop(); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - } - else -#endif - { - GPU_matrix_push(); - GPU_matrix_translate_3fv(v_final); - GPU_matrix_scale_1f(is_pos ? AXIS_HANDLE_SIZE_FG : AXIS_HANDLE_SIZE_BG); - - GPUBatch *sphere = GPU_batch_preset_sphere(0); - GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR); - - /* Black outlines for negative axis balls, otherwise they can be hard to see since - * they use a faded color which can be similar to the circle backdrop in tone. */ - if (is_active && !is_highlight && !is_pos && !select && !(axis_align == axis)) { - static const float axis_black_faded[4] = {0, 0, 0, 0.2f}; - GPU_matrix_scale_1f(sphere_scale); - GPU_batch_uniform_4fv(sphere, "color", axis_black_faded); - GPU_batch_draw(sphere); - GPU_matrix_scale_1f(1.0 / sphere_scale); - } + GPU_matrix_push(); + GPU_matrix_translate_3fv(v_final); + GPU_matrix_mul(font.matrix); + /* Size change from back to front: 0.92f - 1.08f. */ + float scale = ((depth + 1) * 0.08f) + 0.92f; + const float rad = WIDGET_RADIUS * AXIS_HANDLE_SIZE * scale; + UI_draw_roundbox_4fv_ex( + &(const rctf){ + .xmin = -rad, + .xmax = rad, + .ymin = -rad, + .ymax = rad, + }, + inner_color, + NULL, + 0.0f, + outline_color, + AXIS_RING_WIDTH, + rad); + GPU_matrix_pop(); + } - GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR); - GPU_batch_uniform_4fv(sphere, "color", is_pos_color ? color_current : color_current_fade); - GPU_batch_draw(sphere); - GPU_matrix_pop(); + /* Axis XYZ Character. */ + if ((is_pos || is_highlight || (axis == axis_align)) && !is_aligned_back) { + float axis_str_width, axis_string_height; + char axis_str[3] = {'X' + axis, 0, 0}; + if (!is_pos) { + axis_str[0] = '-'; + axis_str[1] = 'X' + axis; } - - /* Axis XYZ Character. */ - if (show_axis_char && (select == false)) { -#ifdef USE_AXIS_FONT - float axis_str_size[2] = {0}; - const char axis_str[2] = {'X' + axis, 0}; - BLF_width_and_height(font.id, axis_str, 2, &axis_str_size[0], &axis_str_size[1]); - - /* Calculate pixel aligned location, without this text draws fuzzy. */ - float v_final_px[3]; - mul_v3_m3v3(v_final_px, font.matrix_m3_invert, v_final); - /* Center the test and pixel align, it's important to round once - * otherwise the characters are noticeably not-centered. - * If this wasn't an issue we could use #BLF_position to place the text. */ - v_final_px[0] = roundf(v_final_px[0] - (axis_str_size[0] / 2.0f)); - v_final_px[1] = roundf(v_final_px[1] - (axis_str_size[1] / 2.0f)); - mul_m3_v3(font.matrix_m3, v_final_px); - - immUnbindProgram(); - - GPU_matrix_push(); - GPU_matrix_translate_3fv(v_final_px); - GPU_matrix_mul(font.matrix); - - BLF_draw_ascii(font.id, axis_str, 2); - GPU_blend(GPU_BLEND_ALPHA); /* XXX, blf disables */ - GPU_matrix_pop(); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); -#else - immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - GPU_line_width(1.0f); - float m3[3][3]; - copy_m3_m4(m3, gz->matrix_offset); - immUniformColor4fv(axis_black); - draw_xyz_wire(pos_id, m3, v_final, 1.0, axis); - immUnbindProgram(); -#endif + BLF_width_and_height(font.id, axis_str, 3, &axis_str_width, &axis_string_height); + + /* Calculate pixel-aligned location, without this text draws fuzzy. */ + float v_final_px[3]; + mul_v3_m3v3(v_final_px, font.matrix_m3_invert, v_final); + /* Center the text and pixel align, it's important to round once + * otherwise the characters are noticeably not-centered. + * If this wasn't an issue we could use #BLF_position to place the text. */ + v_final_px[0] = roundf(v_final_px[0] - (axis_str_width * (is_pos ? 0.5f : 0.55f))); + v_final_px[1] = roundf(v_final_px[1] - (axis_string_height / 2.0f)); + mul_m3_v3(font.matrix_m3, v_final_px); + GPU_matrix_push(); + GPU_matrix_translate_3fv(v_final_px); + GPU_matrix_mul(font.matrix); + float text_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + if (!is_highlight) { + zero_v4(text_color); + text_color[3] = is_active ? 1.0f : 0.9f; } + BLF_color4fv(font.id, text_color); + BLF_draw_ascii(font.id, axis_str, 2); + GPU_matrix_pop(); } } - GPU_matrix_pop(); - immUnbindProgram(); - if (use_project_matrix) { GPU_matrix_pop_projection(); } -} - -static void axis3d_draw_intern(const bContext *C, - wmGizmo *gz, - const bool select, - const bool highlight) -{ - const float *color = highlight ? gz->color_hi : gz->color; - float matrix_final[4][4]; - float matrix_unit[4][4]; - - unit_m4(matrix_unit); - - WM_gizmo_calc_matrix_final_params(gz, - &((struct WM_GizmoMatrixParams){ - .matrix_offset = matrix_unit, - }), - matrix_final); - - GPU_matrix_push(); - GPU_matrix_mul(matrix_final); - - struct AxisDrawInfo draw_info; -#ifdef USE_AXIS_FONT - if (select == false) { - copy_m4_m4(draw_info.matrix_final, matrix_final); - } -#endif -#ifdef USE_FADE_BACKGROUND - if (select == false) { - ED_view3d_background_color_get(CTX_data_scene(C), CTX_wm_view3d(C), draw_info.color_bg); - } -#else - UNUSED_VARS(C); -#endif - - GPU_blend(GPU_BLEND_ALPHA); - axis_geom_draw(gz, color, select, &draw_info); GPU_blend(GPU_BLEND_NONE); + BLF_disable(font.id, BLF_BOLD); GPU_matrix_pop(); } -static void gizmo_axis_draw(const bContext *C, wmGizmo *gz) -{ - const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL; - const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0; - - (void)is_modal; - - GPU_blend(GPU_BLEND_ALPHA); - axis3d_draw_intern(C, gz, false, is_highlight); - GPU_blend(GPU_BLEND_NONE); -} - static int gizmo_axis_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mval[2]) { float point_local[2] = {UNPACK2(mval)}; @@ -601,12 +367,19 @@ static int gizmo_axis_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mv return -1; } -static int gizmo_axis_cursor_get(wmGizmo *gz) +static int gizmo_axis_cursor_get(wmGizmo *UNUSED(gz)) { - if (gz->highlight_part > 0) { - return WM_CURSOR_EDIT; - } - return WM_CURSOR_NSEW_SCROLL; + return WM_CURSOR_DEFAULT; +} + +static void gizmo_axis_screen_bounds_get(bContext *C, wmGizmo *gz, rcti *r_bounding_box) +{ + ScrArea *area = CTX_wm_area(C); + const float rad = WIDGET_RADIUS; + r_bounding_box->xmin = gz->matrix_basis[3][0] + area->totrct.xmin - rad; + r_bounding_box->ymin = gz->matrix_basis[3][1] + area->totrct.ymin - rad; + r_bounding_box->xmax = r_bounding_box->xmin + rad; + r_bounding_box->ymax = r_bounding_box->ymin + rad; } void VIEW3D_GT_navigate_rotate(wmGizmoType *gzt) @@ -618,6 +391,7 @@ void VIEW3D_GT_navigate_rotate(wmGizmoType *gzt) gzt->draw = gizmo_axis_draw; gzt->test_select = gizmo_axis_test_select; gzt->cursor_get = gizmo_axis_cursor_get; + gzt->screen_bounds_get = gizmo_axis_screen_bounds_get; gzt->struct_size = sizeof(wmGizmo); } diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c index 3f07653fb2f..171cf721343 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c @@ -30,7 +30,6 @@ #include "UI_resources.h" #include "WM_api.h" -#include "WM_toolsystem.h" #include "WM_types.h" #include "view3d_intern.h" /* own include */ diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index f2e42cd1725..607ca110d0f 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -40,14 +40,11 @@ #include "DEG_depsgraph.h" #include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_types.h" #include "ED_mesh.h" -#include "ED_screen.h" #include "ED_undo.h" #include "UI_interface.h" diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 0770bac1313..344168e895b 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -24,7 +24,6 @@ #include <math.h> #include <stdlib.h> -#include "DNA_collection_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -36,7 +35,6 @@ #include "BKE_appdir.h" #include "BKE_blender_copybuffer.h" -#include "BKE_collection.h" #include "BKE_context.h" #include "BKE_main.h" #include "BKE_report.h" @@ -49,7 +47,6 @@ #include "ED_outliner.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "ED_transform.h" #include "view3d_intern.h" diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 35ec4de5077..0605ea30806 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -596,7 +596,7 @@ static bool do_lasso_select_objects(ViewContext *vc, } for (base = vc->view_layer->object_bases.first; base; base = base->next) { - if (BASE_SELECTABLE(v3d, base)) { /* use this to avoid un-needed lasso lookups */ + if (BASE_SELECTABLE(v3d, base)) { /* Use this to avoid unnecessary lasso look-ups. */ const bool is_select = base->flag & BASE_SELECTED; const bool is_inside = ((ED_view3d_project_base(vc->region, base) == V3D_PROJ_RET_OK) && BLI_lasso_is_point_inside( @@ -1447,7 +1447,7 @@ static const EnumPropertyItem *object_select_menu_enum_itemf(bContext *C, int totitem = 0; int i = 0; - /* don't need context but avoid docgen using this */ + /* Don't need context but avoid API doc-generation using this. */ if (C == NULL || object_mouse_select_menu_data[i].idname[0] == '\0') { return DummyRNA_NULL_items; } @@ -2494,8 +2494,7 @@ static int view3d_select_exec(bContext *C, wmOperator *op) } /* Pass-through allows tweaks - * FINISHED to signal one operator worked - * */ + * FINISHED to signal one operator worked */ if (retval) { WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 148a0986c5c..cce9287679c 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -27,7 +27,6 @@ #include "DNA_object_types.h" #include "BLI_array.h" -#include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index 2b7b8255068..a6a77ecd5f7 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -224,13 +224,11 @@ void view3d_region_operator_needs_opengl(wmWindow *UNUSED(win), ARegion *region) */ void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist) { - float viewdist; - if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) { return; } - viewdist = rv3d->dist; + float viewdist = rv3d->dist; /* special exception for ortho camera (viewdist isnt used for perspective cameras) */ if (dist != 0.0f) { @@ -248,7 +246,6 @@ bool ED_view3d_context_activate(bContext *C) { bScreen *screen = CTX_wm_screen(C); ScrArea *area = CTX_wm_area(C); - ARegion *region; /* area can be NULL when called from python */ if (area == NULL || area->spacetype != SPACE_VIEW3D) { @@ -259,7 +256,7 @@ bool ED_view3d_context_activate(bContext *C) return false; } - region = BKE_area_find_region_active_win(area); + ARegion *region = BKE_area_find_region_active_win(area); if (region == NULL) { return false; } @@ -282,9 +279,7 @@ void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip) { - int val; - - for (val = 0; val < 4; val++) { + for (int val = 0; val < 4; val++) { normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]); if (UNLIKELY(is_flip)) { negate_v3(clip[val]); @@ -752,14 +747,12 @@ bool ED_view3d_camera_lock_autokey(View3D *v3d, static void view3d_boxview_clip(ScrArea *area) { - ARegion *region; BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb"); float clip[6][4]; float x1 = 0.0f, y1 = 0.0f, z1 = 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f}; - int val; /* create bounding box */ - for (region = area->regionbase.first; region; region = region->next) { + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->regiontype == RGN_TYPE_WINDOW) { RegionView3D *rv3d = region->regiondata; @@ -794,7 +787,7 @@ static void view3d_boxview_clip(ScrArea *area) } } - for (val = 0; val < 8; val++) { + for (int val = 0; val < 8; val++) { if (ELEM(val, 0, 3, 4, 7)) { bb->vec[val][0] = -x1 - ofs[0]; } @@ -826,12 +819,12 @@ static void view3d_boxview_clip(ScrArea *area) normal_tri_v3(clip[5], bb->vec[0], bb->vec[2], bb->vec[1]); /* then plane equations */ - for (val = 0; val < 6; val++) { + for (int val = 0; val < 6; val++) { clip[val][3] = -dot_v3v3(clip[val], bb->vec[val % 5]); } /* create bounding box */ - for (region = area->regionbase.first; region; region = region->next) { + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->regiontype == RGN_TYPE_WINDOW) { RegionView3D *rv3d = region->regiondata; @@ -950,11 +943,10 @@ void ED_view3d_quadview_update(ScrArea *area, ARegion *region, bool do_clip) { ARegion *region_sync = NULL; RegionView3D *rv3d = region->regiondata; - short viewlock; /* this function copies flags from the first of the 3 other quadview * regions to the 2 other, so it assumes this is the region whose * properties are always being edited, weak */ - viewlock = rv3d->viewlock; + short viewlock = rv3d->viewlock; if ((viewlock & RV3D_LOCK_ROTATION) == 0) { do_clip = (viewlock & RV3D_BOXCLIP) != 0; @@ -1015,10 +1007,7 @@ void ED_view3d_quadview_update(ScrArea *area, ARegion *region, bool do_clip) static float view_autodist_depth_margin(ARegion *region, const int mval[2], int margin) { - ViewDepths depth_temp = {0}; rcti rect; - float depth_close; - if (margin == 0) { /* Get Z Depths, needed for perspective, nice for ortho */ rect.xmin = mval[0]; @@ -1030,8 +1019,9 @@ static float view_autodist_depth_margin(ARegion *region, const int mval[2], int BLI_rcti_init_pt_radius(&rect, mval, margin); } + ViewDepths depth_temp = {0}; view3d_update_depths_rect(region, &depth_temp, &rect); - depth_close = view3d_depth_near(&depth_temp); + float depth_close = view3d_depth_near(&depth_temp); MEM_SAFE_FREE(depth_temp.depths); return depth_close; } @@ -1053,14 +1043,13 @@ bool ED_view3d_autodist(Depsgraph *depsgraph, { float depth_close; int margin_arr[] = {0, 2, 4}; - int i; bool depth_ok = false; /* Get Z Depths, needed for perspective, nice for ortho */ ED_view3d_draw_depth(depsgraph, region, v3d, alphaoverride); /* Attempt with low margin's first */ - i = 0; + int i = 0; do { depth_close = view_autodist_depth_margin(region, mval, margin_arr[i++] * U.pixelsize); depth_ok = (depth_close != FLT_MAX); @@ -1104,9 +1093,8 @@ bool ED_view3d_autodist_simple(ARegion *region, int margin, const float *force_depth) { - float depth; - /* Get Z Depths, needed for perspective, nice for ortho */ + float depth; if (force_depth) { depth = *force_depth; } @@ -1237,7 +1225,6 @@ float ED_view3d_radius_to_dist(const View3D *v3d, } else { float lens, sensor_size, zoom; - float angle; if (persp == RV3D_CAMOB) { CameraParams params; @@ -1259,7 +1246,7 @@ float ED_view3d_radius_to_dist(const View3D *v3d, zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; } - angle = focallength_to_fov(lens, sensor_size); + float angle = focallength_to_fov(lens, sensor_size); /* zoom influences lens, correct this by scaling the angle as a distance * (by the zoom-level) */ @@ -1319,14 +1306,13 @@ float ED_view3d_offset_distance(const float mat[4][4], { float pos[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float dir[4] = {0.0f, 0.0f, 1.0f, 0.0f}; - float dist; mul_m4_v4(mat, pos); add_v3_v3(pos, ofs); mul_m4_v4(mat, dir); normalize_v3(dir); - dist = dot_v3v3(pos, dir); + float dist = dot_v3v3(pos, dir); if ((dist < FLT_EPSILON) && (fallback_dist != 0.0f)) { dist = fallback_dist; diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 9d947384bf0..5c0ca1582a6 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -142,7 +142,7 @@ void ED_view3d_smooth_view_ex( /* initialize sms */ view3d_smooth_view_state_backup(&sms.dst, v3d, rv3d); view3d_smooth_view_state_backup(&sms.src, v3d, rv3d); - /* if smoothview runs multiple times... */ + /* If smooth-view runs multiple times. */ if (rv3d->sms == NULL) { view3d_smooth_view_state_backup(&sms.org, v3d, rv3d); } @@ -396,7 +396,7 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *region, b /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636, * when switching camera in quad-view the other ortho views would zoom & reset. * - * For now only redraw all regions when smoothview finishes. + * For now only redraw all regions when smooth-view finishes. */ if (step >= 1.0f) { WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); @@ -423,7 +423,7 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w } /** - * Apply the smoothview immediately, use when we need to start a new view operation. + * Apply the smooth-view immediately, use when we need to start a new view operation. * (so we don't end up half-applying a view operation when pressing keys quickly). */ void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *region) diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 5b42f221c80..cbd65e3175d 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -48,7 +48,7 @@ #include "ED_space_api.h" #include "ED_transform_snap_object_context.h" -#include "PIL_time.h" /* smoothview */ +#include "PIL_time.h" /* Smooth-view. */ #include "UI_interface.h" #include "UI_resources.h" @@ -872,7 +872,7 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) /* delta time */ t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); - /* reduce the veolocity, if JUMP wasn't hold for long enough */ + /* Reduce the velocity, if JUMP wasn't hold for long enough. */ t = min_ff(t, JUMP_TIME_MAX); walk->speed_jump = JUMP_SPEED_MIN + t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX; diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index faed8abb202..b0bc5c6abda 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -55,6 +55,7 @@ set(SRC transform_convert_nla.c transform_convert_node.c transform_convert_object.c + transform_convert_object_texspace.c transform_convert_paintcurve.c transform_convert_particle.c transform_convert_sculpt.c diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 2a7c247ff2b..2fbcbe22349 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -135,7 +135,7 @@ void setTransformViewAspect(TransInfo *t, float r_aspect[3]) } } else if (t->spacetype == SPACE_GRAPH) { - /* depemds on context of usage */ + /* Depends on context of usage. */ } } @@ -440,7 +440,7 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) } else { /* Do we need more refined tags? */ - if (t->flag & T_POSE) { + if (t->options & CTX_POSE_BONE) { WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); } else { @@ -471,7 +471,7 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) } else if (t->spacetype == SPACE_SEQ) { WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL); - /* Keyframes on strips has been moved, so make sure related editos are informed. */ + /* Key-frames on strips has been moved, so make sure related editors are informed. */ WM_event_add_notifier(C, NC_ANIMATION, NULL); } else if (t->spacetype == SPACE_IMAGE) { @@ -484,7 +484,7 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) wmWindow *window = CTX_wm_window(C); WM_paint_cursor_tag_redraw(window, t->region); } - else if (t->flag & T_CURSOR) { + else if (t->options & CTX_CURSOR) { ED_area_tag_redraw(t->area); } else { @@ -695,6 +695,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""}, {TFM_MODAL_AUTOCONSTRAINT, "AUTOCONSTRAIN", 0, "Automatic Constraint", ""}, {TFM_MODAL_AUTOCONSTRAINTPLANE, "AUTOCONSTRAINPLANE", 0, "Automatic Constraint Plane", ""}, + {TFM_MODAL_PRECISION, "PRECISION", 0, "Precision Mode", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -806,8 +807,6 @@ int transformEvent(TransInfo *t, const wmEvent *event) const int modifiers_prev = t->modifiers; const int mode_prev = t->mode; - t->redraw |= handleMouseInput(t, &t->mouse, event); - /* Handle modal numinput events first, if already activated. */ if (((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) && hasNumInput(&t->num) && handleNumInput(t->context, &(t->num), event)) { @@ -895,7 +894,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case TFM_MODAL_ROTATE: /* only switch when... */ - if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { + if (!(t->options & CTX_TEXTURE_SPACE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { if (transform_mode_is_changeable(t->mode)) { restoreTransObjects(t); resetTransModal(t); @@ -1069,7 +1068,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) t->modifiers &= ~(MOD_CONSTRAINT_SELECT | MOD_CONSTRAINT_PLANE); } else { - if (t->flag & T_CAMERA) { + if (t->options & CTX_CAMERA) { /* Exception for switching to dolly, or trackball, in camera view. */ if (t->mode == TFM_TRANSLATION) { setLocalConstraint(t, (CON_AXIS2), TIP_("along local Z")); @@ -1095,6 +1094,19 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } break; + case TFM_MODAL_PRECISION: + if (event->prevval == KM_PRESS) { + t->modifiers |= MOD_PRECISION; + /* Shift is modifier for higher precision transform. */ + t->mouse.precision = 1; + t->redraw |= TREDRAW_HARD; + } + else if (event->prevval == KM_RELEASE) { + t->modifiers &= ~MOD_PRECISION; + t->mouse.precision = 0; + t->redraw |= TREDRAW_HARD; + } + break; /* Those two are only handled in transform's own handler, see T44634! */ case TFM_MODAL_EDGESLIDE_UP: case TFM_MODAL_EDGESLIDE_DOWN: @@ -1249,7 +1261,7 @@ bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], floa createTransData(C, t); /* make TransData structs from selection */ - t->around = centerMode; /* override userdefined mode */ + t->around = centerMode; /* override user-defined mode. */ if (t->data_len_all == 0) { success = false; @@ -1382,7 +1394,7 @@ static void drawTransformPixel(const struct bContext *C, ARegion *region, void * */ if ((U.autokey_flag & AUTOKEY_FLAG_NOWARNING) == 0) { if (region == t->region) { - if (t->flag & (T_OBJECT | T_POSE)) { + if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) { if (ob && autokeyframe_cfra_can_key(scene, &ob->id)) { drawAutoKeyWarning(t, region); } @@ -1652,7 +1664,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if ((prop = RNA_struct_find_property(op->ptr, "texture_space")) && RNA_property_is_set(op->ptr, prop)) { if (RNA_property_boolean_get(op->ptr, prop)) { - options |= CTX_TEXTURE; + options |= CTX_TEXTURE_SPACE; } } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index fff7d47cc5b..24335b6b6b7 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -36,6 +36,11 @@ #include "transform_data.h" +/* use node center for transform instead of upper-left corner. + * disabled since it makes absolute snapping not work so nicely + */ +// #define USE_NODE_CENTER + /* -------------------------------------------------------------------- */ /** \name Types/ * \{ */ @@ -60,6 +65,134 @@ struct wmKeyMap; struct wmOperator; struct wmTimer; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Enums and Flags + * \{ */ + +/** #TransInfo.options */ +typedef enum { + CTX_NONE = 0, + + /* These are similar to TransInfo::data_type. */ + CTX_CAMERA = (1 << 0), + CTX_CURSOR = (1 << 1), + CTX_EDGE_DATA = (1 << 2), + CTX_GPENCIL_STROKES = (1 << 3), + CTX_MASK = (1 << 4), + CTX_MOVIECLIP = (1 << 5), + CTX_OBJECT = (1 << 6), + CTX_PAINT_CURVE = (1 << 7), + CTX_POSE_BONE = (1 << 8), + CTX_TEXTURE_SPACE = (1 << 9), + + CTX_NO_PET = (1 << 10), + CTX_NO_MIRROR = (1 << 11), + CTX_AUTOCONFIRM = (1 << 12), + /** When transforming object's, adjust the object data so it stays in the same place. */ + CTX_OBMODE_XFORM_OBDATA = (1 << 13), + /** Transform object parents without moving their children. */ + CTX_OBMODE_XFORM_SKIP_CHILDREN = (1 << 14), +} eTContext; + +/** #TransInfo.flag */ +typedef enum { + /** \note We could remove 'T_EDIT' and use 'obedit_type', for now ensure they're in sync. */ + T_EDIT = 1 << 0, + /** Transform points, having no rotation/scale. */ + T_POINTS = 1 << 1, + /** restrictions flags */ + T_NO_CONSTRAINT = 1 << 2, + T_NULL_ONE = 1 << 3, + T_NO_ZERO = 1 << 4, + T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO, + + T_PROP_EDIT = 1 << 5, + T_PROP_CONNECTED = 1 << 6, + T_PROP_PROJECTED = 1 << 7, + T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED, + + T_V3D_ALIGN = 1 << 8, + /** For 2D views such as UV or f-curve. */ + T_2D_EDIT = 1 << 9, + T_CLIP_UV = 1 << 10, + + /** Auto-IK is on. */ + T_AUTOIK = 1 << 11, + + /** Don't use mirror even if the data-block option is set. */ + T_NO_MIRROR = 1 << 12, + + /** To indicate that the value set in the `value` parameter is the final + * value of the transformation, modified only by the constrain. */ + T_INPUT_IS_VALUES_FINAL = 1 << 13, + + /** To specify if we save back settings at the end. */ + T_MODAL = 1 << 14, + + /** No re-topology (projection). */ + T_NO_PROJECT = 1 << 15, + + T_RELEASE_CONFIRM = 1 << 16, + + /** Alternative transformation. used to add offset to tracking markers. */ + T_ALT_TRANSFORM = 1 << 17, + + /** #TransInfo.center has been set, don't change it. */ + T_OVERRIDE_CENTER = 1 << 18, + + T_MODAL_CURSOR_SET = 1 << 19, + + T_CLNOR_REBUILD = 1 << 20, + + /** Merges unselected into selected after transforming (runs after transforming). */ + T_AUTOMERGE = 1 << 21, + /** Runs auto-merge & splits. */ + T_AUTOSPLIT = 1 << 22, +} eTFlag; + +/** #TransInfo.modifiers */ +typedef enum { + MOD_CONSTRAINT_SELECT = 1 << 0, + MOD_PRECISION = 1 << 1, + MOD_SNAP = 1 << 2, + MOD_SNAP_INVERT = 1 << 3, + MOD_CONSTRAINT_PLANE = 1 << 4, +} eTModifier; + +/** #TransSnap.status */ +typedef enum { + SNAP_FORCED = 1 << 0, + TARGET_INIT = 1 << 1, + /* Special flag for snap to grid. */ + TARGET_GRID_INIT = 1 << 2, + POINT_INIT = 1 << 3, + MULTI_POINTS = 1 << 4, +} eTSnap; + +/** #TransCon.mode, #TransInfo.con.mode */ +typedef enum { + /** When set constraints are in use. */ + CON_APPLY = 1 << 0, + /** These are only used for modal execution. */ + CON_AXIS0 = 1 << 1, + CON_AXIS1 = 1 << 2, + CON_AXIS2 = 1 << 3, + CON_SELECT = 1 << 4, + /** Does not reorient vector to face viewport when on. */ + CON_NOFLIP = 1 << 5, + CON_USER = 1 << 6, +} eTConstraint; + +/** #TransInfo.state */ +typedef enum { + TRANS_STARTING = 0, + TRANS_RUNNING = 1, + TRANS_CONFIRM = 2, + TRANS_CANCEL = 3, +} eTState; + /** #TransInfo.redraw */ typedef enum { TREDRAW_NOTHING = 0, @@ -67,6 +200,97 @@ typedef enum { TREDRAW_SOFT = 2, } eRedrawFlag; +/** #TransInfo.helpline */ +typedef enum { + HLP_NONE = 0, + HLP_SPRING = 1, + HLP_ANGLE = 2, + HLP_HARROW = 3, + HLP_VARROW = 4, + HLP_CARROW = 5, + HLP_TRACKBALL = 6, +} eTHelpline; + +typedef enum { + TC_NONE = 0, + TC_ACTION_DATA, + TC_POSE, + TC_ARMATURE_VERTS, + TC_CURSOR_IMAGE, + TC_CURSOR_VIEW3D, + TC_CURVE_VERTS, + TC_GRAPH_EDIT_DATA, + TC_GPENCIL, + TC_LATTICE_VERTS, + TC_MASKING_DATA, + TC_MBALL_VERTS, + TC_MESH_VERTS, + TC_MESH_EDGES, + TC_MESH_SKIN, + TC_MESH_UV, + TC_NLA_DATA, + TC_NODE_DATA, + TC_OBJECT, + TC_OBJECT_TEXSPACE, + TC_PAINT_CURVE_VERTS, + TC_PARTICLE_VERTS, + TC_SCULPT, + TC_SEQ_DATA, + TC_TRACKING_DATA, +} eTConvertType; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Keymap Modal Items + * + * \note these values are saved in key-map files, do not change then but just add new ones. + * \{ */ + +enum { + TFM_MODAL_CANCEL = 1, + TFM_MODAL_CONFIRM = 2, + TFM_MODAL_TRANSLATE = 3, + TFM_MODAL_ROTATE = 4, + TFM_MODAL_RESIZE = 5, + TFM_MODAL_SNAP_INV_ON = 6, + TFM_MODAL_SNAP_INV_OFF = 7, + TFM_MODAL_SNAP_TOGGLE = 8, + TFM_MODAL_AXIS_X = 9, + TFM_MODAL_AXIS_Y = 10, + TFM_MODAL_AXIS_Z = 11, + TFM_MODAL_PLANE_X = 12, + TFM_MODAL_PLANE_Y = 13, + TFM_MODAL_PLANE_Z = 14, + TFM_MODAL_CONS_OFF = 15, + TFM_MODAL_ADD_SNAP = 16, + TFM_MODAL_REMOVE_SNAP = 17, + + /* 18 and 19 used by number-input, defined in `ED_numinput.h`. */ + // NUM_MODAL_INCREMENT_UP = 18, + // NUM_MODAL_INCREMENT_DOWN = 19, + + TFM_MODAL_PROPSIZE_UP = 20, + TFM_MODAL_PROPSIZE_DOWN = 21, + TFM_MODAL_AUTOIK_LEN_INC = 22, + TFM_MODAL_AUTOIK_LEN_DEC = 23, + + TFM_MODAL_EDGESLIDE_UP = 24, + TFM_MODAL_EDGESLIDE_DOWN = 25, + + /** For analog input, like track-pad. */ + TFM_MODAL_PROPSIZE = 26, + /** Node editor insert offset (also called auto-offset) direction toggle. */ + TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27, + + TFM_MODAL_AUTOCONSTRAINT = 28, + TFM_MODAL_AUTOCONSTRAINTPLANE = 29, + + TFM_MODAL_PRECISION = 30, +}; + +/** \} */ + typedef struct TransSnapPoint { struct TransSnapPoint *next, *prev; float co[3]; @@ -82,13 +306,14 @@ typedef struct TransSnap { bool snap_self; bool peel; bool use_backface_culling; - char status; + eTSnap status; /* Snapped Element Type (currently for objects only). */ char snapElem; /** snapping from this point (in global-space). */ float snapPoint[3]; /** to this point (in global-space). */ float snapTarget[3]; + float snapTargetGrid[3]; float snapNormal[3]; char snapNodeBorder; ListBase points; @@ -120,7 +345,7 @@ typedef struct TransCon { * the one in #TransInfo is not guarantee to stay the same (Rotates change it). */ int imval[2]; /** Mode flags of the constraint. */ - int mode; + eTConstraint mode; void (*drawExtra)(struct TransInfo *t); /* Note: if 'tc' is NULL, 'td' must also be NULL. @@ -266,37 +491,45 @@ typedef struct TransInfo { TransDataContainer *data_container; int data_container_len; - /** #eTransConvertType - * TODO: It should be a member of #TransDataContainer. */ - int data_type; - /** Combine length of all #TransDataContainer.data_len * Use to check if nothing is selected or if we have a single selection. */ int data_len_all; - /** Current mode. */ - int mode; + /** TODO: It should be a member of #TransDataContainer. */ + eTConvertType data_type; + + /** Current context/options for transform. */ + eTContext options; /** Generic flags for special behaviors. */ - int flag; + eTFlag flag; /** Special modifiers, by function, not key. */ - int modifiers; + eTModifier modifiers; /** Current state (running, canceled. */ - short state; - /** Current context/options for transform. */ - int options; + eTState state; + /** Redraw flag. */ + eRedrawFlag redraw; + /** Choice of custom cursor with or without a help line from the gizmo to the mouse position. */ + eTHelpline helpline; + /** Current mode. */ + eTfmMode mode; + + /** Main transform mode function. */ void (*transform)(struct TransInfo *, const int[2]); - /** Transform function pointer. */ + /* Event handler function that determines whether the viewport needs to be redrawn. */ eRedrawFlag (*handleEvent)(struct TransInfo *, const struct wmEvent *); - /* event handler function pointer RETURN 1 if redraw is needed */ - /** transformed constraint. */ + + /** Constraint Data. */ TransCon con; + + /** Snap Data. */ TransSnap tsnap; - /** numerical input. */ + + /** Numerical input. */ NumInput num; - /** mouse input. */ + + /** Mouse input. */ MouseInput mouse; - /** redraw flag. */ - eRedrawFlag redraw; + /** proportional circle radius. */ float prop_size; /** proportional falloff text. */ @@ -310,9 +543,6 @@ typedef struct TransInfo { float center_global[3]; /** center in screen coordinates. */ float center2d[2]; - /* Lazy initialize center data for when we need other center values. - * V3D_AROUND_ACTIVE + 1 (static assert checks this) */ - TransCenterData center_cache[5]; /** maximum index on the input vector. */ short idx_max; /** Snapping Gears. */ @@ -333,8 +563,6 @@ typedef struct TransInfo { short around; /** space-type where transforming is. */ char spacetype; - /** Choice of custom cursor with or without a help line from the gizmo to the mouse position. */ - char helpline; /** Avoid looking inside #TransDataContainer.obedit. */ short obedit_type; @@ -422,178 +650,6 @@ typedef struct TransInfo { /** \} */ /* -------------------------------------------------------------------- */ -/** \name Flags - * \{ */ - -/** #TransInfo.state */ -enum { - TRANS_STARTING = 0, - TRANS_RUNNING = 1, - TRANS_CONFIRM = 2, - TRANS_CANCEL = 3, -}; - -/** #TransInfo.flag */ -enum { - T_OBJECT = 1 << 0, - /** \note We could remove 'T_EDIT' and use 'obedit_type', for now ensure they're in sync. */ - T_EDIT = 1 << 1, - T_POSE = 1 << 2, - T_TEXTURE = 1 << 3, - /** Transforming the 3d view. */ - T_CAMERA = 1 << 4, - /** Transforming the 3D cursor. */ - T_CURSOR = 1 << 5, - /** Transform points, having no rotation/scale. */ - T_POINTS = 1 << 6, - /** restrictions flags */ - T_NO_CONSTRAINT = 1 << 7, - T_NULL_ONE = 1 << 8, - T_NO_ZERO = 1 << 9, - T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO, - - T_PROP_EDIT = 1 << 10, - T_PROP_CONNECTED = 1 << 11, - T_PROP_PROJECTED = 1 << 12, - T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED, - - T_V3D_ALIGN = 1 << 13, - /** For 2D views such as UV or f-curve. */ - T_2D_EDIT = 1 << 14, - T_CLIP_UV = 1 << 15, - - /** Auto-IK is on. */ - T_AUTOIK = 1 << 16, - - /** Don't use mirror even if the data-block option is set. */ - T_NO_MIRROR = 1 << 17, - - /** To indicate that the value set in the `value` parameter is the final - * value of the transformation, modified only by the constrain. */ - T_INPUT_IS_VALUES_FINAL = 1 << 18, - - /** To specify if we save back settings at the end. */ - T_MODAL = 1 << 19, - - /** No re-topology (projection). */ - T_NO_PROJECT = 1 << 20, - - T_RELEASE_CONFIRM = 1 << 21, - - /** Alternative transformation. used to add offset to tracking markers. */ - T_ALT_TRANSFORM = 1 << 22, - - /** #TransInfo.center has been set, don't change it. */ - T_OVERRIDE_CENTER = 1 << 23, - - T_MODAL_CURSOR_SET = 1 << 24, - - T_CLNOR_REBUILD = 1 << 25, - - /** Merges unselected into selected after transforming (runs after transforming). */ - T_AUTOMERGE = 1 << 26, - /** Runs auto-merge & splits. */ - T_AUTOSPLIT = 1 << 27, -}; - -/** #TransInfo.modifiers */ -enum { - MOD_CONSTRAINT_SELECT = 1 << 0, - MOD_PRECISION = 1 << 1, - MOD_SNAP = 1 << 2, - MOD_SNAP_INVERT = 1 << 3, - MOD_CONSTRAINT_PLANE = 1 << 4, -}; - -/* use node center for transform instead of upper-left corner. - * disabled since it makes absolute snapping not work so nicely - */ -// #define USE_NODE_CENTER - -/** #TransInfo.helpline */ -enum { - HLP_NONE = 0, - HLP_SPRING = 1, - HLP_ANGLE = 2, - HLP_HARROW = 3, - HLP_VARROW = 4, - HLP_CARROW = 5, - HLP_TRACKBALL = 6, -}; - -/** #TransCon.mode, #TransInfo.con.mode */ -enum { - /** When set constraints are in use. */ - CON_APPLY = 1 << 0, - /** These are only used for modal execution. */ - CON_AXIS0 = 1 << 1, - CON_AXIS1 = 1 << 2, - CON_AXIS2 = 1 << 3, - CON_SELECT = 1 << 4, - /** Does not reorient vector to face viewport when on. */ - CON_NOFLIP = 1 << 5, - CON_USER = 1 << 6, -}; - -/** #TransSnap.status */ -enum { - SNAP_FORCED = 1 << 0, - TARGET_INIT = 1 << 1, - POINT_INIT = 1 << 2, - MULTI_POINTS = 1 << 3, -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Keymap Modal Items - * - * \note these values are saved in key-map files, do not change then but just add new ones. - * \{ */ - -enum { - TFM_MODAL_CANCEL = 1, - TFM_MODAL_CONFIRM = 2, - TFM_MODAL_TRANSLATE = 3, - TFM_MODAL_ROTATE = 4, - TFM_MODAL_RESIZE = 5, - TFM_MODAL_SNAP_INV_ON = 6, - TFM_MODAL_SNAP_INV_OFF = 7, - TFM_MODAL_SNAP_TOGGLE = 8, - TFM_MODAL_AXIS_X = 9, - TFM_MODAL_AXIS_Y = 10, - TFM_MODAL_AXIS_Z = 11, - TFM_MODAL_PLANE_X = 12, - TFM_MODAL_PLANE_Y = 13, - TFM_MODAL_PLANE_Z = 14, - TFM_MODAL_CONS_OFF = 15, - TFM_MODAL_ADD_SNAP = 16, - TFM_MODAL_REMOVE_SNAP = 17, - - /* 18 and 19 used by number-input, defined in `ED_numinput.h`. */ - // NUM_MODAL_INCREMENT_UP = 18, - // NUM_MODAL_INCREMENT_DOWN = 19, - - TFM_MODAL_PROPSIZE_UP = 20, - TFM_MODAL_PROPSIZE_DOWN = 21, - TFM_MODAL_AUTOIK_LEN_INC = 22, - TFM_MODAL_AUTOIK_LEN_DEC = 23, - - TFM_MODAL_EDGESLIDE_UP = 24, - TFM_MODAL_EDGESLIDE_DOWN = 25, - - /** For analog input, like track-pad. */ - TFM_MODAL_PROPSIZE = 26, - /** Node editor insert offset (also called auto-offset) direction toggle. */ - TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27, - - TFM_MODAL_AUTOCONSTRAINT = 28, - TFM_MODAL_AUTOCONSTRAINTPLANE = 29, -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Public Transform API * \{ */ @@ -666,9 +722,6 @@ typedef enum { void initMouseInput( TransInfo *t, MouseInput *mi, const float center[2], const int mval[2], const bool precision); void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode); -eRedrawFlag handleMouseInput(struct TransInfo *t, - struct MouseInput *mi, - const struct wmEvent *event); void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], @@ -684,10 +737,6 @@ void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float val /** \name Generics * \{ */ -void initTransDataContainers_FromObjectData(TransInfo *t, - struct Object *obact, - struct Object **objects, - uint objects_len); void initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, @@ -709,7 +758,6 @@ void recalcData(TransInfo *t); void calculateCenter2D(TransInfo *t); void calculateCenterLocal(TransInfo *t, const float center_global[3]); -const TransCenterData *transformCenter_from_type(TransInfo *t, int around); void calculateCenter(TransInfo *t); /* API functions for getting center points */ @@ -724,6 +772,8 @@ void calculatePropRatio(TransInfo *t); void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot); +struct Object *transform_object_deform_pose_armature_get(const TransInfo *t, struct Object *ob); + void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data); /* TODO. transform_query.c */ diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 2ac7e41a7c9..1f589a830fc 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -58,6 +58,10 @@ static void drawObjectConstraint(TransInfo *t); +/* -------------------------------------------------------------------- */ +/** \name Internal Utilities + * \{ */ + static void projection_matrix_calc(const TransInfo *t, float r_pmtx[3][3]) { unit_m3(r_pmtx); @@ -380,14 +384,13 @@ static void planeProjection(const TransInfo *t, const float in[3], float out[3]) add_v3_v3v3(out, in, vec); } -/* +/** * Generic callback for constant spatial constraints applied to linear motion * - * The IN vector in projected into the constrained space and then further + * The `in` vector in projected into the constrained space and then further * projected along the view vector. * (in perspective mode, the view vector is relative to the position on screen) */ - static void applyAxisConstraintVec( TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, const float in[3], float out[3]) { @@ -459,17 +462,16 @@ static void applyAxisConstraintVec( } } -/* +/** * Generic callback for object based spatial constraints applied to linear motion * * At first, the following is applied without orientation * The IN vector in projected into the constrained space and then further * projected along the view vector. - * (in perspective mode, the view vector is relative to the position on screen) + * (in perspective mode, the view vector is relative to the position on screen). * * Further down, that vector is mapped to each data's space. */ - static void applyObjectConstraintVec( TransInfo *t, TransDataContainer *tc, TransData *td, const float in[3], float out[3]) { @@ -489,10 +491,9 @@ static void applyObjectConstraintVec( } } -/* - * Generic callback for constant spatial constraints applied to resize motion +/** + * Generic callback for constant spatial constraints applied to resize motion. */ - static void applyAxisConstraintSize(TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, @@ -516,10 +517,9 @@ static void applyAxisConstraintSize(TransInfo *t, } } -/* - * Callback for object based spatial constraints applied to resize motion +/** + * Callback for object based spatial constraints applied to resize motion. */ - static void applyObjectConstraintSize(TransInfo *t, TransDataContainer *tc, TransData *td, @@ -549,10 +549,10 @@ static void applyObjectConstraintSize(TransInfo *t, } } -static void constraints_rotation_imp(TransInfo *t, - float axismtx[3][3], - float r_vec[3], - float *r_angle) +static void constraints_rotation_impl(TransInfo *t, + float axismtx[3][3], + float r_vec[3], + float *r_angle) { BLI_assert(t->con.mode & CON_APPLY); int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2); @@ -581,15 +581,15 @@ static void constraints_rotation_imp(TransInfo *t, } } -/* +/** * Generic callback for constant spatial constraints applied to rotations * - * The rotation axis is copied into VEC. + * The rotation axis is copied into `vec`. * * In the case of single axis constraints, the rotation axis is directly the one constrained to. * For planar constraints (2 axis), the rotation axis is the normal of the plane. * - * The following only applies when CON_NOFLIP is not set. + * The following only applies when #CON_NOFLIP is not set. * The vector is then modified to always point away from the screen (in global space) * This insures that the rotation is always logically following the mouse. * (ie: not doing counterclockwise rotations when the mouse moves clockwise). @@ -598,19 +598,19 @@ static void applyAxisConstraintRot( TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, float vec[3], float *angle) { if (!td && t->con.mode & CON_APPLY) { - constraints_rotation_imp(t, t->spacemtx, vec, angle); + constraints_rotation_impl(t, t->spacemtx, vec, angle); } } -/* +/** * Callback for object based spatial constraints applied to rotations * - * The rotation axis is copied into VEC. + * The rotation axis is copied into `vec`. * * In the case of single axis constraints, the rotation axis is directly the one constrained to. * For planar constraints (2 axis), the rotation axis is the normal of the plane. * - * The following only applies when CON_NOFLIP is not set. + * The following only applies when #CON_NOFLIP is not set. * The vector is then modified to always point away from the screen (in global space) * This insures that the rotation is always logically following the mouse. * (ie: not doing counterclockwise rotations when the mouse moves clockwise). @@ -637,11 +637,15 @@ static void applyObjectConstraintRot( axismtx = td->axismtx; } - constraints_rotation_imp(t, axismtx, vec, angle); + constraints_rotation_impl(t, axismtx, vec, angle); } } -/*--------------------- INTERNAL SETUP CALLS ------------------*/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal Setup Calls + * \{ */ void setConstraint(TransInfo *t, int mode, const char text[]) { @@ -676,7 +680,7 @@ void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[]) void setLocalConstraint(TransInfo *t, int mode, const char text[]) { - if (t->flag & T_EDIT) { + if ((t->flag & T_EDIT) || t->data_len_all == 1) { /* Although in edit-mode each object has its local space, use the * orientation of the active object. */ setConstraint(t, mode, text); @@ -686,10 +690,10 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[]) } } -/* +/** * Set the constraint according to the user defined orientation * - * ftext is a format string passed to BLI_snprintf. It will add the name of + * `ftext` is a format string passed to #BLI_snprintf. It will add the name of * the orientation where %s is (logically). */ void setUserConstraint(TransInfo *t, int mode, const char ftext[]) @@ -704,40 +708,35 @@ void setUserConstraint(TransInfo *t, int mode, const char ftext[]) const char *spacename = transform_orientations_spacename_get(t, orientation); BLI_snprintf(text, sizeof(text), ftext, spacename); - if (t->modifiers & (MOD_CONSTRAINT_SELECT | MOD_CONSTRAINT_PLANE)) { - /* Force the orientation of the active object. - * Although possible, it is not convenient to use the local or axis constraint - * with the modifier to select constraint. - * This also follows the convention of older versions. */ - setConstraint(t, mode, text); - } - else { - switch (orientation) { - case V3D_ORIENT_LOCAL: - setLocalConstraint(t, mode, text); - break; - case V3D_ORIENT_NORMAL: - if (checkUseAxisMatrix(t)) { - setAxisMatrixConstraint(t, mode, text); - break; - } - ATTR_FALLTHROUGH; - case V3D_ORIENT_GLOBAL: - case V3D_ORIENT_VIEW: - case V3D_ORIENT_CURSOR: - case V3D_ORIENT_GIMBAL: - case V3D_ORIENT_CUSTOM_MATRIX: - case V3D_ORIENT_CUSTOM: - default: { - setConstraint(t, mode, text); + switch (orientation) { + case V3D_ORIENT_LOCAL: + setLocalConstraint(t, mode, text); + break; + case V3D_ORIENT_NORMAL: + if (checkUseAxisMatrix(t)) { + setAxisMatrixConstraint(t, mode, text); break; } + ATTR_FALLTHROUGH; + case V3D_ORIENT_GLOBAL: + case V3D_ORIENT_VIEW: + case V3D_ORIENT_CURSOR: + case V3D_ORIENT_GIMBAL: + case V3D_ORIENT_CUSTOM_MATRIX: + case V3D_ORIENT_CUSTOM: + default: { + setConstraint(t, mode, text); + break; } } t->con.mode |= CON_USER; } -/*----------------- DRAWING CONSTRAINTS -------------------*/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Drawing Constraints + * \{ */ void drawConstraint(TransInfo *t) { @@ -915,7 +914,7 @@ static void drawObjectConstraint(TransInfo *t) mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx); axismtx = tmp_axismtx; } - else if (t->flag & T_POSE) { + else if (t->options & CTX_POSE_BONE) { mul_v3_m4v3(co, tc->mat, td->center); axismtx = td->axismtx; } @@ -938,7 +937,11 @@ static void drawObjectConstraint(TransInfo *t) } } -/*--------------------- START / STOP CONSTRAINTS ---------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Start / Stop Constraints + * \{ */ void startConstraint(TransInfo *t) { @@ -959,7 +962,11 @@ void stopConstraint(TransInfo *t) t->num.idx_max = t->idx_max; } -/*------------------------- MMB Select -------------------------------*/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Middle Mouse Button Select + * \{ */ void initSelectConstraint(TransInfo *t) { @@ -1106,7 +1113,11 @@ void setNearestAxis(TransInfo *t) projection_matrix_calc(t, t->con.pmtx); } -/*-------------- HELPER FUNCTIONS ----------------*/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Helper Functions + * \{ */ int constraintModeToIndex(const TransInfo *t) { @@ -1147,14 +1158,13 @@ bool isLockConstraint(TransInfo *t) return false; } -/* +/** * Returns the dimension of the constraint space. * * For that reason, the flags always needs to be set to properly evaluate here, - * even if they aren't actually used in the callback function. (Which could happen - * for weird constraints not yet designed. Along a path for example.) + * even if they aren't actually used in the callback function. + * (Which could happen for weird constraints not yet designed. Along a path for example.) */ - int getConstraintSpaceDimension(TransInfo *t) { int n = 0; @@ -1172,11 +1182,12 @@ int getConstraintSpaceDimension(TransInfo *t) } return n; - /* - * Someone willing to do it cryptically could do the following instead: + /* Someone willing to do it cryptically could do the following instead: * - * return t->con & (CON_AXIS0|CON_AXIS1|CON_AXIS2); + * `return t->con & (CON_AXIS0|CON_AXIS1|CON_AXIS2);` * * Based on the assumptions that the axis flags are one after the other and start at 1 */ } + +/** \} */ diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 3ea0b0a0a70..6b2e9dd9840 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -23,6 +23,7 @@ #include "DNA_anim_types.h" #include "DNA_constraint_types.h" +#include "DNA_mesh_types.h" #include "MEM_guardedalloc.h" @@ -892,7 +893,6 @@ void special_aftertrans_update(bContext *C, TransInfo *t) special_aftertrans_update__node(C, t); break; case TC_OBJECT: - case TC_OBJECT_TEXSPACE: special_aftertrans_update__object(C, t); break; case TC_SCULPT: @@ -912,6 +912,8 @@ void special_aftertrans_update(bContext *C, TransInfo *t) case TC_LATTICE_VERTS: case TC_MBALL_VERTS: case TC_MESH_UV: + case TC_MESH_SKIN: + case TC_OBJECT_TEXSPACE: case TC_PAINT_CURVE_VERTS: case TC_PARTICLE_VERTS: case TC_NONE: @@ -928,10 +930,10 @@ int special_transform_moving(TransInfo *t) if (t->spacetype == SPACE_GRAPH) { return G_TRANSFORM_FCURVES; } - if ((t->flag & T_EDIT) || (t->flag & T_POSE)) { + if ((t->flag & T_EDIT) || (t->options & CTX_POSE_BONE)) { return G_TRANSFORM_EDIT; } - if (t->flag & (T_OBJECT | T_TEXTURE)) { + if (t->options & (CTX_OBJECT | CTX_TEXTURE_SPACE)) { return G_TRANSFORM_OBJ; } @@ -973,53 +975,254 @@ static int countAndCleanTransDataContainer(TransInfo *t) return t->data_len_all; } -void createTransData(bContext *C, TransInfo *t) +static void init_proportional_edit(TransInfo *t) { - Scene *scene = t->scene; - ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); + eTConvertType convert_type = t->data_type; + switch (convert_type) { + case TC_ACTION_DATA: + case TC_CURVE_VERTS: + case TC_GRAPH_EDIT_DATA: + case TC_GPENCIL: + case TC_LATTICE_VERTS: + case TC_MASKING_DATA: + case TC_MBALL_VERTS: + case TC_MESH_VERTS: + case TC_MESH_EDGES: + case TC_MESH_SKIN: + case TC_MESH_UV: + case TC_NODE_DATA: + case TC_OBJECT: + case TC_PARTICLE_VERTS: + break; + case TC_POSE: /* Disable PET, its not usable in pose mode yet T32444. */ + case TC_ARMATURE_VERTS: + case TC_CURSOR_IMAGE: + case TC_CURSOR_VIEW3D: + case TC_NLA_DATA: + case TC_OBJECT_TEXSPACE: + case TC_PAINT_CURVE_VERTS: + case TC_SCULPT: + case TC_SEQ_DATA: + case TC_TRACKING_DATA: + case TC_NONE: + default: + t->options |= CTX_NO_PET; + t->flag &= ~T_PROP_EDIT_ALL; + return; + } - t->data_len_all = -1; + if (t->data_len_all && (t->flag & T_PROP_EDIT)) { + if (convert_type == TC_OBJECT) { + /* Selected objects are already first, no need to presort. */ + } + else { + sort_trans_data_selected_first(t); + } - eTransConvertType convert_type = TC_NONE; + if (ELEM(convert_type, TC_ACTION_DATA, TC_GRAPH_EDIT_DATA)) { + /* Distance has already been set. */ + } + else if (ELEM(convert_type, TC_MESH_VERTS, TC_MESH_SKIN)) { + if (t->flag & T_PROP_CONNECTED) { + /* Already calculated by transform_convert_mesh_connectivity_distance. */ + } + else { + set_prop_dist(t, false); + } + } + else if (convert_type == TC_MESH_UV && t->flag & T_PROP_CONNECTED) { + /* Already calculated by uv_set_connectivity_distance. */ + } + else if (convert_type == TC_CURVE_VERTS && t->obedit_type == OB_CURVE) { + set_prop_dist(t, false); + } + else { + set_prop_dist(t, true); + } + + sort_trans_data_dist(t); + } + else if (ELEM(t->obedit_type, OB_CURVE)) { + /* Needed because bezier handles can be partially selected + * and are still added into transform data. */ + sort_trans_data_selected_first(t); + } +} + +/* For multi object editing. */ +static void init_TransDataContainers(TransInfo *t, + Object *obact, + Object **objects, + uint objects_len) +{ + switch (t->data_type) { + case TC_POSE: + case TC_ARMATURE_VERTS: + case TC_CURVE_VERTS: + case TC_GPENCIL: + case TC_LATTICE_VERTS: + case TC_MBALL_VERTS: + case TC_MESH_VERTS: + case TC_MESH_EDGES: + case TC_MESH_SKIN: + case TC_MESH_UV: + break; + case TC_ACTION_DATA: + case TC_GRAPH_EDIT_DATA: + case TC_CURSOR_IMAGE: + case TC_CURSOR_VIEW3D: + case TC_MASKING_DATA: + case TC_NLA_DATA: + case TC_NODE_DATA: + case TC_OBJECT: + case TC_OBJECT_TEXSPACE: + case TC_PAINT_CURVE_VERTS: + case TC_PARTICLE_VERTS: + case TC_SCULPT: + case TC_SEQ_DATA: + case TC_TRACKING_DATA: + case TC_NONE: + default: + /* Does not support Multi object editing. */ + return; + } + + const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT; + const short object_type = obact ? obact->type : -1; + + if ((object_mode & OB_MODE_EDIT) || (t->data_type == TC_GPENCIL) || + ((object_mode & OB_MODE_POSE) && (object_type == OB_ARMATURE))) { + if (t->data_container) { + MEM_freeN(t->data_container); + } + + bool free_objects = false; + if (objects == NULL) { + objects = BKE_view_layer_array_from_objects_in_mode( + t->view_layer, + (t->spacetype == SPACE_VIEW3D) ? t->view : NULL, + &objects_len, + { + .object_mode = object_mode, + .no_dup_data = true, + }); + free_objects = true; + } + + t->data_container = MEM_callocN(sizeof(*t->data_container) * objects_len, __func__); + t->data_container_len = objects_len; + + for (int i = 0; i < objects_len; i++) { + TransDataContainer *tc = &t->data_container[i]; + if (((t->flag & T_NO_MIRROR) == 0) && ((t->options & CTX_NO_MIRROR) == 0) && + (objects[i]->type == OB_MESH)) { + tc->use_mirror_axis_x = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_X) != 0; + tc->use_mirror_axis_y = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Y) != 0; + tc->use_mirror_axis_z = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Z) != 0; + } + + if (object_mode & OB_MODE_EDIT) { + tc->obedit = objects[i]; + /* Check needed for UV's */ + if ((t->flag & T_2D_EDIT) == 0) { + tc->use_local_mat = true; + } + } + else if (object_mode & OB_MODE_POSE) { + tc->poseobj = objects[i]; + tc->use_local_mat = true; + } + else if (t->data_type == TC_GPENCIL) { + tc->use_local_mat = true; + } + + if (tc->use_local_mat) { + BLI_assert((t->flag & T_2D_EDIT) == 0); + copy_m4_m4(tc->mat, objects[i]->obmat); + copy_m3_m4(tc->mat3, tc->mat); + /* for non-invertible scale matrices, invert_m4_m4_fallback() + * can still provide a valid pivot */ + invert_m4_m4_fallback(tc->imat, tc->mat); + invert_m3_m3(tc->imat3, tc->mat3); + normalize_m3_m3(tc->mat3_unit, tc->mat3); + } + /* Otherwise leave as zero. */ + } + + if (free_objects) { + MEM_freeN(objects); + } + } +} + +static eTFlag flags_from_data_type(eTConvertType data_type) +{ + switch (data_type) { + case TC_ACTION_DATA: + case TC_GRAPH_EDIT_DATA: + case TC_MASKING_DATA: + case TC_NLA_DATA: + case TC_NODE_DATA: + case TC_PAINT_CURVE_VERTS: + case TC_SEQ_DATA: + case TC_TRACKING_DATA: + return T_POINTS | T_2D_EDIT; + case TC_ARMATURE_VERTS: + case TC_CURVE_VERTS: + case TC_GPENCIL: + case TC_LATTICE_VERTS: + case TC_MBALL_VERTS: + case TC_MESH_VERTS: + case TC_MESH_SKIN: + return T_EDIT | T_POINTS; + case TC_MESH_EDGES: + return T_EDIT; + case TC_MESH_UV: + return T_EDIT | T_POINTS | T_2D_EDIT; + case TC_PARTICLE_VERTS: + return T_POINTS; + case TC_POSE: + case TC_CURSOR_IMAGE: + case TC_CURSOR_VIEW3D: + case TC_OBJECT: + case TC_OBJECT_TEXSPACE: + case TC_SCULPT: + case TC_NONE: + default: + break; + } + return 0; +} + +static eTConvertType convert_type_get(const TransInfo *t, Object **r_obj_armature) +{ + ViewLayer *view_layer = t->view_layer; + Object *ob = OBACT(view_layer); + eTConvertType convert_type = TC_NONE; /* if tests must match recalcData for correct updates */ if (t->options & CTX_CURSOR) { - t->flag |= T_CURSOR; - if (t->spacetype == SPACE_IMAGE) { convert_type = TC_CURSOR_IMAGE; } else { convert_type = TC_CURSOR_VIEW3D; } - - /* Since we're transforming the cursor, initialize this value before it's modified. - * Needed for #snap_grid_apply to access the cursor location. */ - transformCenter_from_type(t, V3D_AROUND_CURSOR); } else if (!(t->options & CTX_PAINT_CURVE) && (t->spacetype == SPACE_VIEW3D) && ob && (ob->mode == OB_MODE_SCULPT) && ob->sculpt) { convert_type = TC_SCULPT; } - else if (t->options & CTX_TEXTURE) { - t->flag |= T_TEXTURE; + else if (t->options & CTX_TEXTURE_SPACE) { convert_type = TC_OBJECT_TEXSPACE; } - else if (t->options & CTX_EDGE) { - t->flag |= T_EDIT; + else if (t->options & CTX_EDGE_DATA) { convert_type = TC_MESH_EDGES; - /* Multi object editing. */ - initTransDataContainers_FromObjectData(t, ob, NULL, 0); } else if (t->options & CTX_GPENCIL_STROKES) { - t->options |= CTX_GPENCIL_STROKES; - t->flag |= T_POINTS | T_EDIT; convert_type = TC_GPENCIL; - initTransDataContainers_FromObjectData(t, ob, NULL, 0); } else if (t->spacetype == SPACE_IMAGE) { - t->flag |= T_POINTS | T_2D_EDIT; if (t->options & CTX_MASK) { convert_type = TC_MASKING_DATA; } @@ -1029,41 +1232,25 @@ void createTransData(bContext *C, TransInfo *t) } } else if (t->obedit_type == OB_MESH) { - t->flag |= T_EDIT; convert_type = TC_MESH_UV; - initTransDataContainers_FromObjectData(t, ob, NULL, 0); } } else if (t->spacetype == SPACE_ACTION) { - t->flag |= T_POINTS | T_2D_EDIT; - t->obedit_type = -1; convert_type = TC_ACTION_DATA; } else if (t->spacetype == SPACE_NLA) { - t->flag |= T_POINTS | T_2D_EDIT; - t->obedit_type = -1; convert_type = TC_NLA_DATA; } else if (t->spacetype == SPACE_SEQ) { - t->flag |= T_POINTS | T_2D_EDIT; - t->obedit_type = -1; - t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point trasnform */ convert_type = TC_SEQ_DATA; } else if (t->spacetype == SPACE_GRAPH) { - t->flag |= T_POINTS | T_2D_EDIT; - t->obedit_type = -1; convert_type = TC_GRAPH_EDIT_DATA; } else if (t->spacetype == SPACE_NODE) { - t->flag |= T_POINTS | T_2D_EDIT; - t->obedit_type = -1; convert_type = TC_NODE_DATA; } else if (t->spacetype == SPACE_CLIP) { - t->flag |= T_POINTS | T_2D_EDIT; - t->obedit_type = -1; - if (t->options & CTX_MOVIECLIP) { convert_type = TC_TRACKING_DATA; } @@ -1072,11 +1259,6 @@ void createTransData(bContext *C, TransInfo *t) } } else if (t->obedit_type != -1) { - t->flag |= T_EDIT | T_POINTS; - - /* Multi object editing. */ - initTransDataContainers_FromObjectData(t, ob, NULL, 0); - if (t->obedit_type == OB_MESH) { if (t->mode == TFM_SKIN_RESIZE) { convert_type = TC_MESH_SKIN; @@ -1095,46 +1277,25 @@ void createTransData(bContext *C, TransInfo *t) convert_type = TC_MBALL_VERTS; } else if (t->obedit_type == OB_ARMATURE) { - t->flag &= ~T_PROP_EDIT; convert_type = TC_ARMATURE_VERTS; } } else if (ob && (ob->mode & OB_MODE_POSE)) { - /* XXX this is currently limited to active armature only... */ - - /* XXX active-layer checking isn't done - * as that should probably be checked through context instead. */ - - /* Multi object editing. */ - initTransDataContainers_FromObjectData(t, ob, NULL, 0); convert_type = TC_POSE; } else if (ob && (ob->mode & OB_MODE_ALL_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) { - /* Important that ob_armature can be set even when its not selected T23412. - * Lines below just check is also visible. */ - Object *ob_armature = BKE_modifiers_is_deformed_by_armature(ob); - if (ob_armature && ob_armature->mode & OB_MODE_POSE) { - Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature); - if (base_arm) { - View3D *v3d = t->view; - if (BASE_VISIBLE(v3d, base_arm)) { - Object *objects[1]; - objects[0] = ob_armature; - uint objects_len = 1; - initTransDataContainers_FromObjectData(t, ob_armature, objects, objects_len); - convert_type = TC_POSE; - } - } + Object *ob_armature = transform_object_deform_pose_armature_get(t, ob); + if (ob_armature) { + *r_obj_armature = ob_armature; + convert_type = TC_POSE; } } else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && - PE_start_edit(PE_get_current(t->depsgraph, scene, ob))) { - t->flag |= T_POINTS; + PE_start_edit(PE_get_current(t->depsgraph, t->scene, ob))) { convert_type = TC_PARTICLE_VERTS; } else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) { if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) { - t->flag |= T_POINTS | T_2D_EDIT; convert_type = TC_PAINT_CURVE_VERTS; } } @@ -1146,47 +1307,55 @@ void createTransData(bContext *C, TransInfo *t) /* In grease pencil all transformations must be canceled if not Object or Edit. */ } else { - /* Needed for correct Object.obmat after duplication, see: T62135. */ - BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); - - if ((scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) != 0) { - t->options |= CTX_OBMODE_XFORM_OBDATA; - } - if ((scene->toolsettings->transform_flag & SCE_XFORM_SKIP_CHILDREN) != 0) { - t->options |= CTX_OBMODE_XFORM_SKIP_CHILDREN; - } - - t->flag |= T_OBJECT; convert_type = TC_OBJECT; } - t->data_type = convert_type; - bool init_prop_edit = (t->flag & T_PROP_EDIT) != 0; + return convert_type; +} + +void createTransData(bContext *C, TransInfo *t) +{ + t->data_len_all = -1; + + Object *ob_armature = NULL; + t->data_type = convert_type_get(t, &ob_armature); + t->flag |= flags_from_data_type(t->data_type); - switch (convert_type) { + if (ob_armature) { + init_TransDataContainers(t, ob_armature, &ob_armature, 1); + } + else { + ViewLayer *view_layer = t->view_layer; + Object *ob = OBACT(view_layer); + init_TransDataContainers(t, ob, NULL, 0); + } + + switch (t->data_type) { case TC_ACTION_DATA: + t->obedit_type = -1; createTransActionData(C, t); break; case TC_POSE: + t->options |= CTX_POSE_BONE; + + /* XXX active-layer checking isn't done + * as that should probably be checked through context instead. */ createTransPose(t); - /* Disable PET, its not usable in pose mode yet T32444. */ - init_prop_edit = false; break; case TC_ARMATURE_VERTS: createTransArmatureVerts(t); break; case TC_CURSOR_IMAGE: createTransCursor_image(t); - init_prop_edit = false; break; case TC_CURSOR_VIEW3D: createTransCursor_view3d(t); - init_prop_edit = false; break; case TC_CURVE_VERTS: createTransCurveVerts(t); break; case TC_GRAPH_EDIT_DATA: + t->obedit_type = -1; createTransGraphEditData(C, t); break; case TC_GPENCIL: @@ -1196,6 +1365,9 @@ void createTransData(bContext *C, TransInfo *t) createTransLatticeVerts(t); break; case TC_MASKING_DATA: + if (t->spacetype == SPACE_CLIP) { + t->obedit_type = -1; + } createTransMaskingData(C, t); break; case TC_MBALL_VERTS: @@ -1214,13 +1386,25 @@ void createTransData(bContext *C, TransInfo *t) createTransUVs(C, t); break; case TC_NLA_DATA: + t->obedit_type = -1; createTransNlaData(C, t); - init_prop_edit = false; break; case TC_NODE_DATA: + t->obedit_type = -1; createTransNodeData(t); break; case TC_OBJECT: + t->options |= CTX_OBJECT; + + /* Needed for correct Object.obmat after duplication, see: T62135. */ + BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); + + if ((t->settings->transform_flag & SCE_XFORM_DATA_ORIGIN) != 0) { + t->options |= CTX_OBMODE_XFORM_OBDATA; + } + if ((t->settings->transform_flag & SCE_XFORM_SKIP_CHILDREN) != 0) { + t->options |= CTX_OBMODE_XFORM_SKIP_CHILDREN; + } createTransObject(C, t); /* Check if we're transforming the camera from the camera */ if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { @@ -1229,36 +1413,34 @@ void createTransData(bContext *C, TransInfo *t) if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) { /* we could have a flag to easily check an object is being transformed */ if (v3d->camera->id.tag & LIB_TAG_DOIT) { - t->flag |= T_CAMERA; + t->options |= CTX_CAMERA; } } else if (v3d->ob_center && v3d->ob_center->id.tag & LIB_TAG_DOIT) { - t->flag |= T_CAMERA; + t->options |= CTX_CAMERA; } } break; case TC_OBJECT_TEXSPACE: createTransTexspace(t); - init_prop_edit = false; break; case TC_PAINT_CURVE_VERTS: createTransPaintCurveVerts(C, t); - init_prop_edit = false; break; case TC_PARTICLE_VERTS: createTransParticleVerts(t); break; case TC_SCULPT: createTransSculpt(C, t); - init_prop_edit = false; break; case TC_SEQ_DATA: + t->obedit_type = -1; + t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point transform. */ createTransSeqData(t); - init_prop_edit = false; break; case TC_TRACKING_DATA: + t->obedit_type = -1; createTransTrackingData(C, t); - init_prop_edit = false; break; case TC_NONE: default: @@ -1270,48 +1452,7 @@ void createTransData(bContext *C, TransInfo *t) countAndCleanTransDataContainer(t); - if (t->data_len_all && init_prop_edit) { - if (convert_type == TC_OBJECT) { - /* Selected objects are already first, no need to presort. */ - } - else { - sort_trans_data_selected_first(t); - } - - if (ELEM(convert_type, TC_ACTION_DATA, TC_GRAPH_EDIT_DATA)) { - /* Distance has already been set. */ - } - else if (ELEM(convert_type, TC_MESH_VERTS, TC_MESH_SKIN)) { - if (t->flag & T_PROP_CONNECTED) { - /* Already calculated by transform_convert_mesh_connectivity_distance. */ - } - else { - set_prop_dist(t, false); - } - } - else if (convert_type == TC_MESH_UV && t->flag & T_PROP_CONNECTED) { - /* Already calculated by uv_set_connectivity_distance. */ - } - else if (convert_type == TC_CURVE_VERTS && t->obedit_type == OB_CURVE) { - set_prop_dist(t, false); - } - else { - set_prop_dist(t, true); - } - - sort_trans_data_dist(t); - } - else { - if (ELEM(t->obedit_type, OB_CURVE)) { - /* Needed because bezier handles can be partially selected - * and are still added into transform data. */ - sort_trans_data_selected_first(t); - } - - if (!init_prop_edit) { - t->flag &= ~T_PROP_EDIT_ALL; - } - } + init_proportional_edit(t); BLI_assert((!(t->flag & T_EDIT)) == (!(t->obedit_type != -1))); } @@ -1557,9 +1698,11 @@ void recalcData(TransInfo *t) flushTransNodes(t); break; case TC_OBJECT: - case TC_OBJECT_TEXSPACE: recalcData_objects(t); break; + case TC_OBJECT_TEXSPACE: + recalcData_texspace(t); + break; case TC_PAINT_CURVE_VERTS: flushTransPaintCurve(t); break; diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index 466bfd6b226..bd7569b3771 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -49,37 +49,9 @@ void mesh_customdatacorrect_init(TransInfo *t); /* transform_convert_sequencer.c */ int transform_convert_sequencer_get_snap_bound(TransInfo *t); - +void transform_convert_sequencer_channel_clamp(TransInfo *t); /********************* intern **********************/ -typedef enum eTransConvertType { - TC_NONE = 0, - TC_ACTION_DATA, - TC_POSE, - TC_ARMATURE_VERTS, - TC_CURSOR_IMAGE, - TC_CURSOR_VIEW3D, - TC_CURVE_VERTS, - TC_GRAPH_EDIT_DATA, - TC_GPENCIL, - TC_LATTICE_VERTS, - TC_MASKING_DATA, - TC_MBALL_VERTS, - TC_MESH_VERTS, - TC_MESH_EDGES, - TC_MESH_SKIN, - TC_MESH_UV, - TC_NLA_DATA, - TC_NODE_DATA, - TC_OBJECT, - TC_OBJECT_TEXSPACE, - TC_PAINT_CURVE_VERTS, - TC_PARTICLE_VERTS, - TC_SCULPT, - TC_SEQ_DATA, - TC_TRACKING_DATA, -} eTransConvertType; - /* transform_convert.c */ bool transform_mode_use_local_origins(const TransInfo *t); void transform_around_single_fallback_ex(TransInfo *t, int data_len_all); @@ -215,10 +187,13 @@ void special_aftertrans_update__node(bContext *C, TransInfo *t); /* transform_convert_object.c */ void createTransObject(bContext *C, TransInfo *t); -void createTransTexspace(TransInfo *t); void recalcData_objects(TransInfo *t); void special_aftertrans_update__object(bContext *C, TransInfo *t); +/* transform_convert_object_texspace.c */ +void createTransTexspace(TransInfo *t); +void recalcData_texspace(TransInfo *t); + /* transform_convert_paintcurve.c */ void createTransPaintCurveVerts(bContext *C, TransInfo *t); void flushTransPaintCurve(TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index e9b2273b343..71b9e11b51f 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -444,7 +444,7 @@ static short pose_grab_with_ik(Main *bmain, Object *ob) for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone->layer & arm->layer) { if (pchan->bone->flag & (BONE_SELECTED | BONE_TRANSFORM_MIRROR)) { - /* Rule: no IK for solitatry (unconnected) bones */ + /* Rule: no IK for solitary (unconnected) bones. */ for (bonec = pchan->bone->childbase.first; bonec; bonec = bonec->next) { if (bonec->flag & BONE_CONNECTED) { break; @@ -870,8 +870,6 @@ void createTransPose(TransInfo *t) t->mode = TFM_RESIZE; } } - - t->flag |= T_POSE; } void createTransArmatureVerts(TransInfo *t) @@ -1354,7 +1352,7 @@ static void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, O } mul_v3_m4v3(data->grabtarget, flip_mtx, td->loc); if (pid) { - /* TODO(germano): Realitve Mirror support */ + /* TODO(germano): Relative Mirror support. */ } data->flag |= CONSTRAINT_IK_AUTO; /* Add a temporary auto IK constraint here, as we will only temporarily active this diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c index 445253d5446..3c01c716123 100644 --- a/source/blender/editors/transform/transform_convert_curve.c +++ b/source/blender/editors/transform/transform_convert_curve.c @@ -298,7 +298,7 @@ void createTransCurveVerts(TransInfo *t) } if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0) { - /* If the middle is selected but the sides arnt, this is needed */ + /* If the middle is selected but the sides aren't, this is needed. */ if (hdata == NULL) { /* if the handle was not saved by the previous handle */ hdata = initTransDataCurveHandles(td, bezt); diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c index deb18b50a22..eaa8962326a 100644 --- a/source/blender/editors/transform/transform_convert_gpencil.c +++ b/source/blender/editors/transform/transform_convert_gpencil.c @@ -135,7 +135,7 @@ static void createTransGPencil_curves(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* Check if stroke has an editcurve */ @@ -242,7 +242,7 @@ static void createTransGPencil_curves(bContext *C, } /* Calculate difference matrix. */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); copy_m3_m4(mtx, diff_mat); pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); @@ -263,7 +263,7 @@ static void createTransGPencil_curves(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* Check if stroke has an editcurve */ @@ -436,7 +436,7 @@ static void createTransGPencil_strokes(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } @@ -507,7 +507,7 @@ static void createTransGPencil_strokes(bContext *C, } /* Calculate difference matrix. */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); /* Undo matrix. */ invert_m4_m4(inverse_diff_mat, diff_mat); @@ -551,7 +551,7 @@ static void createTransGPencil_strokes(bContext *C, continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* What we need to include depends on proportional editing settings... */ diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index b3bd6b31879..ce74c5f5a36 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -251,29 +251,55 @@ void transform_convert_mesh_islanddata_free(struct TransIslandData *island_data) * * \{ */ -static bool bmesh_test_dist_add(BMVert *v, - BMVert *v_other, +/* Propagate distance from v1 and v2 to v0. */ +static bool bmesh_test_dist_add(BMVert *v0, + BMVert *v1, + BMVert *v2, float *dists, - const float *dists_prev, /* optionally track original index */ int *index, - const int *index_prev, const float mtx[3][3]) { - if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) && - (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0)) { - const int i = BM_elem_index_get(v); - const int i_other = BM_elem_index_get(v_other); - float vec[3]; - float dist_other; - sub_v3_v3v3(vec, v->co, v_other->co); - mul_m3_v3(mtx, vec); - - dist_other = dists_prev[i] + len_v3(vec); - if (dist_other < dists[i_other]) { - dists[i_other] = dist_other; + if ((BM_elem_flag_test(v0, BM_ELEM_SELECT) == 0) && + (BM_elem_flag_test(v0, BM_ELEM_HIDDEN) == 0)) { + const int i0 = BM_elem_index_get(v0); + const int i1 = BM_elem_index_get(v1); + + BLI_assert(dists[i1] != FLT_MAX); + if (dists[i0] <= dists[i1]) { + return false; + } + + float dist0; + + if (v2) { + /* Distance across triangle. */ + const int i2 = BM_elem_index_get(v2); + BLI_assert(dists[i2] != FLT_MAX); + if (dists[i0] <= dists[i2]) { + return false; + } + + float vm0[3], vm1[3], vm2[3]; + mul_v3_m3v3(vm0, mtx, v0->co); + mul_v3_m3v3(vm1, mtx, v1->co); + mul_v3_m3v3(vm2, mtx, v2->co); + + dist0 = geodesic_distance_propagate_across_triangle(vm0, vm1, vm2, dists[i1], dists[i2]); + } + else { + /* Distance along edge. */ + float vec[3]; + sub_v3_v3v3(vec, v1->co, v0->co); + mul_m3_v3(mtx, vec); + + dist0 = dists[i1] + len_v3(vec); + } + + if (dist0 < dists[i0]) { + dists[i0] = dist0; if (index != NULL) { - index[i_other] = index_prev[i]; + index[i0] = index[i1]; } return true; } @@ -292,15 +318,16 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, float *dists, int *index) { - BLI_LINKSTACK_DECLARE(queue, BMVert *); + BLI_LINKSTACK_DECLARE(queue, BMEdge *); - /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */ - BLI_LINKSTACK_DECLARE(queue_next, BMVert *); + /* any BM_ELEM_TAG'd edge is in 'queue_next', so we don't add in twice */ + BLI_LINKSTACK_DECLARE(queue_next, BMEdge *); BLI_LINKSTACK_INIT(queue); BLI_LINKSTACK_INIT(queue_next); { + /* Set indexes and initial distances for selected vertices. */ BMIter viter; BMVert *v; int i; @@ -308,7 +335,6 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { float dist; BM_elem_index_set(v, i); /* set_inline */ - BM_elem_flag_disable(v, BM_ELEM_TAG); if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { dist = FLT_MAX; @@ -317,7 +343,6 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, } } else { - BLI_LINKSTACK_PUSH(queue, v); dist = 0.0f; if (index != NULL) { index[i] = i; @@ -329,103 +354,99 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, bm->elem_index_dirty &= ~BM_VERT; } - /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */ - float *dists_prev = MEM_dupallocN(dists); - int *index_prev = MEM_dupallocN(index); /* may be NULL */ + { + /* Add edges with at least one selected vertex to the queue. */ + BMIter eiter; + BMEdge *e; + + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + BMVert *v1 = e->v1; + BMVert *v2 = e->v2; + int i1 = BM_elem_index_get(v1); + int i2 = BM_elem_index_get(v2); + + if (dists[i1] != FLT_MAX || dists[i2] != FLT_MAX) { + BLI_LINKSTACK_PUSH(queue, e); + } + BM_elem_flag_disable(e, BM_ELEM_TAG); + } + } do { - BMVert *v; - LinkNode *lnk; - - /* this is correct but slow to do each iteration, - * instead sync the dist's while clearing BM_ELEM_TAG (below) */ -#if 0 - memcpy(dists_prev, dists, sizeof(float) * bm->totvert); -#endif - - while ((v = BLI_LINKSTACK_POP(queue))) { - BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX); - - /* connected edge-verts */ - if (v->e != NULL) { - BMEdge *e_iter, *e_first; - - e_iter = e_first = v->e; - - /* would normally use BM_EDGES_OF_VERT, but this runs so often, - * its faster to iterate on the data directly */ - do { - - if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == 0) { + BMEdge *e; + + while ((e = BLI_LINKSTACK_POP(queue))) { + BMVert *v1 = e->v1; + BMVert *v2 = e->v2; + int i1 = BM_elem_index_get(v1); + int i2 = BM_elem_index_get(v2); + + if (e->l == NULL || (dists[i1] == FLT_MAX || dists[i2] == FLT_MAX)) { + /* Propagate along edge from vertex with smallest to largest distance. */ + if (dists[i1] > dists[i2]) { + SWAP(int, i1, i2); + SWAP(BMVert *, v1, v2); + } - /* edge distance */ - { - BMVert *v_other = BM_edge_other_vert(e_iter, v); - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) { - if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { - BM_elem_flag_enable(v_other, BM_ELEM_TAG); - BLI_LINKSTACK_PUSH(queue_next, v_other); - } - } + if (bmesh_test_dist_add(v2, v1, NULL, dists, index, mtx)) { + /* Add adjacent loose edges to the queue, or all edges if this is a loose edge. + * Other edges are handled by propagation across edges below. */ + BMEdge *e_other; + BMIter eiter; + BM_ITER_ELEM (e_other, &eiter, v2, BM_EDGES_OF_VERT) { + if (e_other != e && BM_elem_flag_test(e_other, BM_ELEM_TAG) == 0 && + (e->l == NULL || e_other->l == NULL)) { + BM_elem_flag_enable(e_other, BM_ELEM_TAG); + BLI_LINKSTACK_PUSH(queue_next, e_other); } + } + } + } - /* face distance */ - if (e_iter->l) { - BMLoop *l_iter_radial, *l_first_radial; - /** - * imaginary edge diagonally across quad. - * \note This takes advantage of the rules of winding that we - * know 2 or more of a verts edges wont reference the same face twice. - * Also, if the edge is hidden, the face will be hidden too. - */ - l_iter_radial = l_first_radial = e_iter->l; - - do { - if ((l_iter_radial->v == v) && (l_iter_radial->f->len == 4) && - (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0)) { - BMVert *v_other = l_iter_radial->next->next->v; - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) { - if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { - BM_elem_flag_enable(v_other, BM_ELEM_TAG); - BLI_LINKSTACK_PUSH(queue_next, v_other); - } - } + if (e->l != NULL) { + /* Propagate across edge to vertices in adjacent faces. */ + BMLoop *l; + BMIter liter; + BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { + for (BMLoop *l_other = l->next->next; l_other != l; l_other = l_other->next) { + BMVert *v_other = l_other->v; + BLI_assert(!ELEM(v_other, v1, v2)); + + if (bmesh_test_dist_add(v_other, v1, v2, dists, index, mtx)) { + /* Add adjacent edges to the queue, if they are ready to propagate across/along. + * Always propagate along loose edges, and for other edges only propagate across + * if both vertices have a known distances. */ + BMEdge *e_other; + BMIter eiter; + BM_ITER_ELEM (e_other, &eiter, v_other, BM_EDGES_OF_VERT) { + if (e_other != e && BM_elem_flag_test(e_other, BM_ELEM_TAG) == 0 && + (e_other->l == NULL || + dists[BM_elem_index_get(BM_edge_other_vert(e_other, v_other))] != FLT_MAX)) { + BM_elem_flag_enable(e_other, BM_ELEM_TAG); + BLI_LINKSTACK_PUSH(queue_next, e_other); } - } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial); + } } } - } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first); + } } } - /* clear for the next loop */ - for (lnk = queue_next; lnk; lnk = lnk->next) { - BMVert *v_link = lnk->link; - const int i = BM_elem_index_get(v_link); + /* Clear for the next loop. */ + for (LinkNode *lnk = queue_next; lnk; lnk = lnk->next) { + BMEdge *e_link = lnk->link; - BM_elem_flag_disable(v_link, BM_ELEM_TAG); - - /* keep in sync, avoid having to do full memcpy each iteration */ - dists_prev[i] = dists[i]; - if (index != NULL) { - index_prev[i] = index[i]; - } + BM_elem_flag_disable(e_link, BM_ELEM_TAG); } BLI_LINKSTACK_SWAP(queue, queue_next); - /* none should be tagged now since 'queue_next' is empty */ - BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0); - + /* None should be tagged now since 'queue_next' is empty. */ + BLI_assert(BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, BM_ELEM_TAG, true) == 0); } while (BLI_LINKSTACK_SIZE(queue)); BLI_LINKSTACK_FREE(queue); BLI_LINKSTACK_FREE(queue_next); - - MEM_freeN(dists_prev); - if (index_prev != NULL) { - MEM_freeN(index_prev); - } } /** \} */ @@ -1445,7 +1466,7 @@ static void mesh_customdatacorrect_apply_vert(struct TransCustomDataLayer *tcld, * * Interpolate from every other loop (not ideal) * However values will only be taken from loops which overlap other mdisps. - * */ + */ const bool update_loop_mdisps = is_moved && do_loop_mdisps && (tcld->cd_loop_mdisp_offset != -1); if (update_loop_mdisps) { float(*faces_center)[3] = BLI_array_alloca(faces_center, l_num); diff --git a/source/blender/editors/transform/transform_convert_mesh_skin.c b/source/blender/editors/transform/transform_convert_mesh_skin.c index 1807e9adcd1..b1024f5efe4 100644 --- a/source/blender/editors/transform/transform_convert_mesh_skin.c +++ b/source/blender/editors/transform/transform_convert_mesh_skin.c @@ -55,9 +55,7 @@ static float *mesh_skin_transdata_center(const struct TransIslandData *island_da if (island_data->center && island_index != -1) { return island_data->center[island_index]; } - else { - return eve->co; - } + return eve->co; } static void mesh_skin_transdata_create(TransDataBasic *td, diff --git a/source/blender/editors/transform/transform_convert_nla.c b/source/blender/editors/transform/transform_convert_nla.c index adc2d03e2dc..5eb3f68787a 100644 --- a/source/blender/editors/transform/transform_convert_nla.c +++ b/source/blender/editors/transform/transform_convert_nla.c @@ -304,7 +304,7 @@ void recalcData_nla(TransInfo *t) for (i = 0; i < tc->data_len; i++, tdn++) { NlaStrip *strip = tdn->strip; PointerRNA strip_ptr; - short pExceeded, nExceeded, iter; + short iter; int delta_y1, delta_y2; /* if this tdn has no handles, that means it is just a dummy that should be skipped */ @@ -358,21 +358,31 @@ void recalcData_nla(TransInfo *t) * * this is done as a iterative procedure (done 5 times max for now) */ + NlaStrip *prev = strip->prev; + while (prev != NULL && (prev->type & NLASTRIP_TYPE_TRANSITION)) { + prev = prev->prev; + } + + NlaStrip *next = strip->next; + while (next != NULL && (next->type & NLASTRIP_TYPE_TRANSITION)) { + next = next->next; + } + for (iter = 0; iter < 5; iter++) { - pExceeded = ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) && - (tdn->h1[0] < strip->prev->end)); - nExceeded = ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) && - (tdn->h2[0] > strip->next->start)); + + const bool pExceeded = (prev != NULL) && (tdn->h1[0] < prev->end); + const bool nExceeded = (next != NULL) && (tdn->h2[0] > next->start); if ((pExceeded && nExceeded) || (iter == 4)) { - /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise) + /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a + * compromise) * - Simply crop strip to fit within the bounds of the strips bounding it * - If there were no neighbors, clear the transforms * (make it default to the strip's current values). */ - if (strip->prev && strip->next) { - tdn->h1[0] = strip->prev->end; - tdn->h2[0] = strip->next->start; + if (prev && next) { + tdn->h1[0] = prev->end; + tdn->h2[0] = next->start; } else { tdn->h1[0] = strip->start; @@ -381,14 +391,14 @@ void recalcData_nla(TransInfo *t) } else if (nExceeded) { /* move backwards */ - float offset = tdn->h2[0] - strip->next->start; + float offset = tdn->h2[0] - next->start; tdn->h1[0] -= offset; tdn->h2[0] -= offset; } else if (pExceeded) { /* more forwards */ - float offset = strip->prev->end - tdn->h1[0]; + float offset = prev->end - tdn->h1[0]; tdn->h1[0] += offset; tdn->h2[0] += offset; @@ -564,7 +574,7 @@ void special_aftertrans_update__nla(bContext *C, TransInfo *UNUSED(t)) /* free temp memory */ ANIM_animdata_freelist(&anim_data); - /* perform after-transfrom validation */ + /* Perform after-transform validation. */ ED_nla_postop_refresh(&ac); } } diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index 90ffccfdd7b..5f6f00716f9 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -21,12 +21,8 @@ * \ingroup edtransform */ -#include "DNA_mesh_types.h" - #include "MEM_guardedalloc.h" -#include "BLI_compiler_compat.h" -#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_math.h" @@ -46,11 +42,11 @@ #include "DEG_depsgraph_query.h" #include "transform.h" +#include "transform_orientations.h" #include "transform_snap.h" /* Own include. */ #include "transform_convert.h" -#include "transform_orientations.h" /* -------------------------------------------------------------------- */ /** \name Object Mode Custom Data @@ -713,66 +709,6 @@ void createTransObject(bContext *C, TransInfo *t) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Texture Space Transform Creation - * - * Instead of transforming the selection, move the 2D/3D cursor. - * - * \{ */ - -void createTransTexspace(TransInfo *t) -{ - ViewLayer *view_layer = t->view_layer; - TransData *td; - Object *ob; - ID *id; - short *texflag; - - ob = OBACT(view_layer); - - if (ob == NULL) { /* Shouldn't logically happen, but still. */ - return; - } - - id = ob->data; - if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) { - BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform"); - return; - } - - if (BKE_object_obdata_is_libdata(ob)) { - BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform"); - return; - } - - { - BLI_assert(t->data_container_len == 1); - TransDataContainer *tc = t->data_container; - tc->data_len = 1; - td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace"); - td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace"); - } - - td->flag = TD_SELECTED; - copy_v3_v3(td->center, ob->obmat[3]); - td->ob = ob; - - copy_m3_m4(td->mtx, ob->obmat); - copy_m3_m4(td->axismtx, ob->obmat); - normalize_m3(td->axismtx); - pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); - - if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size)) { - ob->dtx |= OB_TEXSPACE; - *texflag &= ~ME_AUTOSPACE; - } - - copy_v3_v3(td->iloc, td->loc); - copy_v3_v3(td->ext->isize, td->ext->size); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Transform (Auto-Keyframing) * \{ */ @@ -962,10 +898,6 @@ void recalcData_objects(TransInfo *t) * otherwise proxies don't function correctly */ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); - - if (t->flag & T_TEXTURE) { - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - } } } @@ -991,7 +923,7 @@ void recalcData_objects(TransInfo *t) void special_aftertrans_update__object(bContext *C, TransInfo *t) { - BLI_assert(t->flag & (T_OBJECT | T_TEXTURE)); + BLI_assert(t->options & CTX_OBJECT); Object *ob; const bool canceled = (t->state == TRANS_CANCEL); diff --git a/source/blender/editors/transform/transform_convert_object_texspace.c b/source/blender/editors/transform/transform_convert_object_texspace.c new file mode 100644 index 00000000000..195eb941b3b --- /dev/null +++ b/source/blender/editors/transform/transform_convert_object_texspace.c @@ -0,0 +1,126 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + */ + +/** \file + * \ingroup edtransform + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "BKE_animsys.h" +#include "BKE_context.h" +#include "BKE_object.h" +#include "BKE_report.h" + +#include "DNA_mesh_types.h" + +#include "transform.h" +#include "transform_snap.h" + +/* Own include. */ +#include "transform_convert.h" + +/* -------------------------------------------------------------------- */ +/** \name Texture Space Transform Creation + * + * Instead of transforming the selection, move the 2D/3D cursor. + * + * \{ */ + +void createTransTexspace(TransInfo *t) +{ + ViewLayer *view_layer = t->view_layer; + TransData *td; + Object *ob; + ID *id; + short *texflag; + + ob = OBACT(view_layer); + + if (ob == NULL) { /* Shouldn't logically happen, but still. */ + return; + } + + id = ob->data; + if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) { + BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform"); + return; + } + + if (BKE_object_obdata_is_libdata(ob)) { + BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform"); + return; + } + + { + BLI_assert(t->data_container_len == 1); + TransDataContainer *tc = t->data_container; + tc->data_len = 1; + td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace"); + td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace"); + } + + td->flag = TD_SELECTED; + copy_v3_v3(td->center, ob->obmat[3]); + td->ob = ob; + + copy_m3_m4(td->mtx, ob->obmat); + copy_m3_m4(td->axismtx, ob->obmat); + normalize_m3(td->axismtx); + pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); + + if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size)) { + ob->dtx |= OB_TEXSPACE; + *texflag &= ~ME_AUTOSPACE; + } + + copy_v3_v3(td->iloc, td->loc); + copy_v3_v3(td->ext->isize, td->ext->size); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Recalc Data object + * + * \{ */ + +/* helper for recalcData() - for object transforms, typically in the 3D view */ +void recalcData_texspace(TransInfo *t) +{ + + if (t->state != TRANS_CANCEL) { + applyProject(t); + } + + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + + for (int i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; + } + DEG_id_tag_update(&td->ob->id, ID_RECALC_GEOMETRY); + } + } +} + +/** \} */ diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index ebb0b6823a3..22b1f9fd8d7 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -25,6 +25,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_listbase.h" #include "BLI_math.h" #include "BKE_context.h" @@ -64,6 +65,8 @@ typedef struct TransSeq { int min; int max; bool snap_left; + int selection_channel_range_min; + int selection_channel_range_max; } TransSeq; /* -------------------------------------------------------------------- */ @@ -623,6 +626,14 @@ void createTransSeqData(TransInfo *t) } } + ts->selection_channel_range_min = MAXSEQ + 1; + LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { + if ((seq->flag & SELECT) != 0) { + ts->selection_channel_range_min = min_ii(ts->selection_channel_range_min, seq->machine); + ts->selection_channel_range_max = max_ii(ts->selection_channel_range_max, seq->machine); + } + } + #undef XXX_DURIAN_ANIM_TX_HACK } @@ -834,7 +845,7 @@ void special_aftertrans_update__sequencer(bContext *UNUSED(C), TransInfo *t) /* Marker transform, not especially nice but we may want to move markers * at the same time as strips in the Video Sequencer. */ if (sseq->flag & SEQ_MARKER_TRANS) { - /* cant use TFM_TIME_EXTEND + /* can't use TFM_TIME_EXTEND * for some reason EXTEND is changed into TRANSLATE, so use frame_side instead */ if (t->mode == TFM_SEQ_SLIDE) { @@ -850,6 +861,21 @@ void special_aftertrans_update__sequencer(bContext *UNUSED(C), TransInfo *t) } } +void transform_convert_sequencer_channel_clamp(TransInfo *t) +{ + const TransSeq *ts = (TransSeq *)TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data; + const int channel_offset = round_fl_to_int(t->values[1]); + const int min_channel_after_transform = ts->selection_channel_range_min + channel_offset; + const int max_channel_after_transform = ts->selection_channel_range_max + channel_offset; + + if (max_channel_after_transform > MAXSEQ) { + t->values[1] -= max_channel_after_transform - MAXSEQ; + } + if (min_channel_after_transform < 1) { + t->values[1] -= min_channel_after_transform - 1; + } +} + int transform_convert_sequencer_get_snap_bound(TransInfo *t) { TransSeq *ts = TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data; diff --git a/source/blender/editors/transform/transform_convert_tracking.c b/source/blender/editors/transform/transform_convert_tracking.c index c3f48adca68..5f5f06e388f 100644 --- a/source/blender/editors/transform/transform_convert_tracking.c +++ b/source/blender/editors/transform/transform_convert_tracking.c @@ -52,6 +52,7 @@ typedef struct TransDataTracking { float (*smarkers)[2]; int markersnr; + int framenr; MovieTrackingMarker *markers; /* marker transformation from curves editor */ @@ -73,9 +74,25 @@ enum transDataTracking_Mode { * * \{ */ -static void markerToTransDataInit(TransData *td, - TransData2D *td2d, - TransDataTracking *tdt, +typedef struct TransformInitContext { + SpaceClip *space_clip; + + TransInfo *t; + TransDataContainer *tc; + + /* NOTE: These pointers will be `nullptr` during counting step. + * This means, that the transformation data initialization functions are to increment + * `tc->data_len` instead of filling in the transformation data when these pointers are + * `nullptr`. For simplicity, check the `current.td` against `nullptr`. + * Do not `tc->data_len` when filling in the transformation data. */ + struct { + TransData *td; + TransData2D *td2d; + TransDataTracking *tdt; + } current; +} TransformInitContext; + +static void markerToTransDataInit(TransformInitContext *init_context, MovieTrackingTrack *track, MovieTrackingMarker *marker, int area, @@ -84,8 +101,19 @@ static void markerToTransDataInit(TransData *td, const float off[2], const float aspect[2]) { + TransData *td = init_context->current.td; + TransData2D *td2d = init_context->current.td2d; + TransDataTracking *tdt = init_context->current.tdt; + + if (td == NULL) { + init_context->tc->data_len++; + return; + } + int anchor = area == TRACK_AREA_POINT && off; + tdt->flag = marker->flag; + tdt->framenr = marker->framenr; tdt->mode = transDataTracking_ModeTracks; if (anchor) { @@ -143,23 +171,20 @@ static void markerToTransDataInit(TransData *td, unit_m3(td->mtx); unit_m3(td->smtx); + + init_context->current.td++; + init_context->current.td2d++; + init_context->current.tdt++; } -static void trackToTransData(const int framenr, - TransData *td, - TransData2D *td2d, - TransDataTracking *tdt, +static void trackToTransData(TransformInitContext *init_context, + const int framenr, MovieTrackingTrack *track, const float aspect[2]) { MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr); - tdt->flag = marker->flag; - marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED); - - markerToTransDataInit(td++, - td2d++, - tdt++, + markerToTransDataInit(init_context, track, marker, TRACK_AREA_POINT, @@ -170,16 +195,14 @@ static void trackToTransData(const int framenr, if (track->flag & SELECT) { markerToTransDataInit( - td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT, marker->pos, NULL, NULL, aspect); + init_context, track, marker, TRACK_AREA_POINT, marker->pos, NULL, NULL, aspect); } if (track->pat_flag & SELECT) { int a; for (a = 0; a < 4; a++) { - markerToTransDataInit(td++, - td2d++, - tdt++, + markerToTransDataInit(init_context, track, marker, TRACK_AREA_PAT, @@ -191,9 +214,7 @@ static void trackToTransData(const int framenr, } if (track->search_flag & SELECT) { - markerToTransDataInit(td++, - td2d++, - tdt++, + markerToTransDataInit(init_context, track, marker, TRACK_AREA_SEARCH, @@ -202,9 +223,7 @@ static void trackToTransData(const int framenr, NULL, aspect); - markerToTransDataInit(td++, - td2d++, - tdt++, + markerToTransDataInit(init_context, track, marker, TRACK_AREA_SEARCH, @@ -213,15 +232,43 @@ static void trackToTransData(const int framenr, NULL, aspect); } + + if (init_context->current.td != NULL) { + marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED); + } } -static void planeMarkerToTransDataInit(TransData *td, - TransData2D *td2d, - TransDataTracking *tdt, +static void trackToTransDataIfNeeded(TransformInitContext *init_context, + const int framenr, + MovieTrackingTrack *track, + const float aspect[2]) +{ + if (!TRACK_VIEW_SELECTED(init_context->space_clip, track)) { + return; + } + if (track->flag & TRACK_LOCKED) { + return; + } + trackToTransData(init_context, framenr, track, aspect); +} + +static void planeMarkerToTransDataInit(TransformInitContext *init_context, MovieTrackingPlaneTrack *plane_track, + MovieTrackingPlaneMarker *plane_marker, float corner[2], const float aspect[2]) { + TransData *td = init_context->current.td; + TransData2D *td2d = init_context->current.td2d; + TransDataTracking *tdt = init_context->current.tdt; + + if (td == NULL) { + init_context->tc->data_len++; + return; + } + + tdt->flag = plane_marker->flag; + tdt->framenr = plane_marker->framenr; tdt->mode = transDataTracking_ModePlaneTracks; tdt->plane_track = plane_track; @@ -247,24 +294,38 @@ static void planeMarkerToTransDataInit(TransData *td, unit_m3(td->mtx); unit_m3(td->smtx); + + init_context->current.td++; + init_context->current.td2d++; + init_context->current.tdt++; } -static void planeTrackToTransData(const int framenr, - TransData *td, - TransData2D *td2d, - TransDataTracking *tdt, +static void planeTrackToTransData(TransformInitContext *init_context, + const int framenr, MovieTrackingPlaneTrack *plane_track, const float aspect[2]) { MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr); - int i; - tdt->flag = plane_marker->flag; - plane_marker->flag &= ~PLANE_MARKER_TRACKED; + for (int i = 0; i < 4; i++) { + planeMarkerToTransDataInit( + init_context, plane_track, plane_marker, plane_marker->corners[i], aspect); + } - for (i = 0; i < 4; i++) { - planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspect); + if (init_context->current.td != NULL) { + plane_marker->flag &= ~PLANE_MARKER_TRACKED; + } +} + +static void planeTrackToTransDataIfNeeded(TransformInitContext *init_context, + const int framenr, + MovieTrackingPlaneTrack *plane_track, + const float aspect[2]) +{ + if (!PLANE_TRACK_VIEW_SELECTED(plane_track)) { + return; } + planeTrackToTransData(init_context, framenr, plane_track, aspect); } static void transDataTrackingFree(TransInfo *UNUSED(t), @@ -284,101 +345,53 @@ static void transDataTrackingFree(TransInfo *UNUSED(t), static void createTransTrackingTracksData(bContext *C, TransInfo *t) { - TransData *td; - TransData2D *td2d; - SpaceClip *sc = CTX_wm_space_clip(C); - MovieClip *clip = ED_space_clip_get_clip(sc); - ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); - ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); - MovieTrackingTrack *track; - MovieTrackingPlaneTrack *plane_track; - TransDataTracking *tdt; - int framenr = ED_space_clip_get_clip_frame_number(sc); + SpaceClip *space_clip = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(space_clip); + const ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); + const ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); + const int framenr = ED_space_clip_get_clip_frame_number(space_clip); TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); - /* count */ - tc->data_len = 0; - - track = tracksbase->first; - while (track) { - if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { - tc->data_len++; /* offset */ + TransformInitContext init_context = {NULL}; + init_context.space_clip = space_clip; + init_context.t = t; + init_context.tc = tc; - if (track->flag & SELECT) { - tc->data_len++; - } + /* Count required transformation data. */ - if (track->pat_flag & SELECT) { - tc->data_len += 4; - } - - if (track->search_flag & SELECT) { - tc->data_len += 2; - } - } + tc->data_len = 0; - track = track->next; + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { + trackToTransDataIfNeeded(&init_context, framenr, track, t->aspect); } - for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) { - if (PLANE_TRACK_VIEW_SELECTED(plane_track)) { - tc->data_len += 4; - } + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { + planeTrackToTransDataIfNeeded(&init_context, framenr, plane_track, t->aspect); } if (tc->data_len == 0) { return; } - td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData"); - td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), - "TransTracking TransData2D"); - tdt = tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataTracking), - "TransTracking TransDataTracking"); - + tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData"); + tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransTracking TransData2D"); + tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataTracking), + "TransTracking TransDataTracking"); tc->custom.type.free_cb = transDataTrackingFree; - /* create actual data */ - track = tracksbase->first; - while (track) { - if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { - trackToTransData(framenr, td, td2d, tdt, track, t->aspect); - - /* offset */ - td++; - td2d++; - tdt++; + init_context.current.td = tc->data; + init_context.current.td2d = tc->data_2d; + init_context.current.tdt = tc->custom.type.data; - if (track->flag & SELECT) { - td++; - td2d++; - tdt++; - } - - if (track->pat_flag & SELECT) { - td += 4; - td2d += 4; - tdt += 4; - } + /* Create actual transformation data. */ - if (track->search_flag & SELECT) { - td += 2; - td2d += 2; - tdt += 2; - } - } - - track = track->next; + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { + trackToTransDataIfNeeded(&init_context, framenr, track, t->aspect); } - for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) { - if (PLANE_TRACK_VIEW_SELECTED(plane_track)) { - planeTrackToTransData(framenr, td, td2d, tdt, plane_track, t->aspect); - td += 4; - td2d += 4; - tdt += 4; - } + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { + planeTrackToTransDataIfNeeded(&init_context, framenr, plane_track, t->aspect); } } @@ -560,17 +573,17 @@ void createTransTrackingData(bContext *C, TransInfo *t) static void cancelTransTracking(TransInfo *t) { TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); - SpaceClip *sc = t->area->spacedata.first; - int i, framenr = ED_space_clip_get_clip_frame_number(sc); TransDataTracking *tdt_array = tc->custom.type.data; - i = 0; + int i = 0; while (i < tc->data_len) { TransDataTracking *tdt = &tdt_array[i]; if (tdt->mode == transDataTracking_ModeTracks) { MovieTrackingTrack *track = tdt->track; - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, tdt->framenr); + + BLI_assert(marker != NULL); marker->flag = tdt->flag; @@ -606,7 +619,10 @@ static void cancelTransTracking(TransInfo *t) } else if (tdt->mode == transDataTracking_ModePlaneTracks) { MovieTrackingPlaneTrack *plane_track = tdt->plane_track; - MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr); + MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track, + tdt->framenr); + + BLI_assert(plane_marker != NULL); plane_marker->flag = tdt->flag; i += 3; diff --git a/source/blender/editors/transform/transform_data.h b/source/blender/editors/transform/transform_data.h index b59197fcd39..5b01433c96b 100644 --- a/source/blender/editors/transform/transform_data.h +++ b/source/blender/editors/transform/transform_data.h @@ -122,11 +122,11 @@ typedef struct TransDataCurveHandleFlags { typedef struct TransData { TRANSDATABASIC; - /** Distance needed to affect element (for Proportionnal Editing). */ + /** Distance needed to affect element (for Proportional Editing). */ float dist; - /** Distance to the nearest element (for Proportionnal Editing). */ + /** Distance to the nearest element (for Proportional Editing). */ float rdist; - /** Factor of the transformation (for Proportionnal Editing). */ + /** Factor of the transformation (for Proportional Editing). */ float factor; /** Value pointer for special transforms. */ float *val; @@ -141,11 +141,11 @@ typedef struct TransData { struct Object *ob; /** For objects/bones, the first constraint in its constraint stack. */ struct bConstraint *con; - /** For objects, poses. 1 single malloc per TransInfo! */ + /** For objects, poses. 1 single allocation per #TransInfo! */ TransDataExtension *ext; /** for curves, stores handle flags for modification/cancel. */ TransDataCurveHandleFlags *hdata; - /** If set, copy of Object or PoseChannel protection. */ + /** If set, copy of Object or #bPoseChannel protection. */ short protectflag; } TransData; diff --git a/source/blender/editors/transform/transform_draw_cursors.c b/source/blender/editors/transform/transform_draw_cursors.c index 84fc45e2b45..ead8eae0997 100644 --- a/source/blender/editors/transform/transform_draw_cursors.c +++ b/source/blender/editors/transform/transform_draw_cursors.c @@ -45,99 +45,45 @@ enum eArrowDirection { RIGHT, }; -struct ArrowDims { - int offset; - int length; - int size; -}; - -#define POS_INDEX 0 -/* NOTE: this --^ is a bit hackish, but simplifies GPUVertFormat usage among functions - * private to this file - merwin - */ +#define ARROW_WIDTH (2.0f * U.pixelsize) +#define DASH_WIDTH (1.0f) +#define DASH_LENGTH (8.0f * DASH_WIDTH * U.pixelsize) -static void drawArrow(enum eArrowDirection dir, const struct ArrowDims *arrow_dims) +static void drawArrow(const uint pos_id, const enum eArrowDirection dir) { - int offset = arrow_dims->offset; - int length = arrow_dims->length; - int size = arrow_dims->size; - - immBegin(GPU_PRIM_LINES, 6); - - switch (dir) { - case LEFT: - offset = -offset; - length = -length; - size = -size; - ATTR_FALLTHROUGH; - case RIGHT: - immVertex2f(POS_INDEX, offset, 0); - immVertex2f(POS_INDEX, offset + length, 0); - immVertex2f(POS_INDEX, offset + length, 0); - immVertex2f(POS_INDEX, offset + length - size, -size); - immVertex2f(POS_INDEX, offset + length, 0); - immVertex2f(POS_INDEX, offset + length - size, size); - break; - - case DOWN: - offset = -offset; - length = -length; - size = -size; - ATTR_FALLTHROUGH; - case UP: - immVertex2f(POS_INDEX, 0, offset); - immVertex2f(POS_INDEX, 0, offset + length); - immVertex2f(POS_INDEX, 0, offset + length); - immVertex2f(POS_INDEX, -size, offset + length - size); - immVertex2f(POS_INDEX, 0, offset + length); - immVertex2f(POS_INDEX, size, offset + length - size); - break; + int offset = 5.0f * UI_DPI_FAC; + int length = (6.0f * UI_DPI_FAC) + (4.0f * U.pixelsize); + int size = (3.0f * UI_DPI_FAC) + (2.0f * U.pixelsize); + + /* To line up the arrow point nicely, one end has to be extended by half its width. But + * being on a 45 degree angle, Pythagoras says a movement of sqrt(2)/2 * (line width /2) */ + float adjust = (M_SQRT2 * ARROW_WIDTH / 4.0f); + + if (ELEM(dir, LEFT, DOWN)) { + offset = -offset; + length = -length; + size = -size; + adjust = -adjust; } - immEnd(); -} - -static void drawArrowHead(enum eArrowDirection dir, int size) -{ - immBegin(GPU_PRIM_LINES, 4); - - switch (dir) { - case LEFT: - size = -size; - ATTR_FALLTHROUGH; - case RIGHT: - immVertex2f(POS_INDEX, 0, 0); - immVertex2f(POS_INDEX, -size, -size); - immVertex2f(POS_INDEX, 0, 0); - immVertex2f(POS_INDEX, -size, size); - break; + immBegin(GPU_PRIM_LINES, 6); - case DOWN: - size = -size; - ATTR_FALLTHROUGH; - case UP: - immVertex2f(POS_INDEX, 0, 0); - immVertex2f(POS_INDEX, -size, -size); - immVertex2f(POS_INDEX, 0, 0); - immVertex2f(POS_INDEX, size, -size); - break; + if (ELEM(dir, LEFT, RIGHT)) { + immVertex2f(pos_id, offset, 0); + immVertex2f(pos_id, offset + length, 0); + immVertex2f(pos_id, offset + length + adjust, adjust); + immVertex2f(pos_id, offset + length - size, -size); + immVertex2f(pos_id, offset + length, 0); + immVertex2f(pos_id, offset + length - size, size); } - - immEnd(); -} - -static void drawArc(float angle_start, float angle_end, int segments, float size) -{ - float delta = (angle_end - angle_start) / segments; - float angle; - int a; - - immBegin(GPU_PRIM_LINE_STRIP, segments + 1); - - for (angle = angle_start, a = 0; a < segments; angle += delta, a++) { - immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size); + else { + immVertex2f(pos_id, 0, offset); + immVertex2f(pos_id, 0, offset + length); + immVertex2f(pos_id, adjust, offset + length + adjust); + immVertex2f(pos_id, -size, offset + length - size); + immVertex2f(pos_id, 0, offset + length); + immVertex2f(pos_id, size, offset + length - size); } - immVertex2f(POS_INDEX, cosf(angle_end) * size, sinf(angle_end) * size); immEnd(); } @@ -149,11 +95,7 @@ static void drawArc(float angle_start, float angle_end, int segments, float size bool transform_draw_cursor_poll(bContext *C) { ARegion *region = CTX_wm_region(C); - - if (region && region->regiontype == RGN_TYPE_WINDOW) { - return 1; - } - return 0; + return (region && region->regiontype == RGN_TYPE_WINDOW) ? 1 : 0; } /** @@ -164,181 +106,117 @@ void transform_draw_cursor_draw(bContext *UNUSED(C), int x, int y, void *customd { TransInfo *t = (TransInfo *)customdata; - if (t->helpline != HLP_NONE) { - struct ArrowDims arrow_dims = { - .offset = 5 * UI_DPI_FAC, - .length = 10 * UI_DPI_FAC, - .size = 5 * UI_DPI_FAC, - }; - - float cent[2]; - const float mval[3] = {x, y, 0.0f}; - float tmval[2] = { - (float)t->mval[0], - (float)t->mval[1], - }; - - projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); - /* Offset the values for the area region. */ - const float offset[2] = { - t->region->winrct.xmin, - t->region->winrct.ymin, - }; - - for (int i = 0; i < 2; i++) { - cent[i] += offset[i]; - tmval[i] += offset[i]; - } - - GPU_line_smooth(true); - GPU_blend(GPU_BLEND_ALPHA); - - GPU_matrix_push(); - - /* Dashed lines first. */ - if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) { - const uint shdr_pos = GPU_vertformat_attr_add( - immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */ - BLI_assert(shdr_pos == POS_INDEX); + if (t->helpline == HLP_NONE) { + return; + } - GPU_line_width(1.0f); + float cent[2]; + const float mval[3] = {x, y, 0.0f}; + float tmval[2] = { + (float)t->mval[0], + (float)t->mval[1], + }; + + projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); + /* Offset the values for the area region. */ + const float offset[2] = { + t->region->winrct.xmin, + t->region->winrct.ymin, + }; + + for (int i = 0; i < 2; i++) { + cent[i] += offset[i]; + tmval[i] += offset[i]; + } - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + + GPU_line_smooth(true); + GPU_blend(GPU_BLEND_ALPHA); + const uint pos_id = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + /* Dashed lines first. */ + if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) { + GPU_line_width(DASH_WIDTH); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + immUniform1i("colors_len", 0); /* "simple" mode */ + immUniformThemeColor3(TH_VIEW_OVERLAY); + immUniform1f("dash_width", DASH_LENGTH); + immUniform1f("dash_factor", 0.5f); + immBegin(GPU_PRIM_LINES, 2); + immVertex2fv(pos_id, cent); + immVertex2f(pos_id, tmval[0], tmval[1]); + immEnd(); + immUnbindProgram(); + } - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + /* And now, solid lines. */ - immUniform1i("colors_len", 0); /* "simple" mode */ - immUniformThemeColor3(TH_VIEW_OVERLAY); - immUniform1f("dash_width", 6.0f * UI_DPI_FAC); - immUniform1f("dash_factor", 0.5f); + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); + immUniformThemeColor3(TH_VIEW_OVERLAY); + immUniform2fv("viewportSize", &viewport_size[2]); + immUniform1f("lineWidth", ARROW_WIDTH); - immBegin(GPU_PRIM_LINES, 2); - immVertex2fv(POS_INDEX, cent); - immVertex2f(POS_INDEX, tmval[0], tmval[1]); - immEnd(); + GPU_matrix_push(); + GPU_matrix_translate_3fv(mval); - immUnbindProgram(); + switch (t->helpline) { + case HLP_SPRING: + GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z'); + drawArrow(pos_id, UP); + drawArrow(pos_id, DOWN); + break; + case HLP_HARROW: + drawArrow(pos_id, RIGHT); + drawArrow(pos_id, LEFT); + break; + case HLP_VARROW: + drawArrow(pos_id, UP); + drawArrow(pos_id, DOWN); + break; + case HLP_CARROW: { + /* Draw arrow based on direction defined by custom-points. */ + const int *data = t->mouse.data; + const float angle = -atan2f(data[2] - data[0], data[3] - data[1]); + GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z'); + drawArrow(pos_id, UP); + drawArrow(pos_id, DOWN); + break; } - - /* And now, solid lines. */ - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - UNUSED_VARS_NDEBUG(pos); /* silence warning */ - BLI_assert(pos == POS_INDEX); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - switch (t->helpline) { - case HLP_SPRING: - immUniformThemeColor3(TH_VIEW_OVERLAY); - - GPU_matrix_translate_3fv(mval); - GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z'); - - GPU_line_width(3.0f); - drawArrow(UP, &arrow_dims); - drawArrow(DOWN, &arrow_dims); - break; - case HLP_HARROW: - immUniformThemeColor3(TH_VIEW_OVERLAY); - GPU_matrix_translate_3fv(mval); - - GPU_line_width(3.0f); - drawArrow(RIGHT, &arrow_dims); - drawArrow(LEFT, &arrow_dims); - break; - case HLP_VARROW: - immUniformThemeColor3(TH_VIEW_OVERLAY); - - GPU_matrix_translate_3fv(mval); - - GPU_line_width(3.0f); - drawArrow(UP, &arrow_dims); - drawArrow(DOWN, &arrow_dims); - break; - case HLP_CARROW: { - /* Draw arrow based on direction defined by custom-points. */ - immUniformThemeColor3(TH_VIEW_OVERLAY); - - GPU_matrix_translate_3fv(mval); - - GPU_line_width(3.0f); - - const int *data = t->mouse.data; - const float dx = data[2] - data[0], dy = data[3] - data[1]; - const float angle = -atan2f(dx, dy); - - GPU_matrix_push(); - - GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z'); - - drawArrow(UP, &arrow_dims); - drawArrow(DOWN, &arrow_dims); - - GPU_matrix_pop(); - break; - } - case HLP_ANGLE: { - float dx = tmval[0] - cent[0], dy = tmval[1] - cent[1]; - float angle = atan2f(dy, dx); - float dist = hypotf(dx, dy); - float delta_angle = min_ff(15.0f / (dist / UI_DPI_FAC), (float)M_PI / 4.0f); - float spacing_angle = min_ff(5.0f / (dist / UI_DPI_FAC), (float)M_PI / 12.0f); - - immUniformThemeColor3(TH_VIEW_OVERLAY); - - GPU_matrix_translate_3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0); - - GPU_line_width(3.0f); - drawArc(angle - delta_angle, angle - spacing_angle, 10, dist); - drawArc(angle + spacing_angle, angle + delta_angle, 10, dist); - - GPU_matrix_push(); - - GPU_matrix_translate_3f( - cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0); - GPU_matrix_rotate_axis(RAD2DEGF(angle - delta_angle), 'Z'); - - drawArrowHead(DOWN, arrow_dims.size); - - GPU_matrix_pop(); - - GPU_matrix_translate_3f( - cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0); - GPU_matrix_rotate_axis(RAD2DEGF(angle + delta_angle), 'Z'); - - drawArrowHead(UP, arrow_dims.size); - break; - } - case HLP_TRACKBALL: { - uchar col[3], col2[3]; - UI_GetThemeColor3ubv(TH_GRID, col); - - GPU_matrix_translate_3fv(mval); - - GPU_line_width(3.0f); - - UI_make_axis_color(col, col2, 'X'); - immUniformColor3ubv(col2); - - drawArrow(RIGHT, &arrow_dims); - drawArrow(LEFT, &arrow_dims); - - UI_make_axis_color(col, col2, 'Y'); - immUniformColor3ubv(col2); - - drawArrow(UP, &arrow_dims); - drawArrow(DOWN, &arrow_dims); - break; - } + case HLP_ANGLE: { + GPU_matrix_push(); + float angle = atan2f(tmval[1] - cent[1], tmval[0] - cent[0]); + GPU_matrix_translate_3f(cosf(angle), sinf(angle), 0); + GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z'); + drawArrow(pos_id, DOWN); + GPU_matrix_pop(); + GPU_matrix_translate_3f(cosf(angle), sinf(angle), 0); + GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z'); + drawArrow(pos_id, UP); + break; } - - immUnbindProgram(); - GPU_matrix_pop(); - - GPU_line_smooth(false); - GPU_blend(GPU_BLEND_NONE); + case HLP_TRACKBALL: { + uchar col[3], col2[3]; + UI_GetThemeColor3ubv(TH_GRID, col); + UI_make_axis_color(col, col2, 'X'); + immUniformColor3ubv(col2); + drawArrow(pos_id, RIGHT); + drawArrow(pos_id, LEFT); + UI_make_axis_color(col, col2, 'Y'); + immUniformColor3ubv(col2); + drawArrow(pos_id, UP); + drawArrow(pos_id, DOWN); + break; + } + case HLP_NONE: + break; } + + GPU_matrix_pop(); + immUnbindProgram(); + GPU_line_smooth(false); + GPU_blend(GPU_BLEND_NONE); } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index b092b3e3e0b..6fca49495e9 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -26,7 +26,6 @@ #include "MEM_guardedalloc.h" #include "DNA_gpencil_types.h" -#include "DNA_mesh_types.h" #include "BLI_blenlib.h" #include "BLI_math.h" @@ -44,6 +43,7 @@ #include "BKE_context.h" #include "BKE_layer.h" #include "BKE_mask.h" +#include "BKE_modifier.h" #include "BKE_paint.h" #include "ED_clip.h" @@ -119,79 +119,6 @@ void resetTransRestrictions(TransInfo *t) t->flag &= ~T_ALL_RESTRICTIONS; } -void initTransDataContainers_FromObjectData(TransInfo *t, - Object *obact, - Object **objects, - uint objects_len) -{ - const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT; - const short object_type = obact ? obact->type : -1; - - if ((object_mode & OB_MODE_EDIT) || (t->options & CTX_GPENCIL_STROKES) || - ((object_mode & OB_MODE_POSE) && (object_type == OB_ARMATURE))) { - if (t->data_container) { - MEM_freeN(t->data_container); - } - - bool free_objects = false; - if (objects == NULL) { - objects = BKE_view_layer_array_from_objects_in_mode( - t->view_layer, - (t->spacetype == SPACE_VIEW3D) ? t->view : NULL, - &objects_len, - { - .object_mode = object_mode, - .no_dup_data = true, - }); - free_objects = true; - } - - t->data_container = MEM_callocN(sizeof(*t->data_container) * objects_len, __func__); - t->data_container_len = objects_len; - - for (int i = 0; i < objects_len; i++) { - TransDataContainer *tc = &t->data_container[i]; - if (((t->flag & T_NO_MIRROR) == 0) && ((t->options & CTX_NO_MIRROR) == 0) && - (objects[i]->type == OB_MESH)) { - tc->use_mirror_axis_x = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_X) != 0; - tc->use_mirror_axis_y = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Y) != 0; - tc->use_mirror_axis_z = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Z) != 0; - } - - if (object_mode & OB_MODE_EDIT) { - tc->obedit = objects[i]; - /* Check needed for UV's */ - if ((t->flag & T_2D_EDIT) == 0) { - tc->use_local_mat = true; - } - } - else if (object_mode & OB_MODE_POSE) { - tc->poseobj = objects[i]; - tc->use_local_mat = true; - } - else if (t->options & CTX_GPENCIL_STROKES) { - tc->use_local_mat = true; - } - - if (tc->use_local_mat) { - BLI_assert((t->flag & T_2D_EDIT) == 0); - copy_m4_m4(tc->mat, objects[i]->obmat); - copy_m3_m4(tc->mat3, tc->mat); - /* for non-invertible scale matrices, invert_m4_m4_fallback() - * can still provide a valid pivot */ - invert_m4_m4_fallback(tc->imat, tc->mat); - invert_m3_m3(tc->imat3, tc->mat3); - normalize_m3_m3(tc->mat3_unit, tc->mat3); - } - /* Otherwise leave as zero. */ - } - - if (free_objects) { - MEM_freeN(objects); - } - } -} - /** * Setup internal data, mouse, vectors * @@ -225,7 +152,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->flag = 0; - if (obact && !(t->options & (CTX_CURSOR | CTX_TEXTURE)) && + if (obact && !(t->options & (CTX_CURSOR | CTX_TEXTURE_SPACE)) && ELEM(object_mode, OB_MODE_EDIT, OB_MODE_EDIT_GPENCIL)) { t->obedit_type = obact->type; } @@ -272,7 +199,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* Crease needs edge flag */ if (ELEM(t->mode, TFM_CREASE, TFM_BWEIGHT)) { - t->options |= CTX_EDGE; + t->options |= CTX_EDGE_DATA; } t->remove_on_cancel = false; @@ -1110,7 +1037,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) return true; } } - else if (t->flag & T_POSE) { + else if (t->options & CTX_POSE_BONE) { ViewLayer *view_layer = t->view_layer; Object *ob = OBACT(view_layer); if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) { @@ -1184,20 +1111,13 @@ void calculateCenter(TransInfo *t) } calculateCenterLocal(t, t->center_global); - /* avoid calculating again */ - { - TransCenterData *cd = &t->center_cache[t->around]; - copy_v3_v3(cd->global, t->center_global); - cd->is_set = true; - } - calculateCenter2D(t); - /* for panning from cameraview */ - if ((t->flag & T_OBJECT) && (t->flag & T_OVERRIDE_CENTER) == 0) { + /* For panning from the camera-view. */ + if ((t->options & CTX_OBJECT) && (t->flag & T_OVERRIDE_CENTER) == 0) { if (t->spacetype == SPACE_VIEW3D && t->region && t->region->regiontype == RGN_TYPE_WINDOW) { - if (t->flag & T_CAMERA) { + if (t->options & CTX_CAMERA) { float axis[3]; /* persinv is nasty, use viewinv instead, always right */ copy_v3_v3(axis, t->viewinv[2]); @@ -1237,23 +1157,6 @@ void calculateCenter(TransInfo *t) } } -BLI_STATIC_ASSERT(ARRAY_SIZE(((TransInfo *)NULL)->center_cache) == (V3D_AROUND_ACTIVE + 1), - "test size"); - -/** - * Lazy initialize transform center data, when we need to access center values from other types. - */ -const TransCenterData *transformCenter_from_type(TransInfo *t, int around) -{ - BLI_assert(around <= V3D_AROUND_ACTIVE); - TransCenterData *cd = &t->center_cache[around]; - if (cd->is_set == false) { - calculateCenter_FromAround(t, around, cd->global); - cd->is_set = true; - } - return cd; -} - void calculatePropRatio(TransInfo *t) { int i; @@ -1416,7 +1319,7 @@ void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot) if (td->ext->rotOrder == ROT_MODE_QUAT) { float quat[4]; - /* calculate the total rotatation */ + /* Calculate the total rotation. */ quat_to_mat3(obmat, td->ext->iquat); if (use_drot) { mul_m3_m3m3(obmat, dmat, obmat); @@ -1437,7 +1340,7 @@ void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot) else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { float axis[3], angle; - /* calculate the total rotatation */ + /* Calculate the total rotation. */ axis_angle_to_mat3(obmat, td->ext->irotAxis, td->ext->irotAngle); if (use_drot) { mul_m3_m3m3(obmat, dmat, obmat); @@ -1459,7 +1362,7 @@ void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot) else { float eul[3]; - /* calculate the total rotatation */ + /* Calculate the total rotation. */ eulO_to_mat3(obmat, td->ext->irot, td->ext->rotOrder); if (use_drot) { mul_m3_m3m3(obmat, dmat, obmat); @@ -1478,3 +1381,23 @@ void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot) copy_v3_v3(td->ext->rot, eul); } } + +Object *transform_object_deform_pose_armature_get(const TransInfo *t, Object *ob) +{ + if (!(ob->mode & OB_MODE_ALL_WEIGHT_PAINT)) { + return NULL; + } + /* Important that ob_armature can be set even when its not selected T23412. + * Lines below just check is also visible. */ + Object *ob_armature = BKE_modifiers_is_deformed_by_armature(ob); + if (ob_armature && ob_armature->mode & OB_MODE_POSE) { + Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature); + if (base_arm) { + View3D *v3d = t->view; + if (BASE_VISIBLE(v3d, base_arm)) { + return ob_armature; + } + } + } + return NULL; +} diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 9c08159cf07..27df29afd8d 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -532,7 +532,7 @@ static void protectflag_to_drawflags_ebone(RegionView3D *rv3d, const EditBone *e /* could move into BLI_math however this is only useful for display/editing purposes */ static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], const float angle) { - /* X/Y are arbitrary axies, most importantly Z is the axis of rotation */ + /* X/Y are arbitrary axes, most importantly Z is the axis of rotation. */ float cross_vec[3]; float quat[4]; @@ -704,7 +704,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) { /* skip strokes that are invalid for current view */ diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 70ef5fcde7a..bfeb96d18c4 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -499,28 +499,4 @@ void applyMouseInput(TransInfo *t, MouseInput *mi, const int mval[2], float outp } } -eRedrawFlag handleMouseInput(TransInfo *t, MouseInput *mi, const wmEvent *event) -{ - eRedrawFlag redraw = TREDRAW_NOTHING; - - switch (event->type) { - case EVT_LEFTSHIFTKEY: - case EVT_RIGHTSHIFTKEY: - if (event->val == KM_PRESS) { - t->modifiers |= MOD_PRECISION; - /* shift is modifier for higher precision transforn */ - mi->precision = 1; - redraw = TREDRAW_HARD; - } - else if (event->val == KM_RELEASE) { - t->modifiers &= ~MOD_PRECISION; - mi->precision = 0; - redraw = TREDRAW_HARD; - } - break; - } - - return redraw; -} - /** \} */ diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index a4d999b868d..9e6e4d8807e 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -70,7 +70,7 @@ int transform_mode_really_used(bContext *C, int mode) bool transdata_check_local_center(TransInfo *t, short around) { return ((around == V3D_AROUND_LOCAL_ORIGINS) && - ((t->flag & (T_OBJECT | T_POSE)) || + ((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)) || (t->spacetype == SPACE_GRAPH) || @@ -513,7 +513,7 @@ void constraintSizeLim(TransInfo *t, TransData *td) return; } - /* extrace scale from matrix and apply back sign */ + /* Extract scale from matrix and apply back sign. */ mat4_to_size(td->ext->size, cob.matrix); mul_v3_v3(td->ext->size, size_sign); } @@ -629,7 +629,7 @@ void ElementRotation_ex(TransInfo *t, * matrix (and inverse). That is not all though. Once the proper translation * has been computed, it has to be converted back into the bone's space. */ - else if (t->flag & T_POSE) { + else if (t->options & CTX_POSE_BONE) { /* Extract and invert armature object matrix */ if ((td->flag & TD_NO_LOC) == 0) { @@ -705,7 +705,7 @@ void ElementRotation_ex(TransInfo *t, mul_m3_m3m3(totmat, mat, td->ext->r_mtx); mul_m3_m3m3(smat, td->ext->r_smtx, totmat); - /* calculate the total rotatation in eulers */ + /* Calculate the total rotation in eulers. */ copy_v3_v3(eul, td->ext->irot); eulO_to_mat3(eulmat, eul, td->ext->rotOrder); @@ -778,7 +778,7 @@ void ElementRotation_ex(TransInfo *t, mul_m3_m3m3(totmat, mat, td->mtx); mul_m3_m3m3(smat, td->smtx, totmat); - /* calculate the total rotatation in eulers */ + /* Calculate the total rotation in eulers. */ add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* correct for delta rot */ eulO_to_mat3(obmat, eul, td->ext->rotOrder); /* mat = transform, obmat = object rotation */ @@ -902,7 +902,7 @@ static void TransMat3ToSize(const float mat[3][3], const float smat[3][3], float mat3_to_rot_size(rmat, size, mat); - /* first tried with dotproduct... but the sign flip is crucial */ + /* First tried with dot-product... but the sign flip is crucial. */ if (dot_v3v3(rmat[0], smat[0]) < 0.0f) { size[0] = -size[0]; } @@ -1026,7 +1026,7 @@ void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float ma mul_v3_fl(vec, td->factor); } - if (t->flag & (T_OBJECT | T_POSE)) { + if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) { mul_m3_v3(td->smtx, vec); } diff --git a/source/blender/editors/transform/transform_mode_align.c b/source/blender/editors/transform/transform_mode_align.c index f16021914f1..5bc2aa68443 100644 --- a/source/blender/editors/transform/transform_mode_align.c +++ b/source/blender/editors/transform/transform_mode_align.c @@ -55,7 +55,7 @@ static void applyAlign(TransInfo *t, const int UNUSED(mval[2])) } /* around local centers */ - if (t->flag & (T_OBJECT | T_POSE)) { + if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) { copy_v3_v3(tc->center_local, td->center); } else { diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c index 7ccfd0149bd..4330d5e79be 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -35,10 +35,12 @@ #include "WM_types.h" #include "UI_interface.h" +#include "UI_view2d.h" #include "BLT_translation.h" #include "transform.h" +#include "transform_convert.h" #include "transform_mode.h" #include "transform_snap.h" @@ -49,9 +51,9 @@ static eRedrawFlag seq_slide_handleEvent(struct TransInfo *t, const wmEvent *event) { BLI_assert(t->mode == TFM_SEQ_SLIDE); - wmKeyMapItem *kmi = t->custom.mode.data; + const wmKeyMapItem *kmi = t->custom.mode.data; if (kmi && event->type == kmi->type && event->val == kmi->val) { - /* Allows the 'Expand to fit' effect to be enabled as a toogle. */ + /* Allows the "Expand to Fit" effect to be enabled as a toggle. */ t->flag ^= T_ALT_TRANSFORM; return TREDRAW_HARD; } @@ -73,7 +75,7 @@ static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRA ofs += BLI_snprintf( str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text); - wmKeyMapItem *kmi = t->custom.mode.data; + const wmKeyMapItem *kmi = t->custom.mode.data; if (kmi) { ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs); } @@ -106,6 +108,7 @@ static void applySeqSlide(TransInfo *t, const int mval[2]) float values_final[3] = {0.0f}; snapSequenceBounds(t, mval); + transform_convert_sequencer_channel_clamp(t); if (applyNumInput(&t->num, values_final)) { if (t->con.mode & CON_APPLY) { if (t->con.mode & CON_AXIS0) { @@ -158,7 +161,7 @@ void initSeqSlide(TransInfo *t) if (t->keymap) { /* Workaround to use the same key as the modal keymap. */ - t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); + t->custom.mode.data = (void *)WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); } } /** \} */ diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index dae3fe6f7b4..dff9ded6b29 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -143,7 +143,7 @@ static BMEdge *get_other_edge(BMVert *v, BMEdge *e) return NULL; } -/* interpoaltes along a line made up of 2 segments (used for edge slide) */ +/* Interpolates along a line made up of 2 segments (used for edge slide). */ static void interp_line_v3_v3v3v3( float p[3], const float v1[3], const float v2[3], const float v3[3], float t) { diff --git a/source/blender/editors/transform/transform_mode_mirror.c b/source/blender/editors/transform/transform_mode_mirror.c index 3aa99975fda..9891af8b9a4 100644 --- a/source/blender/editors/transform/transform_mode_mirror.c +++ b/source/blender/editors/transform/transform_mode_mirror.c @@ -152,7 +152,7 @@ static void ElementMirror(TransInfo *t, TransDataContainer *tc, TransData *td, i sub_v3_v3(vec, td->center); } - if (t->flag & (T_OBJECT | T_POSE)) { + if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) { mul_m3_v3(td->smtx, vec); } diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c index 62a4fbd6f04..4d0bb7fbe9c 100644 --- a/source/blender/editors/transform/transform_mode_resize.c +++ b/source/blender/editors/transform/transform_mode_resize.c @@ -132,7 +132,7 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2])) } } - /* evil hack - redo resize if cliping needed */ + /* Evil hack - redo resize if clipping needed. */ if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values_final, 1)) { size_to_mat3(mat, t->values_final); diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c index ba5b1229f3e..6e497d85417 100644 --- a/source/blender/editors/transform/transform_mode_shrink_fatten.c +++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c @@ -49,9 +49,9 @@ static eRedrawFlag shrinkfatten_handleEvent(struct TransInfo *t, const wmEvent *event) { BLI_assert(t->mode == TFM_SHRINKFATTEN); - wmKeyMapItem *kmi = t->custom.mode.data; + const wmKeyMapItem *kmi = t->custom.mode.data; if (kmi && event->type == kmi->type && event->val == kmi->val) { - /* Allows the 'Even Thickness' effect to be enabled as a toogle. */ + /* Allows the "Even Thickness" effect to be enabled as a toggle. */ t->flag ^= T_ALT_TRANSFORM; return TREDRAW_HARD; } @@ -84,8 +84,13 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) else { /* default header print */ if (unit != NULL) { - ofs += BKE_unit_value_as_string( - str + ofs, sizeof(str) - ofs, distance * unit->scale_length, 4, B_UNIT_LENGTH, unit, true); + ofs += BKE_unit_value_as_string(str + ofs, + sizeof(str) - ofs, + distance * unit->scale_length, + 4, + B_UNIT_LENGTH, + unit, + true); } else { ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f", distance); @@ -97,7 +102,7 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) } ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs); - wmKeyMapItem *kmi = t->custom.mode.data; + const wmKeyMapItem *kmi = t->custom.mode.data; if (kmi) { ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs); } @@ -157,7 +162,7 @@ void initShrinkFatten(TransInfo *t) if (t->keymap) { /* Workaround to use the same key as the modal keymap. */ - t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); + t->custom.mode.data = (void *)WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); } } } diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 851e0feb5f5..41fc6ee0aaf 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -294,7 +294,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) const float *original_normal; /* In pose mode, we want to align normals with Y axis of bones... */ - if (t->flag & T_POSE) { + if (t->options & CTX_POSE_BONE) { original_normal = td->axismtx[1]; } else { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 15c215c426d..01c00247a7a 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -411,7 +411,7 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) int exit_code; TransInfo *t = op->customdata; - const enum TfmMode mode_prev = t->mode; + const eTfmMode mode_prev = t->mode; #if defined(WITH_INPUT_NDOF) && 0 /* Stable 2D mouse coords map to different 3D coords while the 3D mouse is active @@ -432,7 +432,7 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) * since we're not reading from 'td->center' in this case. see: T40241 */ if (t->tsnap.target == SCE_SNAP_TARGET_ACTIVE) { /* In camera view, tsnap callback is not set - * (see initSnappingMode() in transfrom_snap.c, and T40348). */ + * (see #initSnappingMode() in transform_snap.c, and T40348). */ if (t->tsnap.targetSnap && ((t->tsnap.status & TARGET_INIT) == 0)) { t->tsnap.targetSnap(t); } @@ -444,7 +444,7 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) if ((exit_code & OPERATOR_RUNNING_MODAL) == 0) { transformops_exit(C, op); - exit_code &= ~OPERATOR_PASS_THROUGH; /* preventively remove passthrough */ + exit_code &= ~OPERATOR_PASS_THROUGH; /* Preventively remove pass-through. */ } else { if (mode_prev != t->mode) { diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 3b39f4d06ad..1470d3b7059 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -521,23 +521,19 @@ short ED_transform_calc_orientation_from_type_ex(const bContext *C, const int pivot_point) { switch (orientation_type) { - case V3D_ORIENT_GLOBAL: { - unit_m3(r_mat); - return V3D_ORIENT_GLOBAL; - } case V3D_ORIENT_GIMBAL: { if (ob && gimbal_axis(ob, r_mat)) { - return V3D_ORIENT_GIMBAL; + break; } - /* if not gimbal, fall through to normal */ + /* If not gimbal, fall through to normal. */ ATTR_FALLTHROUGH; } case V3D_ORIENT_NORMAL: { if (obedit || (ob && ob->mode & OB_MODE_POSE)) { ED_getTransformOrientationMatrix(C, ob, obedit, pivot_point, r_mat); - return V3D_ORIENT_NORMAL; + break; } - /* no break we define 'normal' as 'local' in Object mode */ + /* No break we define 'normal' as 'local' in Object mode. */ ATTR_FALLTHROUGH; } case V3D_ORIENT_LOCAL: { @@ -552,10 +548,14 @@ short ED_transform_calc_orientation_from_type_ex(const bContext *C, else { transform_orientations_create_from_axis(r_mat, UNPACK3(ob->obmat)); } - return V3D_ORIENT_LOCAL; + break; } + /* If not local, fall through to global. */ + ATTR_FALLTHROUGH; + } + case V3D_ORIENT_GLOBAL: { unit_m3(r_mat); - return V3D_ORIENT_GLOBAL; + break; } case V3D_ORIENT_VIEW: { if (rv3d != NULL) { @@ -565,11 +565,11 @@ short ED_transform_calc_orientation_from_type_ex(const bContext *C, else { unit_m3(r_mat); } - return V3D_ORIENT_VIEW; + break; } case V3D_ORIENT_CURSOR: { BKE_scene_cursor_rot_to_mat3(&scene->cursor, r_mat); - return V3D_ORIENT_CURSOR; + break; } case V3D_ORIENT_CUSTOM_MATRIX: { /* Do nothing. */; @@ -609,6 +609,12 @@ short transform_orientation_matrix_get( orientation_index_custom = orientation - V3D_ORIENT_CUSTOM; orientation = V3D_ORIENT_CUSTOM; } + else if (ob && (ob->mode & OB_MODE_ALL_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) { + Object *ob_armature = transform_object_deform_pose_armature_get(t, ob); + if (ob_armature) { + ob = ob_armature; + } + } if ((t->spacetype == SPACE_VIEW3D) && t->region && (t->region->regiontype == RGN_TYPE_WINDOW)) { rv3d = t->region->regiondata; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index c19dd4598cf..6d04de34016 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -235,7 +235,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t) } else if (t->spacetype == SPACE_IMAGE) { if (validSnap(t)) { - /* This will not draw, and Im nor sure why - campbell */ + /* This will not draw, and I'm nor sure why - campbell */ /* TODO: see 2.7x for non-working code */ } } @@ -299,83 +299,93 @@ eRedrawFlag handleSnapping(TransInfo *t, const wmEvent *event) void applyProject(TransInfo *t) { - /* XXX FLICKER IN OBJECT MODE */ - if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) { - float tvec[3]; - int i; + if (!t->tsnap.project) { + return; + } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - float iloc[3], loc[3], no[3]; - float mval_fl[2]; - if (td->flag & TD_SKIP) { - continue; - } + if (!activeSnap(t) || (t->flag & T_NO_PROJECT)) { + return; + } - if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { - continue; - } + if (doForceIncrementSnap(t)) { + return; + } - copy_v3_v3(iloc, td->loc); - if (tc->use_local_mat) { - mul_m4_v3(tc->mat, iloc); - } - else if (t->flag & T_OBJECT) { - BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); - copy_v3_v3(iloc, td->ob->obmat[3]); - } + float tvec[3]; + int i; - if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) == - V3D_PROJ_RET_OK) { - if (ED_transform_snap_object_project_view3d( - t->tsnap.object_context, - t->depsgraph, - SCE_SNAP_MODE_FACE, - &(const struct SnapObjectParams){ - .snap_select = t->tsnap.modeSelect, - .use_object_edit_cage = (t->flag & T_EDIT) != 0, - .use_occlusion_test = false, - .use_backface_culling = t->tsnap.use_backface_culling, - }, - mval_fl, - NULL, - 0, - loc, - no)) { + /* XXX FLICKER IN OBJECT MODE */ + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + float iloc[3], loc[3], no[3]; + float mval_fl[2]; + if (td->flag & TD_SKIP) { + continue; + } + + if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { + continue; + } + + copy_v3_v3(iloc, td->loc); + if (tc->use_local_mat) { + mul_m4_v3(tc->mat, iloc); + } + else if (t->options & CTX_OBJECT) { + BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); + copy_v3_v3(iloc, td->ob->obmat[3]); + } + + if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) == + V3D_PROJ_RET_OK) { + if (ED_transform_snap_object_project_view3d( + t->tsnap.object_context, + t->depsgraph, + SCE_SNAP_MODE_FACE, + &(const struct SnapObjectParams){ + .snap_select = t->tsnap.modeSelect, + .use_object_edit_cage = (t->flag & T_EDIT) != 0, + .use_occlusion_test = false, + .use_backface_culling = t->tsnap.use_backface_culling, + }, + mval_fl, + NULL, + 0, + loc, + no)) { #if 0 if (tc->use_local_mat) { mul_m4_v3(tc->imat, loc); } #endif - sub_v3_v3v3(tvec, loc, iloc); + sub_v3_v3v3(tvec, loc, iloc); - mul_m3_v3(td->smtx, tvec); + mul_m3_v3(td->smtx, tvec); - add_v3_v3(td->loc, tvec); + add_v3_v3(td->loc, tvec); - if (t->tsnap.align && (t->flag & T_OBJECT)) { - /* handle alignment as well */ - const float *original_normal; - float mat[3][3]; + if (t->tsnap.align && (t->options & CTX_OBJECT)) { + /* handle alignment as well */ + const float *original_normal; + float mat[3][3]; - /* In pose mode, we want to align normals with Y axis of bones... */ - original_normal = td->axismtx[2]; + /* In pose mode, we want to align normals with Y axis of bones... */ + original_normal = td->axismtx[2]; - rotation_between_vecs_to_mat3(mat, original_normal, no); + rotation_between_vecs_to_mat3(mat, original_normal, no); - transform_data_ext_rotate(td, mat, true); + transform_data_ext_rotate(td, mat, true); - /* TODO support constraints for rotation too? see ElementRotation */ - } + /* TODO support constraints for rotation too? see ElementRotation */ } } + } -#if 0 /* TODO: sipport this? */ +#if 0 /* TODO: support this? */ constraintTransLim(t, td); #endif - } } } } @@ -412,7 +422,7 @@ void applyGridAbsolute(TransInfo *t) if (tc->use_local_mat) { mul_m4_v3(tc->mat, iloc); } - else if (t->flag & T_OBJECT) { + else if (t->options & CTX_OBJECT) { BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); copy_v3_v3(iloc, td->ob->obmat[3]); } @@ -561,7 +571,8 @@ static void initSnappingMode(TransInfo *t) } } - if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && (t->flag & T_CAMERA) == 0) { + if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && + (t->options & CTX_CAMERA) == 0) { /* Only 3D view or UV. */ /* Not with camera selected in camera view. */ @@ -916,6 +927,64 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) /** \name Target * \{ */ +static void snap_target_median_impl(TransInfo *t, float r_median[3]) +{ + int i_accum = 0; + + zero_v3(r_median); + + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + int i; + float v[3]; + zero_v3(v); + + for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) { + add_v3_v3(v, td->center); + } + + if (i == 0) { + /* Is this possible? */ + continue; + } + + mul_v3_fl(v, 1.0 / i); + + if (tc->use_local_mat) { + mul_m4_v3(tc->mat, v); + } + + add_v3_v3(r_median, v); + i_accum++; + } + + mul_v3_fl(r_median, 1.0 / i_accum); + + // TargetSnapOffset(t, NULL); +} + +static void snap_target_grid_ensure(TransInfo *t) +{ + /* Only need to calculate once. */ + if ((t->tsnap.status & TARGET_GRID_INIT) == 0) { + if (t->data_type == TC_CURSOR_VIEW3D) { + /* Use a fallback when transforming the cursor. + * In this case the center is _not_ derived from the cursor which is being transformed. */ + copy_v3_v3(t->tsnap.snapTargetGrid, TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->data->iloc); + } + else if (t->around == V3D_AROUND_CURSOR) { + /* Use a fallback for cursor selection, + * this isn't useful as a global center for absolute grid snapping + * since its not based on the position of the selection. */ + snap_target_median_impl(t, t->tsnap.snapTargetGrid); + } + else { + copy_v3_v3(t->tsnap.snapTargetGrid, t->center_global); + } + t->tsnap.status |= TARGET_GRID_INIT; + } +} + static void TargetSnapOffset(TransInfo *t, TransData *td) { if (t->spacetype == SPACE_NODE && td != NULL) { @@ -987,41 +1056,7 @@ static void TargetSnapMedian(TransInfo *t) { /* Only need to calculate once. */ if ((t->tsnap.status & TARGET_INIT) == 0) { - int i_accum = 0; - - t->tsnap.snapTarget[0] = 0; - t->tsnap.snapTarget[1] = 0; - t->tsnap.snapTarget[2] = 0; - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - int i; - float v[3]; - zero_v3(v); - - for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) { - add_v3_v3(v, td->center); - } - - if (i == 0) { - /* Is this possible? */ - continue; - } - - mul_v3_fl(v, 1.0 / i); - - if (tc->use_local_mat) { - mul_m4_v3(tc->mat, v); - } - - add_v3_v3(t->tsnap.snapTarget, v); - i_accum++; - } - - mul_v3_fl(t->tsnap.snapTarget, 1.0 / i_accum); - - TargetSnapOffset(t, NULL); - + snap_target_median_impl(t, t->tsnap.snapTarget); t->tsnap.status |= TARGET_INIT; } } @@ -1034,7 +1069,7 @@ static void TargetSnapClosest(TransInfo *t) TransData *closest = NULL; /* Object mode */ - if (t->flag & T_OBJECT) { + if (t->options & CTX_OBJECT) { int i; FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; @@ -1421,28 +1456,10 @@ static void snap_grid_apply( TransInfo *t, const int max_index, const float grid_dist, const float loc[3], float r_out[3]) { BLI_assert(max_index <= 2); - const float *center_global = t->center_global; + snap_target_grid_ensure(t); + const float *center_global = t->tsnap.snapTargetGrid; const float *asp = t->aspect; - if (t->options & CTX_CURSOR) { - /* Note that we must already have called #transformCenter_from_type, otherwise - * we would be lazy-initializing data which is being transformed, - * causing the transformed cursor location to be used instead of it's initial location. */ - BLI_assert(t->center_cache[V3D_AROUND_CURSOR].is_set); - - /* Use a fallback when transforming the cursor. - * In this case the center is _not_ derived from the cursor which is being transformed. */ - const TransCenterData *cd = transformCenter_from_type(t, V3D_AROUND_CURSOR); - center_global = cd->global; - } - else if (t->around == V3D_AROUND_CURSOR) { - /* Use a fallback for cursor selection, - * this isn't useful as a global center for absolute grid snapping - * since its not based on the position of the selection. */ - const TransCenterData *cd = transformCenter_from_type(t, V3D_AROUND_CENTER_MEDIAN); - center_global = cd->global; - } - float in[3]; if (t->con.mode & CON_APPLY) { BLI_assert(t->tsnap.snapElem == 0); diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index b610369f82d..58198f21ba2 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1959,7 +1959,7 @@ static short snapCurve(SnapData *snapdata, int clip_plane_len = snapdata->clip_plane_len; if (snapdata->has_occlusion_plane) { - /* We snap to vertices even if coccluded. */ + /* We snap to vertices even if occluded. */ clip_planes++; clip_plane_len--; } diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index 533416bf85e..baa178a6a94 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -169,16 +169,16 @@ void ED_undo_push(bContext *C, const char *str) } /** - * \note Also check #undo_history_exec in bottom if you change notifiers. + * Common pre management of undo/redo (killing all running jobs, calling pre handlers, etc.). */ -static int ed_undo_step_impl( - bContext *C, int step, const char *undoname, int undo_index, ReportList *reports) +static void ed_undo_step_pre(bContext *C, + wmWindowManager *wm, + const enum eUndoStepDir undo_dir, + ReportList *reports) { - /* Mutually exclusives, ensure correct input. */ - BLI_assert(((undoname || undo_index != -1) && !step) || - (!(undoname || undo_index != -1) && step)); - CLOG_INFO(&LOG, 1, "name='%s', step=%d", undoname, step); - wmWindowManager *wm = CTX_wm_manager(C); + BLI_assert(ELEM(undo_dir, STEP_UNDO, STEP_REDO)); + + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ScrArea *area = CTX_wm_area(C); @@ -187,18 +187,12 @@ static int ed_undo_step_impl( WM_jobs_kill_all(wm); if (G.debug & G_DEBUG_IO) { - Main *bmain = CTX_data_main(C); if (bmain->lock != NULL) { BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *BEFORE* undo step"); BLO_main_validate_libraries(bmain, reports); } } - /* TODO(campbell): undo_system: use undo system */ - /* grease pencil can be can be used in plenty of spaces, so check it first */ - if (ED_gpencil_session_active()) { - return ED_undo_gpencil_step(C, step, undoname); - } if (area && (area->spacetype == SPACE_VIEW3D)) { Object *obact = CTX_data_active_object(C); if (obact && (obact->type == OB_GPENCIL)) { @@ -206,89 +200,40 @@ static int ed_undo_step_impl( } } - UndoStep *step_data_from_name = NULL; - int step_for_callback = step; - if (undoname != NULL) { - step_data_from_name = BKE_undosys_step_find_by_name(wm->undo_stack, undoname); - if (step_data_from_name == NULL) { - return OPERATOR_CANCELLED; - } - - /* TODO(campbell), could use simple optimization. */ - /* Pointers match on redo. */ - step_for_callback = (BLI_findindex(&wm->undo_stack->steps, step_data_from_name) < - BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active)) ? - 1 : - -1; - } - else if (undo_index != -1) { - step_for_callback = (undo_index < - BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active)) ? - 1 : - -1; - } - /* App-Handlers (pre). */ { /* Note: ignore grease pencil for now. */ - Main *bmain = CTX_data_main(C); wm->op_undo_depth++; BKE_callback_exec_id( - bmain, &scene->id, (step_for_callback > 0) ? BKE_CB_EVT_UNDO_PRE : BKE_CB_EVT_REDO_PRE); + bmain, &scene->id, (undo_dir == STEP_UNDO) ? BKE_CB_EVT_UNDO_PRE : BKE_CB_EVT_REDO_PRE); wm->op_undo_depth--; } +} - /* Undo System */ - { - if (undoname) { - BKE_undosys_step_undo_with_data(wm->undo_stack, C, step_data_from_name); - } - else if (undo_index != -1) { - BKE_undosys_step_undo_from_index(wm->undo_stack, C, undo_index); - } - else { - if (step == 1) { - BKE_undosys_step_undo(wm->undo_stack, C); - } - else { - BKE_undosys_step_redo(wm->undo_stack, C); - } - } +/** + * Common post management of undo/redo (calling post handlers, adding notifiers etc.). + * + * \note Also check #undo_history_exec in bottom if you change notifiers. + */ +static void ed_undo_step_post(bContext *C, + wmWindowManager *wm, + const enum eUndoStepDir undo_dir, + ReportList *reports) +{ + BLI_assert(ELEM(undo_dir, STEP_UNDO, STEP_REDO)); - /* Set special modes for grease pencil */ - if (area && (area->spacetype == SPACE_VIEW3D)) { - Object *obact = CTX_data_active_object(C); - if (obact && (obact->type == OB_GPENCIL)) { - /* set cursor */ - if (ELEM(obact->mode, - OB_MODE_PAINT_GPENCIL, - OB_MODE_SCULPT_GPENCIL, - OB_MODE_WEIGHT_GPENCIL, - OB_MODE_VERTEX_GPENCIL)) { - ED_gpencil_toggle_brush_cursor(C, true, NULL); - } - else { - ED_gpencil_toggle_brush_cursor(C, false, NULL); - } - /* set workspace mode */ - Base *basact = CTX_data_active_base(C); - ED_object_base_activate(C, basact); - } - } - } + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); /* App-Handlers (post). */ { - Main *bmain = CTX_data_main(C); - scene = CTX_data_scene(C); wm->op_undo_depth++; BKE_callback_exec_id( - bmain, &scene->id, step_for_callback > 0 ? BKE_CB_EVT_UNDO_POST : BKE_CB_EVT_REDO_POST); + bmain, &scene->id, (undo_dir == STEP_UNDO) ? BKE_CB_EVT_UNDO_POST : BKE_CB_EVT_REDO_POST); wm->op_undo_depth--; } if (G.debug & G_DEBUG_IO) { - Main *bmain = CTX_data_main(C); if (bmain->lock != NULL) { BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *AFTER* undo step"); BLO_main_validate_libraries(bmain, reports); @@ -299,30 +244,123 @@ static int ed_undo_step_impl( WM_event_add_notifier(C, NC_WM | ND_UNDO, NULL); WM_toolsystem_refresh_active(C); - - Main *bmain = CTX_data_main(C); WM_toolsystem_refresh_screen_all(bmain); if (CLOG_CHECK(&LOG, 1)) { BKE_undosys_print(wm->undo_stack); } - - return OPERATOR_FINISHED; } -static int ed_undo_step_direction(bContext *C, int step, ReportList *reports) +/** Undo or redo one step from current active one. + * May undo or redo several steps at once only if the target step is a 'skipped' one. + * The target step will be the one immediately before or after the active one. */ +static int ed_undo_step_direction(bContext *C, enum eUndoStepDir step, ReportList *reports) { - return ed_undo_step_impl(C, step, NULL, -1, reports); + BLI_assert(ELEM(step, STEP_UNDO, STEP_REDO)); + + CLOG_INFO(&LOG, 1, "direction=%s", (step == STEP_UNDO) ? "STEP_UNDO" : "STEP_REDO"); + + /* TODO(campbell): undo_system: use undo system */ + /* grease pencil can be can be used in plenty of spaces, so check it first */ + /* FIXME: This gpencil undo effectively only supports the one step undo/redo, undo based on name + * or index is fully not implemented. + * FIXME: However, it seems to never be used in current code (`ED_gpencil_session_active` seems + * to always return false). */ + if (ED_gpencil_session_active()) { + return ED_undo_gpencil_step(C, step); + } + + wmWindowManager *wm = CTX_wm_manager(C); + + ed_undo_step_pre(C, wm, step, reports); + + if (step == STEP_UNDO) { + BKE_undosys_step_undo(wm->undo_stack, C); + } + else { + BKE_undosys_step_redo(wm->undo_stack, C); + } + + ed_undo_step_post(C, wm, step, reports); + + return OPERATOR_FINISHED; } +/** Undo the step matching given name. + * May undo several steps at once. + * The target step will be the one immediately before given named one. */ static int ed_undo_step_by_name(bContext *C, const char *undo_name, ReportList *reports) { - return ed_undo_step_impl(C, 0, undo_name, -1, reports); + BLI_assert(undo_name != NULL); + + /* FIXME: See comments in `ed_undo_step_direction`. */ + if (ED_gpencil_session_active()) { + BLI_assert(!"Not implemented currently."); + } + + wmWindowManager *wm = CTX_wm_manager(C); + UndoStep *undo_step_from_name = BKE_undosys_step_find_by_name(wm->undo_stack, undo_name); + if (undo_step_from_name == NULL) { + CLOG_ERROR(&LOG, "Step name='%s' not found in current undo stack", undo_name); + + return OPERATOR_CANCELLED; + } + + UndoStep *undo_step_target = undo_step_from_name->prev; + if (undo_step_target == NULL) { + CLOG_ERROR(&LOG, "Step name='%s' cannot be undone", undo_name); + + return OPERATOR_CANCELLED; + } + + const int undo_dir_i = BKE_undosys_step_calc_direction(wm->undo_stack, undo_step_target, NULL); + BLI_assert(ELEM(undo_dir_i, -1, 1)); + const enum eUndoStepDir undo_dir = (undo_dir_i == -1) ? STEP_UNDO : STEP_REDO; + + CLOG_INFO(&LOG, + 1, + "name='%s', found direction=%s", + undo_name, + (undo_dir == STEP_UNDO) ? "STEP_UNDO" : "STEP_REDO"); + + ed_undo_step_pre(C, wm, undo_dir, reports); + + BKE_undosys_step_load_data_ex(wm->undo_stack, C, undo_step_target, NULL, true); + + ed_undo_step_post(C, wm, undo_dir, reports); + + return OPERATOR_FINISHED; } -static int ed_undo_step_by_index(bContext *C, int index, ReportList *reports) +/** Load the step matching given index in the stack. + * May undo or redo several steps at once. + * The target step will be the one indicated by the given index. */ +static int ed_undo_step_by_index(bContext *C, const int undo_index, ReportList *reports) { - return ed_undo_step_impl(C, 0, NULL, index, reports); + BLI_assert(undo_index >= 0); + + /* FIXME: See comments in `ed_undo_step_direction`. */ + if (ED_gpencil_session_active()) { + BLI_assert(!"Not implemented currently."); + } + + wmWindowManager *wm = CTX_wm_manager(C); + const int active_step_index = BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active); + const enum eUndoStepDir undo_dir = (undo_index < active_step_index) ? STEP_UNDO : STEP_REDO; + + CLOG_INFO(&LOG, + 1, + "index='%d', found direction=%s", + undo_index, + (undo_dir == STEP_UNDO) ? "STEP_UNDO" : "STEP_REDO"); + + ed_undo_step_pre(C, wm, undo_dir, reports); + + BKE_undosys_step_load_from_index(wm->undo_stack, C, undo_index); + + ed_undo_step_post(C, wm, undo_dir, reports); + + return OPERATOR_FINISHED; } void ED_undo_grouped_push(bContext *C, const char *str) @@ -340,11 +378,11 @@ void ED_undo_grouped_push(bContext *C, const char *str) void ED_undo_pop(bContext *C) { - ed_undo_step_direction(C, 1, NULL); + ed_undo_step_direction(C, STEP_UNDO, NULL); } void ED_undo_redo(bContext *C) { - ed_undo_step_direction(C, -1, NULL); + ed_undo_step_direction(C, STEP_REDO, NULL); } void ED_undo_push_op(bContext *C, wmOperator *op) @@ -448,7 +486,7 @@ static int ed_undo_exec(bContext *C, wmOperator *op) { /* "last operator" should disappear, later we can tie this with undo stack nicer */ WM_operator_stack_clear(CTX_wm_manager(C)); - int ret = ed_undo_step_direction(C, 1, op->reports); + int ret = ed_undo_step_direction(C, STEP_UNDO, op->reports); if (ret & OPERATOR_FINISHED) { /* Keep button under the cursor active. */ WM_event_add_mousemove(CTX_wm_window(C)); @@ -477,7 +515,7 @@ static int ed_undo_push_exec(bContext *C, wmOperator *op) static int ed_redo_exec(bContext *C, wmOperator *op) { - int ret = ed_undo_step_direction(C, -1, op->reports); + int ret = ed_undo_step_direction(C, STEP_REDO, op->reports); if (ret & OPERATOR_FINISHED) { /* Keep button under the cursor active. */ WM_event_add_mousemove(CTX_wm_window(C)); diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c index eea0f29d295..4fd8c180a4b 100644 --- a/source/blender/editors/undo/memfile_undo.c +++ b/source/blender/editors/undo/memfile_undo.c @@ -145,19 +145,18 @@ static int memfile_undosys_step_id_reused_cb(LibraryIDLinkCallbackData *cb_data) static void memfile_undosys_step_decode(struct bContext *C, struct Main *bmain, UndoStep *us_p, - int undo_direction, + const eUndoStepDir undo_direction, bool UNUSED(is_final)) { - BLI_assert(undo_direction != 0); + BLI_assert(undo_direction != STEP_INVALID); bool use_old_bmain_data = true; if (USER_EXPERIMENTAL_TEST(&U, use_undo_legacy)) { use_old_bmain_data = false; } - else if (undo_direction > 0) { - /* Redo case. - * The only time we should have to force a complete redo is when current step is tagged as a + else if (undo_direction == STEP_REDO) { + /* The only time we should have to force a complete redo is when current step is tagged as a * redo barrier. * If previous step was not a memfile one should not matter here, current data in old bmain * should still always be valid for unchanged data-blocks. */ @@ -165,9 +164,8 @@ static void memfile_undosys_step_decode(struct bContext *C, use_old_bmain_data = false; } } - else { - /* Undo case. - * Here we do not care whether current step is an undo barrier, since we are coming from + else if (undo_direction == STEP_UNDO) { + /* Here we do not care whether current step is an undo barrier, since we are coming from * 'the future' we can still re-use old data. However, if *next* undo step * (i.e. the one immediately in the future, the one we are coming from) * is a barrier, then we have to force a complete undo. @@ -316,8 +314,8 @@ struct MemFile *ED_undosys_stack_memfile_get_active(UndoStack *ustack) * If the last undo step is a memfile one, find the first #MemFileChunk matching given ID * (using its session UUID), and tag it as "changed in the future". * - * Since non-memfile undos cannot automatically set this flag in the previous step as done with - * memfile ones, this has to be called manually by relevant undo code. + * Since non-memfile undo-steps cannot automatically set this flag in the previous step as done + * with memfile ones, this has to be called manually by relevant undo code. * * \note Only current known case for this is undoing a switch from Object to Sculpt mode (see * T82388). diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index 0aab3810254..38655b8490e 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -39,7 +39,7 @@ set(SRC ed_transverts.c ed_util.c ed_util_imbuf.c - ed_util_ops.c + ed_util_ops.cc gizmo_utils.c numinput.c select_utils.c diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c index 1075f256a09..d0234dee856 100644 --- a/source/blender/editors/util/ed_transverts.c +++ b/source/blender/editors/util/ed_transverts.c @@ -495,8 +495,8 @@ void ED_transverts_create_from_obedit(TransVertStore *tvs, Object *obedit, const } if (!tvs->transverts_tot && tvs->transverts) { - /* prevent memory leak. happens for curves/latticies due to */ - /* difficult condition of adding points to trans data */ + /* Prevent memory leak. happens for curves/lattices due to + * difficult condition of adding points to trans data. */ MEM_freeN(tvs->transverts); tvs->transverts = NULL; } diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index c59fbbe1646..695db9ba246 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -183,7 +183,7 @@ void ED_editors_exit(Main *bmain, bool do_undo_system) return; } - /* frees all editmode undos */ + /* Frees all edit-mode undo-steps. */ if (do_undo_system && G_MAIN->wm.first) { wmWindowManager *wm = G_MAIN->wm.first; /* normally we don't check for NULL undo stack, diff --git a/source/blender/editors/util/ed_util_ops.c b/source/blender/editors/util/ed_util_ops.cc index bb531b11b12..cb7ff9f3a63 100644 --- a/source/blender/editors/util/ed_util_ops.c +++ b/source/blender/editors/util/ed_util_ops.cc @@ -22,6 +22,9 @@ #include <string.h> +#include "DNA_space_types.h" +#include "DNA_windowmanager_types.h" + #include "BLI_fileops.h" #include "BLI_utildefines.h" @@ -33,9 +36,6 @@ #include "BLT_translation.h" -#include "DNA_space_types.h" -#include "DNA_windowmanager_types.h" - #include "ED_render.h" #include "ED_undo.h" #include "ED_util.h" @@ -56,7 +56,7 @@ static bool lib_id_preview_editing_poll(bContext *C) const PointerRNA idptr = CTX_data_pointer_get(C, "id"); BLI_assert(!idptr.data || RNA_struct_is_ID(idptr.type)); - const ID *id = idptr.data; + const ID *id = (ID *)idptr.data; if (!id) { return false; } @@ -88,11 +88,11 @@ static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op) } PointerRNA idptr = CTX_data_pointer_get(C, "id"); - ID *id = idptr.data; + ID *id = (ID *)idptr.data; BKE_previewimg_id_custom_set(id, path); - WM_event_add_notifier(C, NC_ASSET, NULL); + WM_event_add_notifier(C, NC_ASSET, nullptr); return OPERATOR_FINISHED; } @@ -123,7 +123,7 @@ static void ED_OT_lib_id_load_custom_preview(wmOperatorType *ot) static int lib_id_generate_preview_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA idptr = CTX_data_pointer_get(C, "id"); - ID *id = idptr.data; + ID *id = (ID *)idptr.data; ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); @@ -131,9 +131,9 @@ static int lib_id_generate_preview_exec(bContext *C, wmOperator *UNUSED(op)) if (preview) { BKE_previewimg_clear(preview); } - UI_icon_render_id(C, NULL, id, ICON_SIZE_PREVIEW, true); + UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, true); - WM_event_add_notifier(C, NC_ASSET, NULL); + WM_event_add_notifier(C, NC_ASSET, nullptr); return OPERATOR_FINISHED; } @@ -169,15 +169,15 @@ static int lib_id_fake_user_toggle_exec(bContext *C, wmOperator *op) idptr = RNA_property_pointer_get(&pprop.ptr, pprop.prop); } - if ((pprop.prop == NULL) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) { + if ((pprop.prop == nullptr) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) { BKE_report( op->reports, RPT_ERROR, "Incorrect context for running data-block fake user toggling"); return OPERATOR_CANCELLED; } - ID *id = idptr.data; + ID *id = (ID *)idptr.data; - if ((id->lib != NULL) || (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { + if ((id->lib != nullptr) || (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; } @@ -217,14 +217,14 @@ static int lib_id_unlink_exec(bContext *C, wmOperator *op) idptr = RNA_property_pointer_get(&pprop.ptr, pprop.prop); } - if ((pprop.prop == NULL) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) { + if ((pprop.prop == nullptr) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) { BKE_report( op->reports, RPT_ERROR, "Incorrect context for running data-block fake user toggling"); return OPERATOR_CANCELLED; } memset(&idptr, 0, sizeof(idptr)); - RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, NULL); + RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, nullptr); RNA_property_update(C, &pprop.ptr, pprop.prop); return OPERATOR_FINISHED; diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index ba22bcca0e1..91ec8546225 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -508,7 +508,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) #endif case EVT_CKEY: if (event->ctrl) { - /* Copy current str to the copypaste buffer. */ + /* Copy current `str` to the copy/paste buffer. */ WM_clipboard_text_set(n->str, 0); updated = true; } diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index ed9e5053f10..e94aaa49839 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -978,7 +978,7 @@ static int p_connect_pairs(PHandle *handle, PBool topology_from_uvs) PChart *chart = handle->construction_chart; int ncharts = 0; - /* connect pairs, count edges, set vertex-edge pointer to a pairless edge */ + /* Connect pairs, count edges, set vertex-edge pointer to a pair-less edge. */ for (first = chart->faces; first; first = first->nextlink) { if (first->flag & PFACE_CONNECTED) { continue; @@ -1974,7 +1974,7 @@ static PBool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair) b[1] = p_vec_angle(v2->co, v1->co, keepv->co); b[2] = M_PI - b[0] - b[1]; - /* abf criterion 1: avoid sharp and obtuse angles */ + /* ABF criterion 1: avoid sharp and obtuse angles. */ minangle = 15.0f * M_PI / 180.0f; maxangle = M_PI - minangle; @@ -1991,7 +1991,7 @@ static PBool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair) } while (e && (e != oldv->edge)); if (p_vert_interior(oldv)) { - /* hlscm criterion: angular defect smaller than threshold */ + /* HLSCM criterion: angular defect smaller than threshold. */ if (fabsf(angulardefect) > (float)(M_PI * 30.0 / 180.0)) { return P_FALSE; } @@ -2000,12 +2000,12 @@ static PBool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair) PVert *v1 = p_boundary_edge_next(oldv->edge)->vert; PVert *v2 = p_boundary_edge_prev(oldv->edge)->vert; - /* abf++ criterion 2: avoid collapsing verts inwards */ + /* ABF++ criterion 2: avoid collapsing verts inwards. */ if (p_vert_interior(keepv)) { return P_FALSE; } - /* don't collapse significant boundary changes */ + /* Don't collapse significant boundary changes. */ angle = p_vec_angle(v1->co, oldv->co, v2->co); if (angle < (M_PI * 160.0 / 180.0)) { return P_FALSE; @@ -3837,7 +3837,7 @@ static void p_chart_rotate_fit_aabb(PChart *chart) /* Area Smoothing */ -/* 2d bsp tree for inverse mapping - that's a bit silly */ +/* 2d BSP tree for inverse mapping - that's a bit silly. */ typedef struct SmoothTriangle { float co1[2], co2[2], co3[2]; @@ -4288,7 +4288,7 @@ static void p_smooth(PChart *chart) MEM_freeN(hedges); MEM_freeN(vedges); - /* create bsp */ + /* Create BSP. */ t = triangles = MEM_mallocN(sizeof(SmoothTriangle) * esize * 2, "PSmoothTris"); trip = tri = MEM_mallocN(sizeof(SmoothTriangle *) * esize * 2, "PSmoothTriP"); diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 7b27bb570cc..8ebf000baaa 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -129,8 +129,10 @@ typedef struct UvEdge { /** general use flag * (Used to check if edge is boundary here, and propagates to adjacency elements) */ uchar flag; - /** element that guarantees element->face - * has the edge on element->tfindex and element->tfindex+1 is the second uv */ + /** + * Element that guarantees `element.l` has the edge on + * `element.loop_of_poly_index` and `element->loop_of_poly_index + 1` is the second UV. + */ UvElement *element; /** next uv edge with the same exact vertices as this one. * Calculated at startup to save time */ @@ -224,13 +226,13 @@ enum StitchModes { STITCH_EDGE, }; -/* UvElement identification. */ +/** #UvElement identification. */ typedef struct UvElementID { int faceIndex; int elementIndex; } UvElementID; -/* StitchState initializition. */ +/** #StitchState initialization. */ typedef struct StitchStateInit { int uv_selected_count; UvElementID *to_select; @@ -2050,7 +2052,7 @@ static StitchState *stitch_init(bContext *C, BLI_ghash_free(edge_hash, NULL, NULL); - /* refill an edge hash to create edge connnectivity data */ + /* Refill an edge hash to create edge connectivity data. */ state->edge_hash = edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash"); for (i = 0; i < total_edges; i++) { BLI_ghash_insert(edge_hash, edges + i, edges + i); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index be54df1ce9e..fc5f41e8ed5 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -1336,9 +1336,9 @@ static void uv_map_rotation_matrix_ex(float result[4][4], zero_m4(rotup); zero_m4(rotside); - /* compensate front/side.. against opengl x,y,z world definition */ - /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */ - /* i wanted to keep the reason here, so we're rotating*/ + /* Compensate front/side.. against opengl x,y,z world definition. + * This is "a sledgehammer to crack a nut" (overkill), a few plus minus 1 will do here. + * I wanted to keep the reason here, so we're rotating. */ sideangle = (float)M_PI * (sideangledeg + 180.0f) / 180.0f; rotside[0][0] = cosf(sideangle); rotside[0][1] = -sinf(sideangle); |