diff options
Diffstat (limited to 'source/blender/editors')
425 files changed, 15039 insertions, 7646 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 6dd1fe75163..87688ee343c 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -502,7 +502,7 @@ static bool acf_summary_setting_valid(bAnimContext *UNUSED(ac), return (setting == ACHANNEL_SETTING_EXPAND); } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_summary_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -595,7 +595,7 @@ static bool acf_scene_setting_valid(bAnimContext *ac, } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_scene_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -766,7 +766,7 @@ static bool acf_object_setting_valid(bAnimContext *ac, } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_object_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -949,7 +949,7 @@ static bool acf_group_setting_valid(bAnimContext *ac, } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_group_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg) { /* clear extra return data first */ @@ -1086,7 +1086,7 @@ static bool acf_fcurve_setting_valid(bAnimContext *ac, } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -1212,7 +1212,7 @@ static bool acf_nla_controls_setting_valid(bAnimContext *UNUSED(ac), } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_nla_controls_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -1330,7 +1330,7 @@ static bool acf_fillactd_setting_valid(bAnimContext *UNUSED(ac), } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_fillactd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -1425,7 +1425,7 @@ static bool acf_filldrivers_setting_valid(bAnimContext *UNUSED(ac), } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -1489,7 +1489,7 @@ static int acf_dsmat_icon(bAnimListElem *UNUSED(ale)) return ICON_MATERIAL_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -1568,7 +1568,7 @@ static int acf_dslight_icon(bAnimListElem *UNUSED(ale)) return ICON_LIGHT_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dslight_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -1656,7 +1656,7 @@ static short acf_dstex_offset(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(al return 14; /* XXX: simply include this in indention instead? */ } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -1736,7 +1736,7 @@ static int acf_dscachefile_icon(bAnimListElem *ale) return ICON_FILE; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dscachefile_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg) { /* clear extra return data first */ @@ -1818,7 +1818,7 @@ static int acf_dscam_icon(bAnimListElem *UNUSED(ale)) return ICON_CAMERA_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -1911,7 +1911,7 @@ static int acf_dscur_icon(bAnimListElem *ale) } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2009,7 +2009,7 @@ static bool acf_dsskey_setting_valid(bAnimContext *ac, } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2088,7 +2088,7 @@ static int acf_dswor_icon(bAnimListElem *UNUSED(ale)) return ICON_WORLD_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2167,7 +2167,7 @@ static int acf_dspart_icon(bAnimListElem *UNUSED(ale)) return ICON_PARTICLE_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2246,7 +2246,7 @@ static int acf_dsmball_icon(bAnimListElem *UNUSED(ale)) return ICON_META_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2327,7 +2327,7 @@ static int acf_dsarm_icon(bAnimListElem *UNUSED(ale)) return ICON_ARMATURE_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2417,7 +2417,7 @@ static short acf_dsntree_offset(bAnimContext *ac, bAnimListElem *ale) return offset; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2498,7 +2498,7 @@ static int acf_dslinestyle_icon(bAnimListElem *UNUSED(ale)) return ICON_LINE_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2579,7 +2579,7 @@ static int acf_dsmesh_icon(bAnimListElem *UNUSED(ale)) return ICON_MESH_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2659,7 +2659,7 @@ static int acf_dslat_icon(bAnimListElem *UNUSED(ale)) return ICON_LATTICE_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2739,7 +2739,7 @@ static int acf_dsspk_icon(bAnimListElem *UNUSED(ale)) return ICON_SPEAKER; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2818,7 +2818,7 @@ static int acf_dshair_icon(bAnimListElem *UNUSED(ale)) return ICON_HAIR_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dshair_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2897,7 +2897,7 @@ static int acf_dspointcloud_icon(bAnimListElem *UNUSED(ale)) return ICON_POINTCLOUD_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dspointcloud_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -2978,7 +2978,7 @@ static int acf_dsvolume_icon(bAnimListElem *UNUSED(ale)) return ICON_VOLUME_DATA; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dsvolume_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -3137,7 +3137,7 @@ static int acf_dsgpencil_icon(bAnimListElem *UNUSED(ale)) return ICON_GREASEPENCIL; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dsgpencil_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -3218,7 +3218,7 @@ static int acf_dsmclip_icon(bAnimListElem *UNUSED(ale)) return ICON_SEQUENCE; } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_dsmclip_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -3343,7 +3343,7 @@ static bool acf_shapekey_setting_valid(bAnimContext *UNUSED(ac), } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -3437,7 +3437,7 @@ static bool acf_gpd_setting_valid(bAnimContext *UNUSED(ac), } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_gpd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) { /* clear extra return data first */ @@ -3530,7 +3530,7 @@ static bool acf_gpl_setting_valid(bAnimContext *UNUSED(ac), } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) { /* clear extra return data first */ @@ -3616,7 +3616,7 @@ static bool acf_mask_setting_valid(bAnimContext *UNUSED(ac), } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_mask_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -3713,7 +3713,7 @@ static bool acf_masklay_setting_valid(bAnimContext *UNUSED(ac), } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -3849,7 +3849,7 @@ static bool acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac), } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_nlatrack_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -4025,7 +4025,7 @@ static bool acf_nlaaction_setting_valid(bAnimContext *UNUSED(ac), /* conditionally supported */ case ACHANNEL_SETTING_PINNED: /* pinned - map/unmap */ if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) { - /* this should only appear in tweakmode */ + /* This should only appear in tweak-mode. */ return true; } else { @@ -4038,7 +4038,7 @@ static bool acf_nlaaction_setting_valid(bAnimContext *UNUSED(ac), } } -/* get the appropriate flag(s) for the setting when it is valid */ +/* Get the appropriate flag(s) for the setting when it is valid. */ static int acf_nlaaction_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) @@ -4415,7 +4415,7 @@ void ANIM_channel_draw( /* set blending again, as may not be set in previous step */ GPU_blend(GPU_BLEND_ALPHA); - /* step 1) draw backdrop ........................................... */ + /* step 1) draw backdrop ........................................... */ if (acf->draw_backdrop) { acf->draw_backdrop(ac, ale, yminc, ymaxc); } @@ -4674,7 +4674,7 @@ static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void DEG_id_tag_update(ale_setting->id, ID_RECALC_ANIMATION); } if (ale_setting->adt && ale_setting->adt->action) { - /* Action is it's own datablock, so has to be tagged specifically. */ + /* Action is its own datablock, so has to be tagged specifically. */ DEG_id_tag_update(&ale_setting->adt->action->id, ID_RECALC_ANIMATION); } @@ -5096,7 +5096,7 @@ static void draw_setting_widget(bAnimContext *ac, /* set call to send relevant notifiers and/or perform type-specific updates */ if (but) { switch (setting) { - /* settings needing flushing up/down hierarchy */ + /* Settings needing flushing up/down hierarchy. */ case ACHANNEL_SETTING_VISIBLE: /* Graph Editor - 'visibility' toggles */ case ACHANNEL_SETTING_PROTECT: /* General - protection flags */ case ACHANNEL_SETTING_MUTE: /* General - muting flags */ @@ -5176,7 +5176,7 @@ void ANIM_channel_draw_widgets(const bContext *C, } /* step 3) draw special toggles ................................. - * - in Graph Editor, checkboxes for visibility in curves area + * - in Graph Editor, check-boxes for visibility in curves area * - in NLA Editor, glowing dots for solo/not solo... * - in Grease Pencil mode, color swatches for layer color */ @@ -5184,12 +5184,12 @@ void ANIM_channel_draw_widgets(const bContext *C, if ((ac->spacetype == SPACE_GRAPH) && (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE) || acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE))) { - /* pin toggle */ + /* Pin toggle. */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)) { draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_ALWAYS_VISIBLE); offset += ICON_WIDTH; } - /* visibility toggle */ + /* Visibility toggle. */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) { /* For F-curves, add the extra space for the color bands. */ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) { @@ -5462,7 +5462,6 @@ void ANIM_channel_draw_widgets(const bContext *C, prop = RNA_struct_find_property(&ptr, "use_mask_layer"); gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop); if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) { - icon = ICON_LAYER_ACTIVE; if (gpl->flag & GP_LAYER_USE_MASK) { icon = ICON_MOD_MASK; } diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 64082b08da9..8f8c1c067d4 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -747,7 +747,7 @@ static bool animedit_poll_channels_active(bContext *C) return 1; } -/* poll callback for Animation Editor channels list region + not in NLA-tweakmode for NLA */ +/* Poll callback for Animation Editor channels list region + not in NLA-tweak-mode for NLA. */ static bool animedit_poll_channels_nla_tweakmode_off(bContext *C) { ScrArea *area = CTX_wm_area(C); @@ -763,7 +763,7 @@ static bool animedit_poll_channels_nla_tweakmode_off(bContext *C) return 0; } - /* NLA TweakMode test */ + /* NLA tweak-mode test. */ if (area->spacetype == SPACE_NLA) { if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON)) { return 0; @@ -1283,6 +1283,9 @@ static void split_groups_action_temp(bAction *act, bActionGroup *tgrp) else { group_fcurves_last->next->prev = group_fcurves_first->prev; } + + /* Clear links pointing outside the per-group list. */ + group_fcurves_first->prev = group_fcurves_last->next = NULL; } /* Initialize memory for temp-group */ @@ -1337,22 +1340,12 @@ static void join_groups_action_temp(bAction *act) if (agrp->flag & AGRP_TEMP) { LISTBASE_FOREACH (FCurve *, fcu, &agrp->channels) { fcu->grp = NULL; - if (fcu == agrp->channels.last) { - break; - } } BLI_remlink(&act->groups, agrp); break; } } - - /* BLI_movelisttolist() doesn't touch first->prev and last->next pointers in its "dst" list. - * Ensure that after the reshuffling the list is properly terminated. */ - FCurve *act_fcurves_first = act->curves.first; - act_fcurves_first->prev = NULL; - FCurve *act_fcurves_last = act->curves.last; - act_fcurves_last->next = NULL; } /* Change the order of anim-channels within action @@ -1683,7 +1676,7 @@ static void animchannels_group_channels(bAnimContext *ac, agrp = action_groups_add_new(act, name); BLI_assert(agrp != NULL); - /* transfer selected F-Curves across to new group */ + /* Transfer selected F-Curves across to new group. */ for (ale = anim_data.first; ale; ale = ale->next) { FCurve *fcu = (FCurve *)ale->data; bActionGroup *grp = fcu->grp; @@ -1724,7 +1717,7 @@ static int animchannels_group_exec(bContext *C, wmOperator *op) bAnimListElem *ale; int filter; - /* handle each animdata block separately, so that the regrouping doesn't flow into blocks */ + /* Handle each animdata block separately, so that the regrouping doesn't flow into blocks. */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); @@ -2432,6 +2425,7 @@ static int animchannels_clean_empty_exec(bContext *C, wmOperator *UNUSED(op)) /* send notifier that things have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL); return OPERATOR_FINISHED; } @@ -3441,12 +3435,14 @@ static void ANIM_OT_channels_click(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; /* properties */ - /* NOTE: don't save settings, otherwise, can end up with some weird behavior (sticky extend) */ - prop = RNA_def_boolean(ot->srna, "extend", false, "Extend Select", ""); /* SHIFTKEY */ + /* NOTE: don't save settings, otherwise, can end up with some weird behavior (sticky extend) + * + * Key-map: Enable with `Shift`. */ + prop = RNA_def_boolean(ot->srna, "extend", false, "Extend Select", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean( - ot->srna, "children_only", false, "Select Children Only", ""); /* CTRLKEY|SHIFTKEY */ + /* Key-map: Enable with `Ctrl-Shift`. */ + prop = RNA_def_boolean(ot->srna, "children_only", false, "Select Children Only", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index 17251587d3b..42fdb714127 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -93,9 +93,9 @@ void ANIM_list_elem_update(Main *bmain, Scene *scene, bAnimListElem *ale) fcu = (ale->datatype == ALE_FCURVE) ? ale->key_data : NULL; if (fcu && fcu->rna_path) { - /* if we have an fcurve, call the update for the property we + /* If we have an fcurve, call the update for the property we * are editing, this is then expected to do the proper redraws - * and depsgraph updates */ + * and depsgraph updates. */ PointerRNA id_ptr, ptr; PropertyRNA *prop; @@ -109,8 +109,8 @@ void ANIM_list_elem_update(Main *bmain, Scene *scene, bAnimListElem *ale) /* in other case we do standard depsgraph update, ideally * we'd be calling property update functions here too ... */ DEG_id_tag_update(id, - ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | - ID_RECALC_ANIMATION); /* XXX or do we want something more restrictive? */ + /* XXX: or do we want something more restrictive? */ + ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); } } @@ -119,11 +119,10 @@ void ANIM_list_elem_update(Main *bmain, Scene *scene, bAnimListElem *ale) void ANIM_id_update(Main *bmain, ID *id) { if (id) { - DEG_id_tag_update_ex( - bmain, - id, - ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | - ID_RECALC_ANIMATION); /* XXX or do we want something more restrictive? */ + DEG_id_tag_update_ex(bmain, + id, + /* XXX: or do we want something more restrictive? */ + ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); } } diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index aca332ff0fe..2fcd59a1bbe 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -89,7 +89,7 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag) /* *************************************************** */ /* PREVIEW RANGE 'CURTAINS' */ -/* Note: 'Preview Range' tools are defined in anim_ops.c */ +/* NOTE: 'Preview Range' tools are defined in `anim_ops.c`. */ /* Draw preview range 'curtains' for highlighting where the animation data is */ void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width) @@ -168,7 +168,7 @@ void ANIM_draw_framerange(Scene *scene, View2D *v2d) } /* *************************************************** */ -/* NLA-MAPPING UTILITIES (required for drawing and also editing keyframes) */ +/* NLA-MAPPING UTILITIES (required for drawing and also editing keyframes). */ /** * Obtain the AnimData block providing NLA-mapping for the given channel (if applicable). @@ -413,7 +413,7 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo else { /* Calculate min/max using full fcurve evaluation. * [slower than bezier forward differencing but evaluates Back/Elastic interpolation - * as well].*/ + * as well]. */ float step_size = (bezt->vec[1][0] - prev_bezt->vec[1][0]) / resol; for (int j = 0; j <= resol; j++) { float eval_time = prev_bezt->vec[1][0] + step_size * j; diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index a03f19d0111..b2d387ea898 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -32,7 +32,7 @@ * are being edited. Likewise, the NLA Editor also uses this for its channel list and in * its operators. * - * Note: much of the original system this was based on was built before the creation of the RNA + * NOTE: much of the original system this was based on was built before the creation of the RNA * system. In future, it would be interesting to replace some parts of this code with RNA queries, * however, RNA does not eliminate some of the boiler-plate reduction benefits presented by this * system, so if any such work does occur, it should only be used for the internals used here... @@ -131,7 +131,7 @@ static void animedit_get_yscale_factor(bAnimContext *ac) /* ----------- Private Stuff - Action Editor ------------- */ /* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */ -/* Note: there's a similar function in key.c (BKE_key_from_object) */ +/* NOTE: there's a similar function in key.c #BKE_key_from_object. */ static Key *actedit_get_shapekeys(bAnimContext *ac) { ViewLayer *view_layer = ac->view_layer; @@ -222,9 +222,9 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction) ac->mode = saction->mode; return true; - case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */ + case SACTCONT_MASK: /* Mask */ /* XXX: review how this mode is handled. */ { - /* TODO, other methods to get the mask */ + /* TODO: other methods to get the mask. */ #if 0 Sequence *seq = SEQ_select_active_get(ac->scene); MovieClip *clip = ac->scene->clip; @@ -454,7 +454,7 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac) * keep expander channels with no sub-data out, as those cases should get * dealt with by the recursive detection idiom in place. * - * Implementation Note: + * Implementation NOTE: * YES the _doSubChannels variable is NOT read anywhere. BUT, this is NOT an excuse * to go steamrolling the logic into a single-line expression as from experience, * those are notoriously difficult to read + debug when extending later on. The code @@ -1217,7 +1217,7 @@ static bool skip_fcurve_with_name( * * \return true if F-Curve has errors/is disabled */ -static bool fcurve_has_errors(FCurve *fcu) +static bool fcurve_has_errors(const FCurve *fcu) { /* F-Curve disabled - path eval error */ if (fcu->flag & FCURVE_DISABLED) { @@ -1226,7 +1226,7 @@ static bool fcurve_has_errors(FCurve *fcu) /* driver? */ if (fcu->driver) { - ChannelDriver *driver = fcu->driver; + const ChannelDriver *driver = fcu->driver; DriverVar *dvar; /* error flag on driver usually means that there is an error @@ -3132,7 +3132,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m /* check selection and object type filters */ if ((ads->filterflag & ADS_FILTER_ONLYSEL) && - !((base->flag & BASE_SELECTED) /*|| (base == sce->basact)*/)) { + !((base->flag & BASE_SELECTED) /*|| (base == sce->basact) */)) { /* only selected should be shown */ return false; } diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 7adddf8f4ae..9d998326b4d 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -687,7 +687,7 @@ static int ed_marker_add_exec(bContext *C, wmOperator *UNUSED(op)) marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker"); marker->flag = SELECT; marker->frame = frame; - BLI_snprintf(marker->name, sizeof(marker->name), "F_%02d", frame); /* XXX - temp code only */ + BLI_snprintf(marker->name, sizeof(marker->name), "F_%02d", frame); /* XXX: temp code only. */ BLI_addtail(markers, marker); WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); @@ -897,7 +897,7 @@ static int ed_marker_move_invoke(bContext *C, wmOperator *op, const wmEvent *eve return OPERATOR_CANCELLED; } -/* note, init has to be called successfully */ +/* NOTE: init has to be called successfully. */ static void ed_marker_move_apply(bContext *C, wmOperator *op) { #ifdef DURIAN_CAMERA_SWITCH diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c index aac2465d43a..51a897600e1 100644 --- a/source/blender/editors/animation/anim_motion_paths.c +++ b/source/blender/editors/animation/anim_motion_paths.c @@ -355,7 +355,7 @@ static void motionpath_free_free_tree_data(ListBase *targets) /* Perform baking of the given object's and/or its bones' transforms to motion paths * - scene: current scene - * - ob: object whose flagged motionpaths should get calculated + * - ob: object whose flagged motion-paths should get calculated * - recalc: whether we need to */ /* TODO: include reports pointer? */ diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 72d9bff545a..6f3277397c5 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -51,8 +51,10 @@ #include "DEG_depsgraph.h" +#include "SEQ_iterator.h" #include "SEQ_sequencer.h" #include "SEQ_time.h" +#include "SEQ_transform.h" #include "anim_intern.h" @@ -81,6 +83,49 @@ static bool change_frame_poll(bContext *C) return false; } +static int seq_snap_threshold_get_frame_distance(bContext *C) +{ + const int snap_distance = SEQ_tool_settings_snap_distance_get(CTX_data_scene(C)); + const ARegion *region = CTX_wm_region(C); + return round_fl_to_int(UI_view2d_region_to_view_x(®ion->v2d, snap_distance) - + UI_view2d_region_to_view_x(®ion->v2d, 0)); +} + +static void seq_frame_snap_update_best(const int position, + const int timeline_frame, + int *r_best_frame, + int *r_best_distance) +{ + if (abs(position - timeline_frame) < *r_best_distance) { + *r_best_distance = abs(position - timeline_frame); + *r_best_frame = position; + } +} + +static int seq_frame_apply_snap(bContext *C, Scene *scene, const int timeline_frame) +{ + + ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene, false)); + SeqCollection *strips = SEQ_query_all_strips(seqbase); + + int best_frame = 0; + int best_distance = MAXFRAME; + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, strips) { + seq_frame_snap_update_best( + SEQ_transform_get_left_handle_frame(seq), timeline_frame, &best_frame, &best_distance); + seq_frame_snap_update_best( + SEQ_transform_get_right_handle_frame(seq), timeline_frame, &best_frame, &best_distance); + } + SEQ_collection_free(strips); + + if (best_distance < seq_snap_threshold_get_frame_distance(C)) { + return best_frame; + } + + return timeline_frame; +} + /* Set the new frame number */ static void change_frame_apply(bContext *C, wmOperator *op) { @@ -90,7 +135,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) if (do_snap) { if (CTX_wm_space_seq(C)) { - frame = SEQ_time_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false); + frame = seq_frame_apply_snap(C, scene, frame); } else { frame = BKE_scene_frame_snap_by_seconds(scene, 1.0, frame); @@ -181,6 +226,18 @@ static void change_frame_seq_preview_end(bContext *C) } } +static bool use_sequencer_snapping(bContext *C) +{ + if (!CTX_wm_space_seq(C)) { + return false; + } + + Scene *scene = CTX_data_scene(C); + short snap_flag = SEQ_tool_settings_snap_flag_get(scene); + return (scene->toolsettings->snap_flag & SCE_SNAP_SEQ) && + (snap_flag & SEQ_SNAP_CURRENT_FRAME_TO_STRIPS); +} + /* Modal Operator init */ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -190,6 +247,10 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event */ RNA_float_set(op->ptr, "frame", frame_from_event(C, event)); + if (use_sequencer_snapping(C)) { + RNA_boolean_set(op->ptr, "snap", true); + } + change_frame_seq_preview_begin(C, event); change_frame_apply(C, op); @@ -231,11 +292,22 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event) case EVT_LEFTCTRLKEY: case EVT_RIGHTCTRLKEY: - if (event->val == KM_RELEASE) { - RNA_boolean_set(op->ptr, "snap", false); + /* Use Ctrl key to invert snapping in sequencer. */ + if (use_sequencer_snapping(C)) { + if (event->val == KM_RELEASE) { + RNA_boolean_set(op->ptr, "snap", true); + } + else if (event->val == KM_PRESS) { + RNA_boolean_set(op->ptr, "snap", false); + } } - else if (event->val == KM_PRESS) { - RNA_boolean_set(op->ptr, "snap", true); + else { + if (event->val == KM_RELEASE) { + RNA_boolean_set(op->ptr, "snap", false); + } + else if (event->val == KM_PRESS) { + RNA_boolean_set(op->ptr, "snap", true); + } } break; } @@ -465,7 +537,7 @@ static void ANIM_OT_previewrange_set(wmOperatorType *ot) /* rna */ /* used to define frame range. * - * note: border Y values are not used, + * NOTE: border Y values are not used, * but are needed by box_select gesture operator stuff */ WM_operator_properties_border(ot); } diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 43d5efe9ea9..bfaa76b3bf9 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -80,7 +80,7 @@ FCurve *verify_driver_fcurve(ID *id, /* init animdata if none available yet */ adt = BKE_animdata_from_id(id); if (adt == NULL && creation_mode != DRIVER_FCURVE_LOOKUP_ONLY) { - adt = BKE_animdata_add_id(id); + adt = BKE_animdata_ensure_id(id); } if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ @@ -568,7 +568,7 @@ bool ANIM_remove_driver(ReportList *UNUSED(reports), FCurve *fcu_iter = adt->drivers.first; while ((fcu = BKE_fcurve_iter_step(fcu_iter, rna_path)) != NULL) { - /* store the next fcurve for looping */ + /* Store the next fcurve for looping. */ fcu_iter = fcu->next; /* remove F-Curve from driver stack, then free it */ @@ -581,7 +581,7 @@ bool ANIM_remove_driver(ReportList *UNUSED(reports), } else { /* find the matching driver and remove it only - * Note: here is one of the places where we don't want new F-Curve + Driver added! + * NOTE: here is one of the places where we don't want new F-Curve + Driver added! * so 'add' var must be 0 */ fcu = verify_driver_fcurve(id, rna_path, array_index, DRIVER_FCURVE_LOOKUP_ONLY); @@ -1253,7 +1253,7 @@ static int copy_driver_button_exec(bContext *C, wmOperator *op) } } - /* since we're just copying, we don't really need to do anything else...*/ + /* Since we're just copying, we don't really need to do anything else. */ return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } @@ -1303,7 +1303,7 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op) } } - /* since we're just copying, we don't really need to do anything else...*/ + /* Since we're just copying, we don't really need to do anything else. */ return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index 653bd72b364..31552330071 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -246,7 +246,7 @@ static PanelType *fmodifier_subpanel_register(ARegionType *region_type, #define B_REDR 1 #define B_FMODIFIER_REDRAW 20 -/* callback to remove the given modifier */ +/* Callback to remove the given modifier. */ typedef struct FModifierDeleteContext { ID *owner_id; ListBase *modifiers; diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index 636f0d3cbea..0923d490110 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -251,7 +251,7 @@ static short ob_keyframes_loop(KeyframeEditData *ked, ANIM_animdata_freelist(&anim_data); - /* return return code - defaults to zero if nothing happened */ + /* Return the return code (defaults to zero if nothing happened). */ return ret; } @@ -300,7 +300,7 @@ static short scene_keyframes_loop(KeyframeEditData *ked, ANIM_animdata_freelist(&anim_data); - /* return return code - defaults to zero if nothing happened */ + /* Return the return code (defaults to zero if nothing happened). */ return ret; } @@ -1024,7 +1024,7 @@ static short mirror_bezier_value(KeyframeEditData *ked, BezTriple *bezt) return 0; } -/* Note: for markers and 'value', the values to use must be supplied as the first float value */ +/* NOTE: for markers and 'value', the values to use must be supplied as the first float value. */ /* calchandles_fcurve */ KeyframeEditFunc ANIM_editkeyframes_mirror(short mode) { @@ -1109,7 +1109,7 @@ static short set_bezier_auto_clamped(KeyframeEditData *UNUSED(ked), BezTriple *b return 0; } -/* Sets the selected bezier handles to type 'vector' */ +/* Sets the selected bezier handles to type 'vector'. */ static short set_bezier_vector(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { /* If the key is selected, always apply to both handles. */ @@ -1164,7 +1164,7 @@ static short set_bezier_align(KeyframeEditData *UNUSED(ked), BezTriple *bezt) return 0; } -/* Sets selected bezier handles to type 'free' */ +/* Sets selected bezier handles to type 'free'. */ static short set_bezier_free(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { /* If the key is selected, always apply to both handles. */ diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 87291974e08..eb91afa5c84 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -193,7 +193,7 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo BezTriple *lastb; int totCount, i; - /* check if any points */ + /* Check if any points. */ if ((fcu == NULL) || (fcu->bezt == NULL) || (fcu->totvert == 0) || (!cleardefault && fcu->totvert == 1)) { return; @@ -408,7 +408,7 @@ bool decimate_fcurve(bAnimListElem *ale, float remove_ratio, float error_sq_max) { FCurve *fcu = (FCurve *)ale->key_data; - /* Check if the curve actually has any points */ + /* Check if the curve actually has any points. */ if (fcu == NULL || fcu->bezt == NULL || fcu->totvert == 0) { return true; } @@ -588,7 +588,7 @@ typedef struct TempFrameValCache { float frame, val; } TempFrameValCache; -/* Evaluates the curves between each selected keyframe on each frame, and keys the value */ +/* Evaluates the curves between each selected keyframe on each frame, and keys the value. */ void sample_fcurve(FCurve *fcu) { BezTriple *bezt, *start = NULL, *end = NULL; @@ -600,7 +600,7 @@ void sample_fcurve(FCurve *fcu) return; } - /* find selected keyframes... once pair has been found, add keyframes */ + /* Find selected keyframes... once pair has been found, add keyframes. */ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { /* check if selected, and which end this is */ if (BEZT_ISSEL_ANY(bezt)) { @@ -693,7 +693,7 @@ typedef struct tAnimCopybufItem { int totvert; /* number of keyframes stored for this channel */ BezTriple *bezt; /* keyframes in buffer */ - short id_type; /* Result of GS(id->name)*/ + short id_type; /* Result of `GS(id->name)`. */ bool is_bone; /* special flag for armature bones */ } tAnimCopybufItem; @@ -913,7 +913,7 @@ static tAnimCopybufItem *pastebuf_match_path_property(Main *bmain, if (aci->rna_path && fcu->rna_path) { /* find the property of the fcurve and compare against the end of the tAnimCopybufItem * more involved since it needs to do path lookups. - * This is not 100% reliable since the user could be editing the curves on a path that wont + * This is not 100% reliable since the user could be editing the curves on a path that won't * resolve, or a bone could be renamed after copying for eg. but in normal copy & paste * this should work out ok. */ @@ -932,7 +932,7 @@ static tAnimCopybufItem *pastebuf_match_path_property(Main *bmain, int len_id = strlen(identifier); int len_path = strlen(fcu->rna_path); if (len_id <= len_path) { - /* note, paths which end with "] will fail with this test - Animated ID Props */ + /* NOTE: paths which end with "] will fail with this test - Animated ID Props. */ if (STREQ(identifier, fcu->rna_path + (len_path - len_id))) { if ((from_single) || (aci->array_index == fcu->array_index)) { break; diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index f229d48b4eb..0a499232ba9 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -85,6 +85,8 @@ static KeyingSet *keyingset_get_from_op_with_error(wmOperator *op, PropertyRNA *prop, Scene *scene); +static int delete_key_using_keying_set(bContext *C, wmOperator *op, KeyingSet *ks); + /* ************************************************** */ /* Keyframing Setting Wrangling */ @@ -140,7 +142,7 @@ bAction *ED_id_action_ensure(Main *bmain, ID *id) /* init animdata if none available yet */ adt = BKE_animdata_from_id(id); if (adt == NULL) { - adt = BKE_animdata_add_id(id); + adt = BKE_animdata_ensure_id(id); } if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ @@ -952,7 +954,7 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop) case CONSTRAINT_TYPE_KINEMATIC: return true; - /* single-transform constraints */ + /* Single-transform constraints. */ case CONSTRAINT_TYPE_TRACKTO: if (searchtype == VISUALKEY_ROT) { return true; @@ -1672,7 +1674,7 @@ int delete_keyframe(Main *bmain, } /* get F-Curve - * Note: here is one of the places where we don't want new Action + F-Curve added! + * NOTE: here is one of the places where we don't want new Action + F-Curve added! * so 'add' var must be 0 */ if (act == NULL) { @@ -1779,7 +1781,7 @@ static int clear_keyframe(Main *bmain, } /* get F-Curve - * Note: here is one of the places where we don't want new Action + F-Curve added! + * NOTE: here is one of the places where we don't want new Action + F-Curve added! * so 'add' var must be 0 */ if (act == NULL) { @@ -2079,42 +2081,19 @@ void ANIM_OT_keyframe_insert_menu(wmOperatorType *ot) static int delete_key_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - float cfra = (float)CFRA; /* XXX for now, don't bother about all the yucky offset crap */ - int num_channels; - KeyingSet *ks = keyingset_get_from_op_with_error(op, op->type->prop, scene); if (ks == NULL) { return OPERATOR_CANCELLED; } - const int prop_type = RNA_property_type(op->type->prop); - if (prop_type == PROP_ENUM) { - int type = RNA_property_enum_get(op->ptr, op->type->prop); - ks = ANIM_keyingset_get_from_enum_type(scene, type); - if (ks == NULL) { - BKE_report(op->reports, RPT_ERROR, "No active Keying Set"); - return OPERATOR_CANCELLED; - } - } - else if (prop_type == PROP_STRING) { - char type_id[MAX_ID_NAME - 2]; - RNA_property_string_get(op->ptr, op->type->prop, type_id); - ks = ANIM_keyingset_get_from_idname(scene, type_id); - - if (ks == NULL) { - BKE_reportf(op->reports, RPT_ERROR, "Active Keying Set '%s' not found", type_id); - return OPERATOR_CANCELLED; - } - } - else { - BLI_assert(0); - } + return delete_key_using_keying_set(C, op, ks); +} - /* report failure */ - if (ks == NULL) { - BKE_report(op->reports, RPT_ERROR, "No active Keying Set"); - return OPERATOR_CANCELLED; - } +static int delete_key_using_keying_set(bContext *C, wmOperator *op, KeyingSet *ks) +{ + Scene *scene = CTX_data_scene(C); + float cfra = (float)CFRA; /* XXX for now, don't bother about all the yucky offset crap */ + int num_channels; /* try to delete keyframes for the channels specified by KeyingSet */ num_channels = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_DELETE, cfra); @@ -2130,7 +2109,8 @@ static int delete_key_exec(bContext *C, wmOperator *op) if (num_channels > 0) { /* if the appropriate properties have been set, make a note that we've inserted something */ - if (RNA_boolean_get(op->ptr, "confirm_success")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "confirm_success"); + if (prop != NULL && RNA_property_boolean_get(op->ptr, prop)) { BKE_reportf(op->reports, RPT_INFO, "Successfully removed %d keyframes for keying set '%s'", @@ -2244,7 +2224,7 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op)) bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); MEM_freeN(bone_name); - /* delete if bone is selected*/ + /* Delete if bone is selected. */ if ((pchan) && (pchan->bone)) { if (pchan->bone->flag & BONE_SELECTED) { can_delete = true; @@ -2301,7 +2281,7 @@ void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static int delete_key_v3d_exec(bContext *C, wmOperator *op) +static int delete_key_v3d_without_keying_set(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); float cfra = (float)CFRA; @@ -2408,6 +2388,18 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int delete_key_v3d_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + KeyingSet *ks = ANIM_scene_get_active_keyingset(scene); + + if (ks == NULL) { + return delete_key_v3d_without_keying_set(C, op); + } + + return delete_key_using_keying_set(C, op, ks); +} + void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot) { /* identifiers */ @@ -2810,14 +2802,14 @@ bool autokeyframe_cfra_can_key(const Scene *scene, ID *id) /* --------------- API/Per-Datablock Handling ------------------- */ /* Checks if some F-Curve has a keyframe for a given frame */ -bool fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter) +bool fcurve_frame_has_keyframe(const FCurve *fcu, float frame, short filter) { /* quick sanity check */ if (ELEM(NULL, fcu, fcu->bezt)) { return false; } - /* we either include all regardless of muting, or only non-muted */ + /* We either include all regardless of muting, or only non-muted. */ if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED) == 0) { bool replace; int i = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, frame, fcu->totvert, &replace); @@ -2931,7 +2923,7 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter) } /* 2. test for time */ - /* TODO... yet to be implemented (this feature may evolve before then anyway) */ + /* TODO: yet to be implemented (this feature may evolve before then anyway). */ } /* try materials */ @@ -3101,7 +3093,7 @@ bool ED_autokeyframe_property( ToolSettings *ts = scene->toolsettings; const eInsertKeyFlags flag = ANIM_get_keyframing_flags(scene, true); - /* Note: We use rnaindex instead of fcu->array_index, + /* NOTE: We use rnaindex instead of fcu->array_index, * because a button may control all items of an array at once. * E.g., color wheels (see T42567). */ BLI_assert((fcu->array_index == rnaindex) || (rnaindex == -1)); diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index fda7b600c1c..0206aabd359 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -529,7 +529,7 @@ void ANIM_OT_keying_set_active_set(wmOperatorType *ot) /* Keying Set Type Info declarations */ static ListBase keyingset_type_infos = {NULL, NULL}; -/* Built-In Keying Sets (referencing type infos)*/ +/* Built-In Keying Sets (referencing type information). */ ListBase builtin_keyingsets = {NULL, NULL}; /* --------------- */ diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c index 034378399b9..6af033f3cf2 100644 --- a/source/blender/editors/animation/time_scrub_ui.c +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -109,7 +109,7 @@ static void draw_current_frame(const Scene *scene, if (draw_line) { /* Draw vertical line to from the bottom of the current frame box to the bottom of the screen. */ - const float subframe_x = UI_view2d_view_to_region_x(v2d, BKE_scene_frame_get(scene)); + const float subframe_x = UI_view2d_view_to_region_x(v2d, BKE_scene_ctime_get(scene)); GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index 3902f6613a1..45bf18fe1bb 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -89,15 +89,14 @@ EditBone *ED_armature_ebone_add(bArmature *arm, const char *name) bone->roll1 = 0.0f; bone->roll2 = 0.0f; bone->curve_in_x = 0.0f; - bone->curve_in_y = 0.0f; + bone->curve_in_z = 0.0f; bone->curve_out_x = 0.0f; - bone->curve_out_y = 0.0f; + bone->curve_out_z = 0.0f; bone->ease1 = 1.0f; bone->ease2 = 1.0f; - bone->scale_in_x = 1.0f; - bone->scale_in_y = 1.0f; - bone->scale_out_x = 1.0f; - bone->scale_out_y = 1.0f; + + copy_v3_fl(bone->scale_in, 1.0f); + copy_v3_fl(bone->scale_out, 1.0f); return bone; } @@ -226,7 +225,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op)) static int armature_click_extrude_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - /* TODO most of this code is copied from set3dcursor_invoke, + /* TODO: most of this code is copied from set3dcursor_invoke, * it would be better to reuse code in set3dcursor_invoke */ /* temporarily change 3d cursor position */ @@ -439,17 +438,15 @@ static void updateDuplicateSubtarget(EditBone *dup_bone, } } -static void updateDuplicateActionConstraintSettings(EditBone *dup_bone, - EditBone *orig_bone, - Object *ob, - bConstraint *curcon) +static void updateDuplicateActionConstraintSettings( + EditBone *dup_bone, EditBone *orig_bone, Object *ob, bPoseChannel *pchan, bConstraint *curcon) { bActionConstraint *act_con = (bActionConstraint *)curcon->data; bAction *act = (bAction *)act_con->act; float mat[4][4]; - bConstraintOb cob = {.depsgraph = NULL, .scene = NULL, .ob = ob, .pchan = NULL}; + bConstraintOb cob = {.depsgraph = NULL, .scene = NULL, .ob = ob, .pchan = pchan}; BKE_constraint_custom_object_space_get(cob.space_obj_world_matrix, curcon); unit_m4(mat); @@ -833,7 +830,7 @@ static void updateDuplicateConstraintSettings(EditBone *dup_bone, EditBone *orig for (curcon = conlist->first; curcon; curcon = curcon->next) { switch (curcon->type) { case CONSTRAINT_TYPE_ACTION: - updateDuplicateActionConstraintSettings(dup_bone, orig_bone, ob, curcon); + updateDuplicateActionConstraintSettings(dup_bone, orig_bone, ob, pchan, curcon); break; case CONSTRAINT_TYPE_KINEMATIC: updateDuplicateKinematicConstraintSettings(curcon); @@ -1265,6 +1262,10 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) ebone->bbone_prev_type = ebone_iter->bbone_prev_type; ebone->bbone_next_type = ebone_iter->bbone_next_type; + ebone->bbone_flag = ebone_iter->bbone_flag; + ebone->bbone_prev_flag = ebone_iter->bbone_prev_flag; + ebone->bbone_next_flag = ebone_iter->bbone_next_flag; + /* Lets try to fix any constraint subtargets that might * have been duplicated */ @@ -1464,15 +1465,14 @@ static int armature_extrude_exec(bContext *C, wmOperator *op) newbone->roll1 = ebone->roll1; newbone->roll2 = ebone->roll2; newbone->curve_in_x = ebone->curve_in_x; - newbone->curve_in_y = ebone->curve_in_y; + newbone->curve_in_z = ebone->curve_in_z; newbone->curve_out_x = ebone->curve_out_x; - newbone->curve_out_y = ebone->curve_out_y; + newbone->curve_out_z = ebone->curve_out_z; newbone->ease1 = ebone->ease1; newbone->ease2 = ebone->ease2; - newbone->scale_in_x = ebone->scale_in_x; - newbone->scale_in_y = ebone->scale_in_y; - newbone->scale_out_x = ebone->scale_out_x; - newbone->scale_out_y = ebone->scale_out_y; + + copy_v3_v3(newbone->scale_in, ebone->scale_in); + copy_v3_v3(newbone->scale_out, ebone->scale_out); BLI_strncpy(newbone->name, ebone->name, sizeof(newbone->name)); @@ -1556,7 +1556,7 @@ void ARMATURE_OT_extrude(wmOperatorType *ot) /* ********************** Bone Add *************************************/ -/*op makes a new bone and returns it with its tip selected */ +/* Op makes a new bone and returns it with its tip selected. */ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) { @@ -1601,7 +1601,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) ED_armature_edit_refresh_layer_used(obedit->data); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit); DEG_id_tag_update(&obedit->id, ID_RECALC_SELECT); ED_outliner_select_sync_from_edit_bone_tag(C); @@ -1692,7 +1692,7 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit); DEG_id_tag_update(&obedit->id, ID_RECALC_SELECT); ED_outliner_select_sync_from_edit_bone_tag(C); diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index 912aafbd6e3..ea6c71fd33f 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -228,7 +228,7 @@ float ED_armature_ebone_roll_to_vector(const EditBone *bone, return roll; } -/* note, ranges arithmetic is used below */ +/* NOTE: ranges arithmetic is used below. */ typedef enum eCalcRollTypes { /* pos */ CALC_ROLL_POS_X = 0, @@ -449,7 +449,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op) } if (changed) { - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); DEG_id_tag_update(&arm->id, ID_RECALC_SELECT); } @@ -519,7 +519,7 @@ static int armature_roll_clear_exec(bContext *C, wmOperator *op) } if (changed) { - /* Note, notifier might evolve. */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); DEG_id_tag_update(&arm->id, ID_RECALC_SELECT); } @@ -577,7 +577,7 @@ static void chains_find_tips(ListBase *edbo, ListBase *list) EditBone *curBone, *ebo; LinkData *ld; - /* note: this is potentially very slow ... there's got to be a better way */ + /* NOTE: this is potentially very slow ... there's got to be a better way. */ for (curBone = edbo->first; curBone; curBone = curBone->next) { short stop = 0; @@ -1000,7 +1000,7 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) armature_clear_swap_done_flags(arm); armature_tag_unselect(arm); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); DEG_id_tag_update(&arm->id, ID_RECALC_SELECT); } @@ -1030,7 +1030,7 @@ void ARMATURE_OT_switch_direction(wmOperatorType *ot) /** \name Align Operator * \{ */ -/* helper to fix a ebone position if its parent has moved due to alignment*/ +/* Helper to fix a ebone position if its parent has moved due to alignment. */ static void fix_connected_bone(EditBone *ebone) { float diff[3]; @@ -1073,9 +1073,9 @@ static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actb add_v3_v3v3(selbone->tail, selbone->head, actboneaxis); selbone->roll = actbone->roll; - /* if the bone being aligned has connected descendants they must be moved + /* If the bone being aligned has connected descendants they must be moved * according to their parent new position, otherwise they would be left - * in an inconsistent state: connected but away from the parent*/ + * in an inconsistent state: connected but away from the parent. */ fix_editbone_connected_children(edbo, selbone); } @@ -1107,7 +1107,7 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op) } } - /* if there is only 1 selected bone, we assume that that is the active bone, + /* if there is only 1 selected bone, we assume that it is the active bone, * since a user will need to have clicked on a bone (thus selecting it) to make it active */ num_selected_bones = CTX_DATA_COUNT(C, selected_editable_bones); @@ -1151,7 +1151,7 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op) op->reports, RPT_INFO, "%d bones aligned to bone '%s'", num_selected_bones, actbone->name); } - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); DEG_id_tag_update(&arm->id, ID_RECALC_SELECT); diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index 4fff2ae03b0..d429e51061b 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -161,11 +161,11 @@ typedef struct tPChanFCurveLink { /** old bbone values (to be restored along with the transform properties) */ float roll1, roll2; /** (NOTE: we haven't renamed these this time, as their names are already long enough) */ - float curve_in_x, curve_in_y; - float curve_out_x, curve_out_y; + float curve_in_x, curve_in_z; + float curve_out_x, curve_out_z; float ease1, ease2; - float scale_in_x, scale_in_y; - float scale_out_x, scale_out_y; + float scale_in[3]; + float scale_out[3]; /** copy of custom properties at start of operator (to be restored before each modal step) */ struct IDProperty *oldprops; diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index 70154695dcd..35bd30377c8 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -69,7 +69,7 @@ /** \name Unique Bone Name Utility (Edit Mode) * \{ */ -/* note: there's a ed_armature_bone_unique_name() too! */ +/* NOTE: there's a ed_armature_bone_unique_name() too! */ static bool editbone_unique_check(void *arg, const char *name) { struct { @@ -589,7 +589,7 @@ static int armature_autoside_names_exec(bContext *C, wmOperator *op) /* Since we renamed stuff... */ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - /* Note, notifier might evolve. */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); } MEM_freeN(objects); diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 66ca38ce218..32fd1c9ad41 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -457,7 +457,7 @@ static void separated_armature_fix_links(Main *bmain, Object *origArm, Object *n bConstraint *con; ListBase *opchans, *npchans; - /* get reference to list of bones in original and new armatures */ + /* Get reference to list of bones in original and new armatures. */ opchans = &origArm->pose->chanbase; npchans = &newArm->pose->chanbase; @@ -576,7 +576,7 @@ static void separate_armature_bones(Main *bmain, Object *ob, const bool is_selec /* check if bone needs to be removed */ if (is_select == (EBONE_VISIBLE(arm, curbone) && (curbone->flag & BONE_SELECTED))) { - /* clear the bone->parent var of any bone that had this as its parent */ + /* Clear the bone->parent var of any bone that had this as its parent. */ LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) { if (ebo->parent == curbone) { ebo->parent = NULL; @@ -703,7 +703,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op) ok = true; - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob_old); } MEM_freeN(bases); @@ -838,7 +838,7 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op) } } - /* If there is only 1 selected bone, we assume that that is the active bone, + /* If there is only 1 selected bone, we assume that it is the active bone, * since a user will need to have clicked on a bone (thus selecting it) to make it active. */ bool is_active_only_selected = false; if (actbone->flag & BONE_SELECTED) { @@ -893,7 +893,7 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op) } } - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); DEG_id_tag_update(&ob->id, ID_RECALC_SELECT); @@ -1004,7 +1004,7 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op) ED_armature_edit_sync_selection(arm->edbo); - /* Note, notifier might evolve. */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); } MEM_freeN(objects); diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 65f30c3729f..bd799c00373 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -1426,7 +1426,7 @@ static void armature_select_more_less(Object *ob, bool more) bArmature *arm = (bArmature *)ob->data; EditBone *ebone; - /* XXX, eventually we shouldn't need this - campbell */ + /* XXX(campbell): eventually we shouldn't need this. */ ED_armature_edit_sync_selection(arm->edbo); /* count bones & store selection state */ diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index f86ec545712..ec5c665402b 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -478,7 +478,7 @@ void ED_object_vgroup_calc_from_armature(ReportList *reports, bArmature *arm = par->data; if (mode == ARM_GROUPS_NAME) { - const int defbase_tot = BLI_listbase_count(&ob->defbase); + const int defbase_tot = BKE_object_defgroup_count(ob); int defbase_add; /* Traverse the bone list, trying to create empty vertex * groups corresponding to the bone. @@ -486,8 +486,8 @@ void ED_object_vgroup_calc_from_armature(ReportList *reports, defbase_add = bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb); if (defbase_add) { - /* its possible there are DWeight's outside the range of the current - * objects deform groups, in this case the new groups wont be empty T33889. */ + /* It's possible there are DWeights outside the range of the current + * object's deform groups. In this case the new groups won't be empty T33889. */ ED_vgroup_data_clamp_range(ob->data, defbase_tot); } } diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index 3d1d8d0d1f1..874f1b49451 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -391,7 +391,7 @@ void armature_tag_unselect(bArmature *arm) void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bool check_select) { - /* TODO When this function is called by property updates, + /* TODO: When this function is called by property updates, * canceling the value change will not restore mirrored bone correctly. */ /* Currently check_select==true when this function is called from a transform operator, @@ -414,9 +414,8 @@ void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bo eboflip->tail[2] = ebo->tail[2]; eboflip->rad_tail = ebo->rad_tail; eboflip->curve_out_x = -ebo->curve_out_x; - eboflip->curve_out_y = ebo->curve_out_y; - eboflip->scale_out_x = ebo->scale_out_x; - eboflip->scale_out_y = ebo->scale_out_y; + eboflip->curve_out_z = ebo->curve_out_z; + copy_v3_v3(eboflip->scale_out, ebo->scale_out); eboflip->ease2 = ebo->ease2; eboflip->roll2 = -ebo->roll2; @@ -438,9 +437,8 @@ void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bo eboflip->rad_head = ebo->rad_head; eboflip->curve_in_x = -ebo->curve_in_x; - eboflip->curve_in_y = ebo->curve_in_y; - eboflip->scale_in_x = ebo->scale_in_x; - eboflip->scale_in_y = ebo->scale_in_y; + eboflip->curve_in_z = ebo->curve_in_z; + copy_v3_v3(eboflip->scale_in, ebo->scale_in); eboflip->ease1 = ebo->ease1; eboflip->roll1 = -ebo->roll1; @@ -542,19 +540,22 @@ static EditBone *make_boneList_recursive(ListBase *edbo, eBone->roll1 = curBone->roll1; eBone->roll2 = curBone->roll2; eBone->curve_in_x = curBone->curve_in_x; - eBone->curve_in_y = curBone->curve_in_y; + eBone->curve_in_z = curBone->curve_in_z; eBone->curve_out_x = curBone->curve_out_x; - eBone->curve_out_y = curBone->curve_out_y; + eBone->curve_out_z = curBone->curve_out_z; eBone->ease1 = curBone->ease1; eBone->ease2 = curBone->ease2; - eBone->scale_in_x = curBone->scale_in_x; - eBone->scale_in_y = curBone->scale_in_y; - eBone->scale_out_x = curBone->scale_out_x; - eBone->scale_out_y = curBone->scale_out_y; + + copy_v3_v3(eBone->scale_in, curBone->scale_in); + copy_v3_v3(eBone->scale_out, curBone->scale_out); eBone->bbone_prev_type = curBone->bbone_prev_type; eBone->bbone_next_type = curBone->bbone_next_type; + eBone->bbone_flag = curBone->bbone_flag; + eBone->bbone_prev_flag = curBone->bbone_prev_flag; + eBone->bbone_next_flag = curBone->bbone_next_flag; + if (curBone->prop) { eBone->prop = IDP_CopyProperty(curBone->prop); } @@ -757,19 +758,21 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm) newBone->roll1 = eBone->roll1; newBone->roll2 = eBone->roll2; newBone->curve_in_x = eBone->curve_in_x; - newBone->curve_in_y = eBone->curve_in_y; + newBone->curve_in_z = eBone->curve_in_z; newBone->curve_out_x = eBone->curve_out_x; - newBone->curve_out_y = eBone->curve_out_y; + newBone->curve_out_z = eBone->curve_out_z; newBone->ease1 = eBone->ease1; newBone->ease2 = eBone->ease2; - newBone->scale_in_x = eBone->scale_in_x; - newBone->scale_in_y = eBone->scale_in_y; - newBone->scale_out_x = eBone->scale_out_x; - newBone->scale_out_y = eBone->scale_out_y; + copy_v3_v3(newBone->scale_in, eBone->scale_in); + copy_v3_v3(newBone->scale_out, eBone->scale_out); newBone->bbone_prev_type = eBone->bbone_prev_type; newBone->bbone_next_type = eBone->bbone_next_type; + newBone->bbone_flag = eBone->bbone_flag; + newBone->bbone_prev_flag = eBone->bbone_prev_flag; + newBone->bbone_next_flag = eBone->bbone_next_flag; + if (eBone->prop) { newBone->prop = IDP_CopyProperty(eBone->prop); } @@ -844,7 +847,7 @@ void ED_armature_to_edit(bArmature *arm) } /* *************************************************************** */ -/* Used by Undo for Armature EditMode*/ +/* Used by Undo for Armature EditMode. */ /* free's bones and their properties */ diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c index 725945f8edc..832e75b2a8b 100644 --- a/source/blender/editors/armature/editarmature_undo.c +++ b/source/blender/editors/armature/editarmature_undo.c @@ -206,7 +206,7 @@ static void armature_undosys_step_decode(struct bContext *C, } undoarm_to_editarm(&elem->data, arm); arm->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&arm->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index f5daa427149..20d7baa39ed 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -224,7 +224,7 @@ void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob, ePosePathC #endif /* For a single frame update it's faster to re-use existing dependency graph and avoid overhead - * of building all the relations and so on for a temporary one. */ + * of building all the relations and so on for a temporary one. */ if (range == POSE_PATH_CALC_RANGE_CURRENT_FRAME) { /* NOTE: Dependency graph will be evaluated at all the frames, but we first need to access some * nested pointers, like animation data. */ @@ -318,7 +318,7 @@ static int pose_calculate_paths_exec(bContext *C, wmOperator *op) TIMEIT_START(recalc_pose_paths); #endif - /* calculate the bones that now have motionpaths... */ + /* Calculate the bones that now have motionpaths. */ /* TODO: only make for the selected bones? */ ED_pose_recalculate_paths(C, scene, ob, POSE_PATH_CALC_RANGE_FULL); @@ -396,7 +396,7 @@ static int pose_update_paths_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - /* calculate the bones that now have motionpaths... */ + /* Calculate the bones that now have motion-paths. */ /* TODO: only make for the selected bones? */ ED_pose_recalculate_paths(C, scene, ob, POSE_PATH_CALC_RANGE_FULL); @@ -455,7 +455,7 @@ static void ED_pose_clear_paths(Object *ob, bool only_selected) DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); } -/* operator callback - wrapper for the backend function */ +/* Operator callback - wrapper for the back-end function. */ static int pose_clear_paths_exec(bContext *C, wmOperator *op) { Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); @@ -567,7 +567,7 @@ static int pose_flip_names_exec(bContext *C, wmOperator *op) /* since we renamed stuff... */ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); } FOREACH_OBJECT_IN_MODE_END; @@ -618,7 +618,7 @@ static int pose_autoside_names_exec(bContext *C, wmOperator *op) /* since we renamed stuff... */ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); ob_prev = ob; } @@ -663,7 +663,7 @@ static int pose_bone_rotmode_exec(bContext *C, wmOperator *op) const int mode = RNA_enum_get(op->ptr, "type"); Object *prev_ob = NULL; - /* set rotation mode of selected bones */ + /* Set rotation mode of selected bones. */ CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob) { /* use API Method for conversions... */ BKE_rotMode_change_values( @@ -760,7 +760,7 @@ static int pose_armature_layers_showall_exec(bContext *C, wmOperator *op) RNA_boolean_set_array(&ptr, "layers", layers); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); @@ -833,7 +833,7 @@ static int armature_layers_exec(bContext *C, wmOperator *op) RNA_id_pointer_create((ID *)arm, &ptr); RNA_boolean_set_array(&ptr, "layers", layers); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); @@ -919,7 +919,7 @@ static int pose_bone_layers_exec(bContext *C, wmOperator *op) RNA_boolean_set_array(&ptr, "layers", layers); if (prev_ob != ob) { - /* Note, notifier might evolve. */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); DEG_id_tag_update((ID *)ob->data, ID_RECALC_COPY_ON_WRITE); prev_ob = ob; @@ -998,7 +998,7 @@ static int armature_bone_layers_exec(bContext *C, wmOperator *op) ED_armature_edit_refresh_layer_used(ob->data); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); return OPERATOR_FINISHED; diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index 21fcbf8886b..df3550d5db6 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -516,7 +516,7 @@ static int poselib_add_exec(bContext *C, wmOperator *op) /* use Keying Set to determine what to store for the pose */ - /* this includes custom props :)*/ + /* This includes custom props :). */ ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_WHOLE_CHARACTER_SELECTED_ID); ANIM_apply_keyingset(C, NULL, act, ks, MODIFYKEY_MODE_INSERT, (float)frame); @@ -863,7 +863,7 @@ typedef struct tPoseLib_PreviewData { /** active area. */ ScrArea *area; - /** RNA-Pointer to Object 'ob' .*/ + /** RNA-Pointer to Object 'ob'. */ PointerRNA rna_ptr; /** object to work on. */ Object *ob; @@ -1100,7 +1100,7 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData /* start tagging/keying */ for (agrp = act->groups.first; agrp; agrp = agrp->next) { - /* only for selected bones unless there aren't any selected, in which case all are included */ + /* Only for selected bones unless there aren't any selected, in which case all are included. */ pchan = BKE_pose_channel_find_name(pose, agrp->name); if (pchan) { @@ -1462,7 +1462,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con pld->state = PL_PREVIEW_CONFIRM; break; - /* toggle between original pose and poselib pose*/ + /* Toggle between original pose and poselib pose. */ case EVT_TABKEY: pld->flag |= PL_PREVIEW_SHOWORIGINAL; pld->redraw = PL_PREVIEW_REDRAWALL; diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 8fc06a5f962..c39fcb790dd 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -69,7 +69,7 @@ /* ***************** Pose Select Utilities ********************* */ -/* Note: SEL_TOGGLE is assumed to have already been handled! */ +/* NOTE: SEL_TOGGLE is assumed to have already been handled! */ static void pose_do_bone_select(bPoseChannel *pchan, const int select_mode) { /* select pchan only if selectable, but deselect works always */ @@ -161,9 +161,9 @@ void ED_armature_pose_select_pick_bone(ViewLayer *view_layer, /* Since we do unified select, we don't shift+select a bone if the * armature object was not active yet. - * Note, special exception for armature mode so we can do multi-select + * NOTE(campbell): special exception for armature mode so we can do multi-select * we could check for multi-select explicitly but think its fine to - * always give predictable behavior in weight paint mode - campbell */ + * always give predictable behavior in weight paint mode. */ if ((ob_act == NULL) || ((ob_act != ob) && (ob_act->mode & OB_MODE_ALL_WEIGHT_PAINT) == 0)) { /* When we are entering into posemode via toggle-select, * from another active object - always select the bone. */ diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index f7b54b79601..1a1685e4a01 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -19,6 +19,28 @@ /** \file * \ingroup edarmature + * + * Pose 'Sliding' Tools + * ==================== + * + * - Push & Relax, Breakdowner + + * These tools provide the animator with various capabilities + * for interactively controlling the spacing of poses, but also + * for 'pushing' and/or 'relaxing' extremes as they see fit. + * + * - Propagate + + * This tool copies elements of the selected pose to successive + * keyframes, allowing the animator to go back and modify the poses + * for some "static" pose controls, without having to repeatedly + * doing a "next paste" dance. + * + * - Pose Sculpting (TODO) + + * This is yet to be implemented, but the idea here is to use + * sculpting techniques to make it easier to pose rigs by allowing + * rigs to be manipulated using a familiar paint-based interface. */ #include "MEM_guardedalloc.h" @@ -75,35 +97,48 @@ #define OVERSHOOT_RANGE_DELTA 0.2f /* **************************************************** */ -/* == POSE 'SLIDING' TOOLS == - * - * A) Push & Relax, Breakdowner - * These tools provide the animator with various capabilities - * for interactively controlling the spacing of poses, but also - * for 'pushing' and/or 'relaxing' extremes as they see fit. - * - * B) Propagate - * This tool copies elements of the selected pose to successive - * keyframes, allowing the animator to go back and modify the poses - * for some "static" pose controls, without having to repeatedly - * doing a "next paste" dance. - * - * C) Pose Sculpting - * This is yet to be implemented, but the idea here is to use - * sculpting techniques to make it easier to pose rigs by allowing - * rigs to be manipulated using a familiar paint-based interface. - */ -/* **************************************************** */ /* A) Push & Relax, Breakdowner */ -/* Temporary data shared between these operators */ +/** Axis Locks. */ +typedef enum ePoseSlide_AxisLock { + PS_LOCK_X = (1 << 0), + PS_LOCK_Y = (1 << 1), + PS_LOCK_Z = (1 << 2), +} ePoseSlide_AxisLock; + +/** Pose Sliding Modes. */ +typedef enum ePoseSlide_Modes { + /** Exaggerate the pose. */ + POSESLIDE_PUSH = 0, + /** soften the pose. */ + POSESLIDE_RELAX, + /** Slide between the endpoint poses, finding a 'soft' spot. */ + POSESLIDE_BREAKDOWN, + POSESLIDE_PUSH_REST, + POSESLIDE_RELAX_REST, +} ePoseSlide_Modes; + +/** Transforms/Channels to Affect. */ +typedef enum ePoseSlide_Channels { + PS_TFM_ALL = 0, /* All transforms and properties */ + + PS_TFM_LOC, /* Loc/Rot/Scale */ + PS_TFM_ROT, + PS_TFM_SIZE, + + PS_TFM_BBONE_SHAPE, /* Bendy Bones */ + + PS_TFM_PROPS, /* Custom Properties */ +} ePoseSlide_Channels; + +/** Temporary data shared between these operators. */ typedef struct tPoseSlideOp { /** current scene */ Scene *scene; /** area that we're operating in (needed for modal()) */ ScrArea *area; - /** region that we're operating in (needed for modal()) */ - ARegion *region; + /** Header of the region used for drawing the slider. */ + ARegion *region_header; /** len of the PoseSlideObject array. */ uint objects_len; @@ -120,76 +155,57 @@ typedef struct tPoseSlideOp { /** frame after current frame (blend-to) - global time */ int nextFrame; - /** sliding mode (ePoseSlide_Modes) */ - short mode; + /** Sliding Mode. */ + ePoseSlide_Modes mode; /** unused for now, but can later get used for storing runtime settings.... */ short flag; /* Store overlay settings when invoking the operator. Bones will be temporarily hidden. */ int overlay_flag; - /** which transforms/channels are affected (ePoseSlide_Channels) */ - short channels; - /** axis-limits for transforms (ePoseSlide_AxisLock) */ - short axislock; + /** Which transforms/channels are affected. */ + ePoseSlide_Channels channels; + /** Axis-limits for transforms. */ + ePoseSlide_AxisLock axislock; - /* Allow overshoot or clamp between 0% and 100%. */ + /** Allow overshoot or clamp between 0% and 100%. */ bool overshoot; - /* Reduces percentage delta from mouse movement. */ + /** Reduces factor delta from mouse movement. */ bool precision; - /* Move percentage in 10% steps. */ + /** Move factor in 10% steps. */ bool increments; - /* Draw callback handler. */ + /** Draw callback handler. */ void *draw_handle; - /* Accumulative, unclamped and unrounded percentage. */ - float raw_percentage; + /** Accumulative, unclamped and unrounded factor. */ + float raw_factor; - /* 0-1 value for determining the influence of whatever is relevant. */ - float percentage; + /** 0-1 value for determining the influence of whatever is relevant. */ + float factor; - /* Last cursor position in screen space used for mouse movement delta calculation. */ + /** Last cursor position in screen space used for mouse movement delta calculation. */ int last_cursor_x; - /* Numeric input. */ + /** Numeric input. */ NumInput num; struct tPoseSlideObject *ob_data_array; } tPoseSlideOp; typedef struct tPoseSlideObject { - Object *ob; /* active object that Pose Info comes from */ - float prevFrameF; /* prevFrame, but in local action time (for F-Curve lookups to work) */ - float nextFrameF; /* nextFrame, but in local action time (for F-Curve lookups to work) */ + /** Active object that Pose Info comes from. */ + Object *ob; + /** `prevFrame`, but in local action time (for F-Curve look-ups to work). */ + float prevFrameF; + /** `nextFrame`, but in local action time (for F-Curve look-ups to work). */ + float nextFrameF; bool valid; } tPoseSlideObject; -/* Pose Sliding Modes */ -typedef enum ePoseSlide_Modes { - POSESLIDE_PUSH = 0, /* exaggerate the pose... */ - POSESLIDE_RELAX, /* soften the pose... */ - POSESLIDE_BREAKDOWN, /* slide between the endpoint poses, finding a 'soft' spot */ - POSESLIDE_PUSH_REST, - POSESLIDE_RELAX_REST, -} ePoseSlide_Modes; - -/* Transforms/Channels to Affect */ -typedef enum ePoseSlide_Channels { - PS_TFM_ALL = 0, /* All transforms and properties */ - - PS_TFM_LOC, /* Loc/Rot/Scale */ - PS_TFM_ROT, - PS_TFM_SIZE, - - PS_TFM_BBONE_SHAPE, /* Bendy Bones */ - - PS_TFM_PROPS, /* Custom Properties */ -} ePoseSlide_Channels; - -/* Property enum for ePoseSlide_Channels */ +/** Property enum for #ePoseSlide_Channels. */ static const EnumPropertyItem prop_channels_types[] = { {PS_TFM_ALL, "ALL", @@ -204,13 +220,6 @@ static const EnumPropertyItem prop_channels_types[] = { {0, NULL, 0, NULL, NULL}, }; -/* Axis Locks */ -typedef enum ePoseSlide_AxisLock { - PS_LOCK_X = (1 << 0), - PS_LOCK_Y = (1 << 1), - PS_LOCK_Z = (1 << 2), -} ePoseSlide_AxisLock; - /* Property enum for ePoseSlide_AxisLock */ static const EnumPropertyItem prop_axis_lock_types[] = { {0, "FREE", 0, "Free", "All axes are affected"}, @@ -248,22 +257,22 @@ static void draw_overshoot_triangle(const uint8_t color[4], immUnbindProgram(); } -static void draw_ticks(const float start_percentage, - const float end_percentage, - const struct vec2f line_start, +static void draw_ticks(const float start_factor, + const float end_factor, + const float line_start[2], const float base_tick_height, const float line_width, const uint8_t color_overshoot[4], const uint8_t color_line[4]) { - /* Use percentage represented as 0-100 int to avoid floating point precision problems. */ + /* Use factor represented as 0-100 int to avoid floating point precision problems. */ const int tick_increment = 10; - /* Round initial_tick_percentage up to the next tick_increment. */ - int tick_percentage = ceil((start_percentage * 100) / tick_increment) * tick_increment; - float tick_height = base_tick_height; + /* Round initial_tick_factor up to the next tick_increment. */ + int tick_percentage = ceil((start_factor * 100) / tick_increment) * tick_increment; - while (tick_percentage <= (int)(end_percentage * 100)) { + while (tick_percentage <= (int)(end_factor * 100)) { + float tick_height; /* Different ticks have different heights. Multiples of 100% are the tallest, 50% is a bit * smaller and the rest is the minimum size. */ if (tick_percentage % 100 == 0) { @@ -276,12 +285,14 @@ static void draw_ticks(const float start_percentage, tick_height = base_tick_height * 0.5; } - const float x = line_start.x + - (((float)tick_percentage / 100) - start_percentage) * SLIDE_PIXEL_DISTANCE; - const struct rctf tick_rect = {.xmin = x - (line_width / 2), - .xmax = x + (line_width / 2), - .ymin = line_start.y - (tick_height / 2), - .ymax = line_start.y + (tick_height / 2)}; + const float x = line_start[0] + + (((float)tick_percentage / 100) - start_factor) * SLIDE_PIXEL_DISTANCE; + const rctf tick_rect = { + .xmin = x - (line_width / 2), + .xmax = x + (line_width / 2), + .ymin = line_start[1] - (tick_height / 2), + .ymax = line_start[1] + (tick_height / 2), + }; if (tick_percentage < 0 || tick_percentage > 100) { UI_draw_roundbox_3ub_alpha(&tick_rect, true, 1, color_overshoot, 255); @@ -293,73 +304,83 @@ static void draw_ticks(const float start_percentage, } } -static void draw_main_line(const struct rctf main_line_rect, - const float percentage, +static void draw_main_line(const rctf *main_line_rect, + const float factor, const bool overshoot, const uint8_t color_overshoot[4], const uint8_t color_line[4]) { if (overshoot) { /* In overshoot mode, draw the 0-100% range differently to provide a visual reference. */ - const float line_zero_percent = main_line_rect.xmin - - ((percentage - 0.5f - OVERSHOOT_RANGE_DELTA) * + const float line_zero_percent = main_line_rect->xmin - + ((factor - 0.5f - OVERSHOOT_RANGE_DELTA) * SLIDE_PIXEL_DISTANCE); const float clamped_line_zero_percent = clamp_f( - line_zero_percent, main_line_rect.xmin, main_line_rect.xmax); + line_zero_percent, main_line_rect->xmin, main_line_rect->xmax); const float clamped_line_hundred_percent = clamp_f( - line_zero_percent + SLIDE_PIXEL_DISTANCE, main_line_rect.xmin, main_line_rect.xmax); - - const struct rctf left_overshoot_line_rect = {.xmin = main_line_rect.xmin, - .xmax = clamped_line_zero_percent, - .ymin = main_line_rect.ymin, - .ymax = main_line_rect.ymax}; - const struct rctf right_overshoot_line_rect = {.xmin = clamped_line_hundred_percent, - .xmax = main_line_rect.xmax, - .ymin = main_line_rect.ymin, - .ymax = main_line_rect.ymax}; + line_zero_percent + SLIDE_PIXEL_DISTANCE, main_line_rect->xmin, main_line_rect->xmax); + + const rctf left_overshoot_line_rect = { + .xmin = main_line_rect->xmin, + .xmax = clamped_line_zero_percent, + .ymin = main_line_rect->ymin, + .ymax = main_line_rect->ymax, + }; + const rctf right_overshoot_line_rect = { + .xmin = clamped_line_hundred_percent, + .xmax = main_line_rect->xmax, + .ymin = main_line_rect->ymin, + .ymax = main_line_rect->ymax, + }; UI_draw_roundbox_3ub_alpha(&left_overshoot_line_rect, true, 0, color_overshoot, 255); UI_draw_roundbox_3ub_alpha(&right_overshoot_line_rect, true, 0, color_overshoot, 255); - const struct rctf non_overshoot_line_rect = {.xmin = clamped_line_zero_percent, - .xmax = clamped_line_hundred_percent, - .ymin = main_line_rect.ymin, - .ymax = main_line_rect.ymax}; + const rctf non_overshoot_line_rect = { + .xmin = clamped_line_zero_percent, + .xmax = clamped_line_hundred_percent, + .ymin = main_line_rect->ymin, + .ymax = main_line_rect->ymax, + }; UI_draw_roundbox_3ub_alpha(&non_overshoot_line_rect, true, 0, color_line, 255); } else { - UI_draw_roundbox_3ub_alpha(&main_line_rect, true, 0, color_line, 255); + UI_draw_roundbox_3ub_alpha(main_line_rect, true, 0, color_line, 255); } } static void draw_backdrop(const int fontid, - const struct rctf main_line_rect, + const rctf *main_line_rect, const float color_bg[4], const short region_y_size, const float base_tick_height) { float string_pixel_size[2]; - const char *percentage_placeholder = "000%%"; + const char *percentage_string_placeholder = "000%%"; BLF_width_and_height(fontid, - percentage_placeholder, - sizeof(percentage_placeholder), + percentage_string_placeholder, + sizeof(percentage_string_placeholder), &string_pixel_size[0], &string_pixel_size[1]); - const struct vec2f pad = {.x = (region_y_size - base_tick_height) / 2, .y = 2.0f * U.pixelsize}; - const struct rctf backdrop_rect = {.xmin = main_line_rect.xmin - string_pixel_size[0] - pad.x, - .xmax = main_line_rect.xmax + pad.x, - .ymin = pad.y, - .ymax = region_y_size - pad.y}; + const float pad[2] = {(region_y_size - base_tick_height) / 2, 2.0f * U.pixelsize}; + const rctf backdrop_rect = { + .xmin = main_line_rect->xmin - string_pixel_size[0] - pad[0], + .xmax = main_line_rect->xmax + pad[0], + .ymin = pad[1], + .ymax = region_y_size - pad[1], + }; UI_draw_roundbox_aa(&backdrop_rect, true, 4.0f, color_bg); } -/* Draw an on screen Slider for a Pose Slide Operator. */ +/** + * Draw an on screen Slider for a Pose Slide Operator. + */ static void pose_slide_draw_2d_slider(const struct bContext *UNUSED(C), ARegion *region, void *arg) { tPoseSlideOp *pso = arg; /* Only draw in region from which the Operator was started. */ - if (region != pso->region) { + if (region != pso->region_header) { return; } @@ -392,28 +413,30 @@ static void pose_slide_draw_2d_slider(const struct bContext *UNUSED(C), ARegion const float base_tick_height = 12.0 * U.pixelsize; const float line_y = region->winy / 2; - struct rctf main_line_rect = {.xmin = (region->winx / 2) - (SLIDE_PIXEL_DISTANCE / 2), - .xmax = (region->winx / 2) + (SLIDE_PIXEL_DISTANCE / 2), - .ymin = line_y - line_width / 2, - .ymax = line_y + line_width / 2}; - float line_start_percentage = 0; - int handle_pos_x = main_line_rect.xmin + SLIDE_PIXEL_DISTANCE * pso->percentage; + rctf main_line_rect = { + .xmin = (region->winx / 2) - (SLIDE_PIXEL_DISTANCE / 2), + .xmax = (region->winx / 2) + (SLIDE_PIXEL_DISTANCE / 2), + .ymin = line_y - line_width / 2, + .ymax = line_y + line_width / 2, + }; + float line_start_factor = 0; + int handle_pos_x = main_line_rect.xmin + SLIDE_PIXEL_DISTANCE * pso->factor; if (pso->overshoot) { main_line_rect.xmin = main_line_rect.xmin - SLIDE_PIXEL_DISTANCE * OVERSHOOT_RANGE_DELTA; main_line_rect.xmax = main_line_rect.xmax + SLIDE_PIXEL_DISTANCE * OVERSHOOT_RANGE_DELTA; - line_start_percentage = pso->percentage - 0.5f - OVERSHOOT_RANGE_DELTA; + line_start_factor = pso->factor - 0.5f - OVERSHOOT_RANGE_DELTA; handle_pos_x = region->winx / 2; } - draw_backdrop(fontid, main_line_rect, color_bg, pso->region->winy, base_tick_height); + draw_backdrop(fontid, &main_line_rect, color_bg, pso->region_header->winy, base_tick_height); - draw_main_line(main_line_rect, pso->percentage, pso->overshoot, color_overshoot, color_line); + draw_main_line(&main_line_rect, pso->factor, pso->overshoot, color_overshoot, color_line); - const float percentage_range = pso->overshoot ? 1 + OVERSHOOT_RANGE_DELTA * 2 : 1; - const struct vec2f line_start_position = {.x = main_line_rect.xmin, .y = line_y}; - draw_ticks(line_start_percentage, - line_start_percentage + percentage_range, + const float factor_range = pso->overshoot ? 1 + OVERSHOOT_RANGE_DELTA * 2 : 1; + const float line_start_position[2] = {main_line_rect.xmin, line_y}; + draw_ticks(line_start_factor, + line_start_factor + factor_range, line_start_position, base_tick_height, line_width, @@ -421,70 +444,72 @@ static void pose_slide_draw_2d_slider(const struct bContext *UNUSED(C), ARegion color_line); /* Draw triangles at the ends of the line in overshoot mode to indicate direction of 0-100% - * range.*/ + * range. */ if (pso->overshoot) { - if (pso->percentage > 1 + OVERSHOOT_RANGE_DELTA + 0.5) { + if (pso->factor > 1 + OVERSHOOT_RANGE_DELTA + 0.5) { draw_overshoot_triangle(color_line, false, main_line_rect.xmin, line_y); } - if (pso->percentage < 0 - OVERSHOOT_RANGE_DELTA - 0.5) { + if (pso->factor < 0 - OVERSHOOT_RANGE_DELTA - 0.5) { draw_overshoot_triangle(color_line, true, main_line_rect.xmax, line_y); } } char percentage_string[256]; - /* Draw handle indicating current percentage. */ - const struct rctf handle_rect = {.xmin = handle_pos_x - (line_width), - .xmax = handle_pos_x + (line_width), - .ymin = line_y - (base_tick_height / 2), - .ymax = line_y + (base_tick_height / 2)}; + /* Draw handle indicating current factor. */ + const rctf handle_rect = { + .xmin = handle_pos_x - (line_width), + .xmax = handle_pos_x + (line_width), + .ymin = line_y - (base_tick_height / 2), + .ymax = line_y + (base_tick_height / 2), + }; UI_draw_roundbox_3ub_alpha(&handle_rect, true, 1, color_handle, 255); - BLI_snprintf(percentage_string, sizeof(percentage_string), "%.0f%%", pso->percentage * 100); + BLI_snprintf(percentage_string, sizeof(percentage_string), "%.0f%%", pso->factor * 100); /* Draw percentage string. */ - float percentage_pixel_size[2]; + float percentage_string_pixel_size[2]; BLF_width_and_height(fontid, percentage_string, sizeof(percentage_string), - &percentage_pixel_size[0], - &percentage_pixel_size[1]); + &percentage_string_pixel_size[0], + &percentage_string_pixel_size[1]); BLF_position(fontid, - main_line_rect.xmin - 24.0 * U.pixelsize - percentage_pixel_size[0] / 2, - (region->winy / 2) - percentage_pixel_size[1] / 2, + main_line_rect.xmin - 24.0 * U.pixelsize - percentage_string_pixel_size[0] / 2, + (region->winy / 2) - percentage_string_pixel_size[1] / 2, 0.0f); BLF_draw(fontid, percentage_string, sizeof(percentage_string)); } -/* operator init */ +/** Operator custom-data initialization. */ static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode) { tPoseSlideOp *pso; - /* init slide-op data */ + /* Init slide-op data. */ pso = op->customdata = MEM_callocN(sizeof(tPoseSlideOp), "tPoseSlideOp"); - /* get info from context */ + /* Get info from context. */ pso->scene = CTX_data_scene(C); - pso->area = CTX_wm_area(C); /* only really needed when doing modal() */ - pso->region = CTX_wm_region(C); /* only really needed when doing modal() */ + pso->area = CTX_wm_area(C); /* Only really needed when doing modal(). */ + pso->region_header = CTX_wm_region(C); /* Only really needed when doing modal(). */ pso->cframe = pso->scene->r.cfra; pso->mode = mode; - /* set range info from property values - these may get overridden for the invoke() */ - pso->percentage = RNA_float_get(op->ptr, "percentage"); - pso->raw_percentage = pso->percentage; + /* Set range info from property values - these may get overridden for the invoke(). */ + pso->factor = RNA_float_get(op->ptr, "factor"); + pso->raw_factor = pso->factor; pso->prevFrame = RNA_int_get(op->ptr, "prev_frame"); pso->nextFrame = RNA_int_get(op->ptr, "next_frame"); - /* get the set of properties/axes that can be operated on */ + /* Get the set of properties/axes that can be operated on. */ pso->channels = RNA_enum_get(op->ptr, "channels"); pso->axislock = RNA_enum_get(op->ptr, "axis_lock"); - /* for each Pose-Channel which gets affected, get the F-Curves for that channel - * and set the relevant transform flags... */ + /* For each Pose-Channel which gets affected, get the F-Curves for that channel + * and set the relevant transform flags. */ poseAnim_mapping_get(C, &pso->pfLinks); Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data( @@ -504,43 +529,44 @@ static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode) ob_data->ob = ob_iter; ob_data->valid = true; - /* apply NLA mapping corrections so the frame lookups work */ + /* Apply NLA mapping corrections so the frame look-ups work. */ ob_data->prevFrameF = BKE_nla_tweakedit_remap( ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP); ob_data->nextFrameF = BKE_nla_tweakedit_remap( ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP); - /* set depsgraph flags */ - /* make sure the lock is set OK, unlock can be accidentally saved? */ + /* Set depsgraph flags. */ + /* Make sure the lock is set OK, unlock can be accidentally saved? */ ob_data->ob->pose->flag |= POSE_LOCKED; ob_data->ob->pose->flag &= ~POSE_DO_UNLOCK; } MEM_freeN(objects); - /* do basic initialize of RB-BST used for finding keyframes, but leave the filling of it up - * to the caller of this (usually only invoke() will do it, to make things more efficient). - */ + /* Do basic initialize of RB-BST used for finding keyframes, but leave the filling of it up + * to the caller of this (usually only invoke() will do it, to make things more efficient). */ BLI_dlrbTree_init(&pso->keys); /* Initialize numeric input. */ initNumInput(&pso->num); - pso->num.idx_max = 0; /* one axis */ + pso->num.idx_max = 0; /* One axis. */ pso->num.val_flag[0] |= NUM_NO_NEGATIVE; - pso->num.unit_type[0] = B_UNIT_NONE; /* percentages don't have any units... */ + pso->num.unit_type[0] = B_UNIT_NONE; /* Percentages don't have any units. */ /* Register UI drawing callback. */ ARegion *region_header = BKE_area_find_region_type(pso->area, RGN_TYPE_HEADER); if (region_header != NULL) { - pso->region = region_header; + pso->region_header = region_header; pso->draw_handle = ED_region_draw_cb_activate( region_header->type, pose_slide_draw_2d_slider, pso, REGION_DRAW_POST_PIXEL); } - /* return status is whether we've got all the data we were requested to get */ + /* Return status is whether we've got all the data we were requested to get. */ return 1; } -/* exiting the operator - free data */ +/** + * Exiting the operator (free data). + */ static void pose_slide_exit(wmOperator *op) { tPoseSlideOp *pso = op->customdata; @@ -550,34 +576,33 @@ static void pose_slide_exit(wmOperator *op) v3d->overlay.flag = pso->overlay_flag; /* Remove UI drawing callback. */ - ED_region_draw_cb_exit(pso->region->type, pso->draw_handle); - - /* if data exists, clear its data and exit */ - if (pso) { - /* free the temp pchan links and their data */ - poseAnim_mapping_free(&pso->pfLinks); + ED_region_draw_cb_exit(pso->region_header->type, pso->draw_handle); - /* free RB-BST for keyframes (if it contained data) */ - BLI_dlrbTree_free(&pso->keys); + /* Free the temp pchan links and their data. */ + poseAnim_mapping_free(&pso->pfLinks); - if (pso->ob_data_array != NULL) { - MEM_freeN(pso->ob_data_array); - } + /* Free RB-BST for keyframes (if it contained data). */ + BLI_dlrbTree_free(&pso->keys); - /* free data itself */ - MEM_freeN(pso); + if (pso->ob_data_array != NULL) { + MEM_freeN(pso->ob_data_array); } - /* cleanup */ + /* Free data itself. */ + MEM_freeN(pso); + + /* Cleanup. */ op->customdata = NULL; } /* ------------------------------------ */ -/* helper for apply() / reset() - refresh the data */ +/** + * Helper for apply() / reset() - refresh the data. + */ static void pose_slide_refresh(bContext *C, tPoseSlideOp *pso) { - /* wrapper around the generic version, allowing us to add some custom stuff later still */ + /* Wrapper around the generic version, allowing us to add some custom stuff later still. */ for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) { tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index]; if (ob_data->valid) { @@ -609,7 +634,9 @@ static bool pose_frame_range_from_object_get(tPoseSlideOp *pso, return false; } -/* helper for apply() - perform sliding for some value */ +/** + * Helper for apply() - perform sliding for some value. + */ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, float *val) { float prevFrameF, nextFrameF; @@ -619,17 +646,17 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, flo pose_frame_range_from_object_get(pso, ob, &prevFrameF, &nextFrameF); - /* get keyframe values for endpoint poses to blend with */ - /* previous/start */ + /* Get keyframe values for endpoint poses to blend with. */ + /* Previous/start. */ sVal = evaluate_fcurve(fcu, prevFrameF); - /* next/end */ + /* Next/end. */ eVal = evaluate_fcurve(fcu, nextFrameF); - /* calculate the relative weights of the endpoints */ + /* Calculate the relative weights of the endpoints. */ if (pso->mode == POSESLIDE_BREAKDOWN) { - /* get weights from the percentage control */ - w1 = pso->percentage; /* this must come second */ - w2 = 1.0f - w1; /* this must come first */ + /* Get weights from the factor control. */ + w1 = pso->factor; /* This must come second. */ + w2 = 1.0f - w1; /* This must come first. */ } else { /* - these weights are derived from the relative distance of these @@ -652,30 +679,37 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, flo * the value the current frame is closer to. */ switch (pso->mode) { - case POSESLIDE_PUSH: /* make the current pose more pronounced */ + case POSESLIDE_PUSH: /* Make the current pose more pronounced. */ { /* Slide the pose away from the breakdown pose in the timeline */ - (*val) -= ((sVal * w2) + (eVal * w1) - (*val)) * pso->percentage; + (*val) -= ((sVal * w2) + (eVal * w1) - (*val)) * pso->factor; break; } - case POSESLIDE_RELAX: /* make the current pose more like its surrounding ones */ + case POSESLIDE_RELAX: /* Make the current pose more like its surrounding ones. */ { /* Slide the pose towards the breakdown pose in the timeline */ - (*val) += ((sVal * w2) + (eVal * w1) - (*val)) * pso->percentage; + (*val) += ((sVal * w2) + (eVal * w1) - (*val)) * pso->factor; break; } - case POSESLIDE_BREAKDOWN: /* make the current pose slide around between the endpoints */ + case POSESLIDE_BREAKDOWN: /* Make the current pose slide around between the endpoints. */ { /* Perform simple linear interpolation - - * coefficient for start must come from pso->percentage. */ + * coefficient for start must come from pso->factor. */ /* TODO: make this use some kind of spline interpolation instead? */ (*val) = ((sVal * w2) + (eVal * w1)); break; } + /* Those are handled in pose_slide_rest_pose_apply. */ + case POSESLIDE_PUSH_REST: + case POSESLIDE_RELAX_REST: { + break; + } } } -/* helper for apply() - perform sliding for some 3-element vector */ +/** + * Helper for apply() - perform sliding for some 3-element vector. + */ static void pose_slide_apply_vec3(tPoseSlideOp *pso, tPChanFCurveLink *pfl, float vec[3], @@ -684,30 +718,32 @@ static void pose_slide_apply_vec3(tPoseSlideOp *pso, LinkData *ld = NULL; char *path = NULL; - /* get the path to use... */ + /* Get the path to use. */ path = BLI_sprintfN("%s.%s", pfl->pchan_path, propName); - /* using this path, find each matching F-Curve for the variables we're interested in */ + /* Using this path, find each matching F-Curve for the variables we're interested in. */ while ((ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path))) { FCurve *fcu = (FCurve *)ld->data; const int idx = fcu->array_index; const int lock = pso->axislock; - /* check if this F-Curve is ok given the current axis locks */ + /* Check if this F-Curve is ok given the current axis locks. */ BLI_assert(fcu->array_index < 3); if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) || ((lock & PS_LOCK_Z) && (idx == 2))) { - /* just work on these channels one by one... there's no interaction between values */ + /* Just work on these channels one by one... there's no interaction between values. */ pose_slide_apply_val(pso, fcu, pfl->ob, &vec[fcu->array_index]); } } - /* free the temp path we got */ + /* Free the temp path we got. */ MEM_freeN(path); } -/* helper for apply() - perform sliding for custom properties or bbone properties */ +/** + * Helper for apply() - perform sliding for custom properties or bbone properties. + */ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl, const char prop_prefix[]) @@ -716,7 +752,7 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, LinkData *ld; int len = strlen(pfl->pchan_path); - /* setup pointer RNA for resolving paths */ + /* Setup pointer RNA for resolving paths. */ RNA_pointer_create(NULL, &RNA_PoseBone, pfl->pchan, &ptr); /* - custom properties are just denoted using ["..."][etc.] after the end of the base path, @@ -732,22 +768,21 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, continue; } - /* do we have a match? - * - bPtr is the RNA Path with the standard part chopped off - * - pPtr is the chunk of the path which is left over + /* Do we have a match? + * - bPtr is the RNA Path with the standard part chopped off. + * - pPtr is the chunk of the path which is left over. */ bPtr = strstr(fcu->rna_path, pfl->pchan_path) + len; pPtr = strstr(bPtr, prop_prefix); if (pPtr) { - /* use RNA to try and get a handle on this property, then, assuming that it is just - * numerical, try and grab the value as a float for temp editing before setting back - */ + /* Use RNA to try and get a handle on this property, then, assuming that it is just + * numerical, try and grab the value as a float for temp editing before setting back. */ PropertyRNA *prop = RNA_struct_find_property(&ptr, pPtr); if (prop) { switch (RNA_property_type(prop)) { - /* continuous values that can be smoothly interpolated... */ + /* Continuous values that can be smoothly interpolated. */ case PROP_FLOAT: { float tval = RNA_property_float_get(&ptr, prop); pose_slide_apply_val(pso, fcu, pfl->ob, &tval); @@ -761,7 +796,7 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, break; } - /* values which can only take discrete values */ + /* Values which can only take discrete values. */ case PROP_BOOLEAN: { float tval = (float)RNA_property_boolean_get(&ptr, prop); pose_slide_apply_val(pso, fcu, pfl->ob, &tval); @@ -770,14 +805,13 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, break; } case PROP_ENUM: { - /* don't handle this case - these don't usually represent interchangeable - * set of values which should be interpolated between - */ + /* Don't handle this case - these don't usually represent interchangeable + * set of values which should be interpolated between. */ break; } default: - /* cannot handle */ + /* Cannot handle. */ // printf("Cannot Pose Slide non-numerical property\n"); break; } @@ -786,7 +820,9 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, } } -/* helper for apply() - perform sliding for quaternion rotations (using quat blending) */ +/** + * Helper for apply() - perform sliding for quaternion rotations (using quat blending). + */ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) { FCurve *fcu_w = NULL, *fcu_x = NULL, *fcu_y = NULL, *fcu_z = NULL; @@ -797,21 +833,21 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) float prevFrameF, nextFrameF; if (!pose_frame_range_from_object_get(pso, pfl->ob, &prevFrameF, &nextFrameF)) { - BLI_assert(!"Invalid pfl data"); + BLI_assert_msg(0, "Invalid pfl data"); return; } - /* get the path to use - this should be quaternion rotations only (needs care) */ + /* Get the path to use - this should be quaternion rotations only (needs care). */ path = BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation_quaternion"); - /* get the current frame number */ + /* Get the current frame number. */ cframe = (float)pso->cframe; - /* using this path, find each matching F-Curve for the variables we're interested in */ + /* Using this path, find each matching F-Curve for the variables we're interested in. */ while ((ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path))) { FCurve *fcu = (FCurve *)ld->data; - /* assign this F-Curve to one of the relevant pointers... */ + /* Assign this F-Curve to one of the relevant pointers. */ switch (fcu->array_index) { case 3: /* z */ fcu_z = fcu; @@ -828,14 +864,14 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) } } - /* only if all channels exist, proceed */ + /* Only if all channels exist, proceed. */ if (fcu_w && fcu_x && fcu_y && fcu_z) { float quat_final[4]; - /* perform blending */ + /* Perform blending. */ if (pso->mode == POSESLIDE_BREAKDOWN) { /* Just perform the interpolation between quat_prev and - * quat_next using pso->percentage as a guide. */ + * quat_next using pso->factor as a guide. */ float quat_prev[4]; float quat_next[4]; @@ -852,7 +888,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) normalize_qt(quat_prev); normalize_qt(quat_next); - interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->percentage); + interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->factor); } else { /* POSESLIDE_PUSH and POSESLIDE_RELAX. */ @@ -870,11 +906,11 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) normalize_qt(quat_curr); if (pso->mode == POSESLIDE_PUSH) { - interp_qt_qtqt(quat_final, quat_breakdown, quat_curr, 1.0f + pso->percentage); + interp_qt_qtqt(quat_final, quat_breakdown, quat_curr, 1.0f + pso->factor); } else { BLI_assert(pso->mode == POSESLIDE_RELAX); - interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, pso->percentage); + interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, pso->factor); } } @@ -882,7 +918,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) quat_to_compatible_quat(pchan->quat, quat_final, pchan->quat); } - /* free the path now */ + /* Free the path now. */ MEM_freeN(path); } @@ -895,11 +931,11 @@ static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], flo ((lock & PS_LOCK_Z) && (idx == 2))) { float diff_val = default_value - vec[idx]; if (pso->mode == POSESLIDE_RELAX_REST) { - vec[idx] += pso->percentage * diff_val; + vec[idx] += pso->factor * diff_val; } else { /* Push */ - vec[idx] -= pso->percentage * diff_val; + vec[idx] -= pso->factor * diff_val; } } } @@ -917,80 +953,84 @@ static void pose_slide_rest_pose_apply_other_rot(tPoseSlideOp *pso, float vec[4] for (int idx = 0; idx < 4; idx++) { float diff_val = default_values[idx] - vec[idx]; if (pso->mode == POSESLIDE_RELAX_REST) { - vec[idx] += pso->percentage * diff_val; + vec[idx] += pso->factor * diff_val; } else { /* Push */ - vec[idx] -= pso->percentage * diff_val; + vec[idx] -= pso->factor * diff_val; } } } -/* apply() - perform the pose sliding between the current pose and the rest pose */ +/** + * apply() - perform the pose sliding between the current pose and the rest pose. + */ static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso) { tPChanFCurveLink *pfl; - /* for each link, handle each set of transforms */ + /* For each link, handle each set of transforms. */ for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) { - /* valid transforms for each PoseChannel should have been noted already - * - sliding the pose should be a straightforward exercise for location+rotation, + /* Valid transforms for each #bPoseChannel should have been noted already. + * - Sliding the pose should be a straightforward exercise for location+rotation, * but rotations get more complicated since we may want to use quaternion blending - * for quaternions instead... + * for quaternions instead. */ bPoseChannel *pchan = pfl->pchan; if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) { - /* calculate these for the 'location' vector, and use location curves */ + /* Calculate these for the 'location' vector, and use location curves. */ pose_slide_rest_pose_apply_vec3(pso, pchan->loc, 0.0f); } if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) { - /* calculate these for the 'scale' vector, and use scale curves */ + /* Calculate these for the 'scale' vector, and use scale curves. */ pose_slide_rest_pose_apply_vec3(pso, pchan->size, 1.0f); } if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) { - /* everything depends on the rotation mode */ + /* Everything depends on the rotation mode. */ if (pchan->rotmode > 0) { - /* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */ + /* Eulers - so calculate these for the 'eul' vector, and use euler_rotation curves. */ pose_slide_rest_pose_apply_vec3(pso, pchan->eul, 0.0f); } else if (pchan->rotmode == ROT_MODE_AXISANGLE) { pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, false); } else { - /* quaternions - use quaternion blending */ + /* Quaternions - use quaternion blending. */ pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, true); } } if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) { - /* bbone properties - they all start a "bbone_" prefix */ - /* TODO Not implemented */ + /* Bbone properties - they all start a "bbone_" prefix. */ + /* TODO: Not implemented. */ // pose_slide_apply_props(pso, pfl, "bbone_"); } 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). */ - /* TODO Not implemented */ + /* TODO: Not implemented. */ // pose_slide_apply_props(pso, pfl, "[\""); } } - /* depsgraph updates + redraws */ + /* Depsgraph updates + redraws. */ pose_slide_refresh(C, pso); } -/* apply() - perform the pose sliding based on weighting various poses */ +/** + * apply() - perform the pose sliding based on weighting various poses. + */ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) { tPChanFCurveLink *pfl; /* Sanitize the frame ranges. */ if (pso->prevFrame == pso->nextFrame) { - /* move out one step either side */ + /* Move out one step either side. */ pso->prevFrame--; pso->nextFrame++; @@ -1001,7 +1041,7 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) continue; } - /* apply NLA mapping corrections so the frame lookups work */ + /* Apply NLA mapping corrections so the frame look-ups work. */ ob_data->prevFrameF = BKE_nla_tweakedit_remap( ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP); ob_data->nextFrameF = BKE_nla_tweakedit_remap( @@ -1009,9 +1049,9 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) } } - /* for each link, handle each set of transforms */ + /* For each link, handle each set of transforms. */ for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) { - /* valid transforms for each PoseChannel should have been noted already + /* Valid transforms for each #bPoseChannel should have been noted already * - sliding the pose should be a straightforward exercise for location+rotation, * but rotations get more complicated since we may want to use quaternion blending * for quaternions instead... @@ -1019,32 +1059,32 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) bPoseChannel *pchan = pfl->pchan; if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) { - /* calculate these for the 'location' vector, and use location curves */ + /* Calculate these for the 'location' vector, and use location curves. */ pose_slide_apply_vec3(pso, pfl, pchan->loc, "location"); } if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) { - /* calculate these for the 'scale' vector, and use scale curves */ + /* Calculate these for the 'scale' vector, and use scale curves. */ pose_slide_apply_vec3(pso, pfl, pchan->size, "scale"); } if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) { - /* everything depends on the rotation mode */ + /* Everything depends on the rotation mode. */ if (pchan->rotmode > 0) { - /* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */ + /* Eulers - so calculate these for the 'eul' vector, and use euler_rotation curves. */ pose_slide_apply_vec3(pso, pfl, pchan->eul, "rotation_euler"); } else if (pchan->rotmode == ROT_MODE_AXISANGLE) { /* TODO: need to figure out how to do this! */ } else { - /* quaternions - use quaternion blending */ + /* Quaternions - use quaternion blending. */ pose_slide_apply_quat(pso, pfl); } } if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) { - /* bbone properties - they all start a "bbone_" prefix */ + /* Bbone properties - they all start a "bbone_" prefix. */ pose_slide_apply_props(pso, pfl, "bbone_"); } @@ -1055,28 +1095,35 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) } } - /* depsgraph updates + redraws */ + /* Depsgraph updates + redraws. */ pose_slide_refresh(C, pso); } -/* perform auto-key-framing after changes were made + confirmed */ +/** + * Perform auto-key-framing after changes were made + confirmed. + */ static void pose_slide_autoKeyframe(bContext *C, tPoseSlideOp *pso) { - /* wrapper around the generic call */ + /* Wrapper around the generic call. */ poseAnim_mapping_autoKeyframe(C, pso->scene, &pso->pfLinks, (float)pso->cframe); } -/* reset changes made to current pose */ +/** + * Reset changes made to current pose. + */ static void pose_slide_reset(tPoseSlideOp *pso) { - /* wrapper around the generic call, so that custom stuff can be added later */ + /* Wrapper around the generic call, so that custom stuff can be added later. */ poseAnim_mapping_reset(&pso->pfLinks); } /* ------------------------------------ */ -/* Draw percentage indicator in workspace footer. */ -/* TODO: Include hints about locks here... */ +/** + * Draw percentage indicator in status-bar. + * + * TODO: Include hints about locks here. + */ static void pose_slide_draw_status(bContext *C, tPoseSlideOp *pso) { char status_str[UI_MAX_DRAW_STR]; @@ -1100,25 +1147,25 @@ static void pose_slide_draw_status(bContext *C, tPoseSlideOp *pso) break; default: - /* unknown */ + /* Unknown. */ strcpy(mode_str, TIP_("Sliding-Tool")); break; } switch (pso->axislock) { case PS_LOCK_X: - BLI_strncpy(axis_str, TIP_("[X]/Y/Z axis only (X to clear)"), sizeof(axis_str)); + STRNCPY(axis_str, TIP_("[X]/Y/Z axis only (X to clear)")); break; case PS_LOCK_Y: - BLI_strncpy(axis_str, TIP_("X/[Y]/Z axis only (Y to clear)"), sizeof(axis_str)); + STRNCPY(axis_str, TIP_("X/[Y]/Z axis only (Y to clear)")); break; case PS_LOCK_Z: - BLI_strncpy(axis_str, TIP_("X/Y/[Z] axis only (Z to clear)"), sizeof(axis_str)); + STRNCPY(axis_str, TIP_("X/Y/[Z] axis only (Z to clear)")); break; default: if (ELEM(pso->channels, PS_TFM_LOC, PS_TFM_ROT, PS_TFM_SIZE)) { - BLI_strncpy(axis_str, TIP_("X/Y/Z = Axis Constraint"), sizeof(axis_str)); + STRNCPY(axis_str, TIP_("X/Y/Z = Axis Constraint")); } else { axis_str[0] = '\0'; @@ -1146,43 +1193,38 @@ static void pose_slide_draw_status(bContext *C, tPoseSlideOp *pso) axis_str); break; case PS_TFM_BBONE_SHAPE: - BLI_strncpy(limits_str, - TIP_("G/R/S/[B]/C - Bendy Bone properties only (B to clear) | %s"), - sizeof(limits_str)); + STRNCPY(limits_str, TIP_("G/R/S/[B]/C - Bendy Bone properties only (B to clear) | %s")); break; case PS_TFM_PROPS: - BLI_strncpy(limits_str, - TIP_("G/R/S/B/[C] - Custom Properties only (C to clear) | %s"), - sizeof(limits_str)); + STRNCPY(limits_str, TIP_("G/R/S/B/[C] - Custom Properties only (C to clear) | %s")); break; default: - BLI_strncpy( - limits_str, TIP_("G/R/S/B/C - Limit to Transform/Property Set"), sizeof(limits_str)); + STRNCPY(limits_str, TIP_("G/R/S/B/C - Limit to Transform/Property Set")); break; } if (pso->overshoot) { - BLI_strncpy(overshoot_str, TIP_("[E] - Disable overshoot"), sizeof(overshoot_str)); + STRNCPY(overshoot_str, TIP_("[E] - Disable overshoot")); } else { - BLI_strncpy(overshoot_str, TIP_("E - Enable overshoot"), sizeof(overshoot_str)); + STRNCPY(overshoot_str, TIP_("[E] - Enable overshoot")); } if (pso->precision) { - BLI_strncpy(precision_str, TIP_("[Shift] - Precision active"), sizeof(precision_str)); + STRNCPY(precision_str, TIP_("[Shift] - Precision active")); } else { - BLI_strncpy(precision_str, TIP_("Shift - Hold for precision"), sizeof(precision_str)); + STRNCPY(precision_str, TIP_("Shift - Hold for precision")); } if (pso->increments) { - BLI_strncpy(increments_str, TIP_("[Ctrl] - Increments active"), sizeof(increments_str)); + STRNCPY(increments_str, TIP_("[Ctrl] - Increments active")); } else { - BLI_strncpy(increments_str, TIP_("Ctrl - Hold for 10% increments"), sizeof(increments_str)); + STRNCPY(increments_str, TIP_("Ctrl - Hold for 10% increments")); } - BLI_strncpy(bone_vis_str, TIP_("[H] - Toggle bone visibility"), sizeof(increments_str)); + STRNCPY(bone_vis_str, TIP_("[H] - Toggle bone visibility")); if (hasNumInput(&pso->num)) { Scene *scene = pso->scene; @@ -1208,57 +1250,59 @@ static void pose_slide_draw_status(bContext *C, tPoseSlideOp *pso) ED_area_status_text(pso->area, ""); } -/* common code for invoke() methods */ +/** + * Common code for invoke() methods. + */ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *pso) { tPChanFCurveLink *pfl; wmWindow *win = CTX_wm_window(C); - /* for each link, add all its keyframes to the search tree */ + /* For each link, add all its keyframes to the search tree. */ for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) { LinkData *ld; - /* do this for each F-Curve */ + /* Do this for each F-Curve. */ for (ld = pfl->fcurves.first; ld; ld = ld->next) { FCurve *fcu = (FCurve *)ld->data; fcurve_to_keylist(pfl->ob->adt, fcu, &pso->keys, 0); } } - /* cancel if no keyframes found... */ + /* Cancel if no keyframes found. */ if (pso->keys.root) { ActKeyColumn *ak; float cframe = (float)pso->cframe; - /* firstly, check if the current frame is a keyframe... */ + /* Firstly, check if the current frame is a keyframe. */ ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(&pso->keys, compare_ak_cfraPtr, &cframe); if (ak == NULL) { - /* current frame is not a keyframe, so search */ + /* Current frame is not a keyframe, so search. */ ActKeyColumn *pk = (ActKeyColumn *)BLI_dlrbTree_search_prev( &pso->keys, compare_ak_cfraPtr, &cframe); ActKeyColumn *nk = (ActKeyColumn *)BLI_dlrbTree_search_next( &pso->keys, compare_ak_cfraPtr, &cframe); - /* new set the frames */ - /* prev frame */ + /* New set the frames. */ + /* Prev frame. */ pso->prevFrame = (pk) ? (pk->cfra) : (pso->cframe - 1); RNA_int_set(op->ptr, "prev_frame", pso->prevFrame); - /* next frame */ + /* Next frame. */ pso->nextFrame = (nk) ? (nk->cfra) : (pso->cframe + 1); RNA_int_set(op->ptr, "next_frame", pso->nextFrame); } else { - /* current frame itself is a keyframe, so just take keyframes on either side */ - /* prev frame */ + /* Current frame itself is a keyframe, so just take keyframes on either side. */ + /* Prev frame. */ pso->prevFrame = (ak->prev) ? (ak->prev->cfra) : (pso->cframe - 1); RNA_int_set(op->ptr, "prev_frame", pso->prevFrame); - /* next frame */ + /* Next frame. */ pso->nextFrame = (ak->next) ? (ak->next->cfra) : (pso->cframe + 1); RNA_int_set(op->ptr, "next_frame", pso->nextFrame); } - /* apply NLA mapping corrections so the frame lookups work */ + /* Apply NLA mapping corrections so the frame look-ups work. */ for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) { tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index]; if (ob_data->valid) { @@ -1275,8 +1319,8 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p return OPERATOR_CANCELLED; } - /* initial apply for operator... */ - /* TODO: need to calculate percentage for initial round too... */ + /* Initial apply for operator. */ + /* TODO: need to calculate factor for initial round too. */ if (!ELEM(pso->mode, POSESLIDE_PUSH_REST, POSESLIDE_RELAX_REST)) { pose_slide_apply(C, pso); } @@ -1284,16 +1328,16 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p pose_slide_rest_pose_apply(C, pso); } - /* depsgraph updates + redraws */ + /* Depsgraph updates + redraws. */ pose_slide_refresh(C, pso); - /* set cursor to indicate modal */ + /* Set cursor to indicate modal. */ WM_cursor_modal_set(win, WM_CURSOR_EW_SCROLL); - /* header print */ + /* Header print. */ pose_slide_draw_status(C, pso); - /* add a modal handler for this operator */ + /* Add a modal handler for this operator. */ WM_event_add_modal_handler(C, op); /* Hide Bone Overlay. */ @@ -1304,31 +1348,32 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p return OPERATOR_RUNNING_MODAL; } -/* Calculate percentage based on mouse movement, clamp or round to increments if - * enabled by the user. Store the new percentage value. +/** + * Calculate factor based on mouse movement, clamp or round to increments if + * enabled by the user. Store the new factor value. */ -static void pose_slide_mouse_update_percentage(tPoseSlideOp *pso, - wmOperator *op, - const wmEvent *event) +static void pose_slide_mouse_update_factor(tPoseSlideOp *pso, wmOperator *op, const wmEvent *event) { - const float percentage_delta = (event->x - pso->last_cursor_x) / ((float)(SLIDE_PIXEL_DISTANCE)); - /* Reduced percentage delta in precision mode (shift held). */ - pso->raw_percentage += pso->precision ? (percentage_delta / 8) : percentage_delta; - pso->percentage = pso->raw_percentage; + const float factor_delta = (event->x - pso->last_cursor_x) / ((float)(SLIDE_PIXEL_DISTANCE)); + /* Reduced factor delta in precision mode (shift held). */ + pso->raw_factor += pso->precision ? (factor_delta / 8) : factor_delta; + pso->factor = pso->raw_factor; pso->last_cursor_x = event->x; if (!pso->overshoot) { - pso->percentage = clamp_f(pso->percentage, 0, 1); + pso->factor = clamp_f(pso->factor, 0, 1); } if (pso->increments) { - pso->percentage = round(pso->percentage * 10) / 10; + pso->factor = round(pso->factor * 10) / 10; } - RNA_float_set(op->ptr, "percentage", pso->percentage); + RNA_float_set(op->ptr, "factor", pso->factor); } -/* handle an event to toggle channels mode */ +/** + * Handle an event to toggle channels mode. + */ static void pose_slide_toggle_channels_mode(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_Channels channel) @@ -1349,7 +1394,9 @@ static void pose_slide_toggle_channels_mode(wmOperator *op, RNA_enum_set(op->ptr, "axis_lock", pso->axislock); } -/* handle an event to toggle axis locks - returns whether any change in state is needed */ +/** + * Handle an event to toggle axis locks - returns whether any change in state is needed. + */ static bool pose_slide_toggle_axis_locks(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_AxisLock axis) @@ -1376,7 +1423,9 @@ static bool pose_slide_toggle_axis_locks(wmOperator *op, return true; } -/* common code for modal() */ +/** + * Operator `modal()` callback. + */ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso = op->customdata; @@ -1386,11 +1435,11 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) const bool has_numinput = hasNumInput(&pso->num); switch (event->type) { - case LEFTMOUSE: /* confirm */ + case LEFTMOUSE: /* Confirm. */ case EVT_RETKEY: case EVT_PADENTER: { if (event->val == KM_PRESS) { - /* return to normal cursor and header status */ + /* Return to normal cursor and header status. */ ED_workspace_status_text(C, NULL); ED_area_status_text(pso->area, NULL); WM_cursor_modal_restore(win); @@ -1398,48 +1447,48 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) /* Depsgraph updates + redraws. Redraw needed to remove UI. */ pose_slide_refresh(C, pso); - /* insert keyframes as required... */ + /* Insert keyframes as required. */ pose_slide_autoKeyframe(C, pso); pose_slide_exit(op); - /* done! */ + /* Done! */ return OPERATOR_FINISHED; } break; } - case EVT_ESCKEY: /* cancel */ + case EVT_ESCKEY: /* Cancel. */ case RIGHTMOUSE: { if (event->val == KM_PRESS) { - /* return to normal cursor and header status */ + /* Return to normal cursor and header status. */ ED_workspace_status_text(C, NULL); ED_area_status_text(pso->area, NULL); WM_cursor_modal_restore(win); - /* reset transforms back to original state */ + /* Reset transforms back to original state. */ pose_slide_reset(pso); - /* Depsgraph updates + redraws.*/ + /* Depsgraph updates + redraws. */ pose_slide_refresh(C, pso); - /* clean up temp data */ + /* Clean up temp data. */ pose_slide_exit(op); - /* canceled! */ + /* Canceled! */ return OPERATOR_CANCELLED; } break; } - /* Percentage Change... */ - case MOUSEMOVE: /* calculate new position */ + /* Factor Change... */ + case MOUSEMOVE: /* Calculate new position. */ { - /* only handle mousemove if not doing numinput */ + /* Only handle mouse-move if not doing numinput. */ if (has_numinput == false) { - /* update percentage based on position of mouse */ - pose_slide_mouse_update_percentage(pso, op, event); + /* Update factor based on position of mouse. */ + pose_slide_mouse_update_factor(pso, op, event); - /* update pose to reflect the new values (see below) */ + /* Update pose to reflect the new values (see below). */ do_pose_update = true; } break; @@ -1451,12 +1500,12 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) /* Grab percentage from numeric input, and store this new value for redo * NOTE: users see ints, while internally we use a 0-1 float */ - value = pso->percentage * 100.0f; + value = pso->factor * 100.0f; applyNumInput(&pso->num, &value); - pso->percentage = value / 100.0f; - CLAMP(pso->percentage, 0.0f, 1.0f); - RNA_float_set(op->ptr, "percentage", pso->percentage); + pso->factor = value / 100.0f; + CLAMP(pso->factor, 0.0f, 1.0f); + RNA_float_set(op->ptr, "factor", pso->factor); /* Update pose to reflect the new values (see below) */ do_pose_update = true; @@ -1464,7 +1513,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) } if (event->val == KM_PRESS) { switch (event->type) { - /* Transform Channel Limits */ + /* Transform Channel Limits. */ /* XXX: Replace these hard-coded hotkeys with a modal-map that can be customized. */ case EVT_GKEY: /* Location */ { @@ -1571,8 +1620,8 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else { - /* unhandled event - maybe it was some view manipulation? */ - /* allow to pass through */ + /* Unhandled event - maybe it was some view manipulation? */ + /* Allow to pass through. */ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; } } @@ -1581,15 +1630,13 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) /* Perform pose updates - in response to some user action * (e.g. pressing a key or moving the mouse). */ if (do_pose_update) { - pose_slide_mouse_update_percentage(pso, op, event); - - /* update percentage indicator in header */ + /* Update percentage indicator in header. */ pose_slide_draw_status(C, pso); - /* reset transforms (to avoid accumulation errors) */ + /* Reset transforms (to avoid accumulation errors). */ pose_slide_reset(pso); - /* apply... */ + /* Apply. */ if (!ELEM(pso->mode, POSESLIDE_PUSH_REST, POSESLIDE_RELAX_REST)) { pose_slide_apply(C, pso); } @@ -1598,21 +1645,25 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) } } - /* still running... */ + /* Still running. */ return OPERATOR_RUNNING_MODAL; } -/* common code for cancel() */ +/** + * Common code for cancel() + */ static void pose_slide_cancel(bContext *UNUSED(C), wmOperator *op) { - /* cleanup and done */ + /* Cleanup and done. */ pose_slide_exit(op); } -/* common code for exec() methods */ +/** + * Common code for exec() methods. + */ static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso) { - /* settings should have been set up ok for applying, so just apply! */ + /* Settings should have been set up ok for applying, so just apply! */ if (!ELEM(pso->mode, POSESLIDE_PUSH_REST, POSESLIDE_RELAX_REST)) { pose_slide_apply(C, pso); } @@ -1620,10 +1671,10 @@ static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso pose_slide_rest_pose_apply(C, pso); } - /* insert keyframes if needed */ + /* Insert keyframes if needed. */ pose_slide_autoKeyframe(C, pso); - /* cleanup and done */ + /* Cleanup and done. */ pose_slide_exit(op); return OPERATOR_FINISHED; @@ -1637,11 +1688,11 @@ static void pose_slide_opdef_properties(wmOperatorType *ot) PropertyRNA *prop; prop = RNA_def_float_factor(ot->srna, - "percentage", + "factor", 0.5f, 0.0f, 1.0f, - "Percentage", + "Factor", "Weighting factor for which keyframe is favored more", 0.0, 1.0); @@ -1687,12 +1738,14 @@ static void pose_slide_opdef_properties(wmOperatorType *ot) /* ------------------------------------ */ -/* invoke() - for 'push from breakdown' mode */ +/** + * Operator `invoke()` callback for 'push from breakdown' mode. + */ static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso; - /* initialize data */ + /* Initialize data. */ if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) { pose_slide_exit(op); return OPERATOR_CANCELLED; @@ -1702,19 +1755,21 @@ static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *ev pso->last_cursor_x = event->x; - /* Initialize percentage so that it won't pop on first mouse move. */ - pose_slide_mouse_update_percentage(pso, op, event); + /* Initialize factor so that it won't pop on first mouse move. */ + pose_slide_mouse_update_factor(pso, op, event); - /* do common setup work */ + /* Do common setup work. */ return pose_slide_invoke_common(C, op, pso); } -/* exec() - for push */ +/** + * Operator `exec()` callback - for push. + */ static int pose_slide_push_exec(bContext *C, wmOperator *op) { tPoseSlideOp *pso; - /* initialize data (from RNA-props) */ + /* Initialize data (from RNA-props). */ if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) { pose_slide_exit(op); return OPERATOR_CANCELLED; @@ -1722,7 +1777,7 @@ static int pose_slide_push_exec(bContext *C, wmOperator *op) pso = op->customdata; - /* do common exec work */ + /* Do common exec work. */ return pose_slide_exec_common(C, op, pso); } @@ -1749,12 +1804,14 @@ void POSE_OT_push(wmOperatorType *ot) /* ........................ */ -/* invoke() - for 'relax to breakdown' mode */ +/** + * Invoke callback - for 'relax to breakdown' mode. + */ static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso; - /* initialize data */ + /* Initialize data. */ if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) { pose_slide_exit(op); return OPERATOR_CANCELLED; @@ -1764,19 +1821,21 @@ static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *e pso->last_cursor_x = event->x; - /* Initialize percentage so that it won't pop on first mouse move. */ - pose_slide_mouse_update_percentage(pso, op, event); + /* Initialize factor so that it won't pop on first mouse move. */ + pose_slide_mouse_update_factor(pso, op, event); - /* do common setup work */ + /* Do common setup work. */ return pose_slide_invoke_common(C, op, pso); } -/* exec() - for relax */ +/** + * Operator exec() - for relax. + */ static int pose_slide_relax_exec(bContext *C, wmOperator *op) { tPoseSlideOp *pso; - /* initialize data (from RNA-props) */ + /* Initialize data (from RNA-props). */ if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) { pose_slide_exit(op); return OPERATOR_CANCELLED; @@ -1784,7 +1843,7 @@ static int pose_slide_relax_exec(bContext *C, wmOperator *op) pso = op->customdata; - /* do common exec work */ + /* Do common exec work. */ return pose_slide_exec_common(C, op, pso); } @@ -1810,12 +1869,14 @@ void POSE_OT_relax(wmOperatorType *ot) } /* ........................ */ -/* invoke() - for 'push from rest pose' mode */ +/** + * Operator `invoke()` - for 'push from rest pose' mode. + */ static int pose_slide_push_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso; - /* initialize data */ + /* Initialize data. */ if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) { pose_slide_exit(op); return OPERATOR_CANCELLED; @@ -1825,19 +1886,21 @@ static int pose_slide_push_rest_invoke(bContext *C, wmOperator *op, const wmEven pso->last_cursor_x = event->x; - /* Initialize percentage so that it won't pop on first mouse move. */ - pose_slide_mouse_update_percentage(pso, op, event); + /* Initialize factor so that it won't pop on first mouse move. */ + pose_slide_mouse_update_factor(pso, op, event); /* do common setup work */ return pose_slide_invoke_common(C, op, pso); } -/* exec() - for push */ +/** + * Operator `exec()` - for push. + */ static int pose_slide_push_rest_exec(bContext *C, wmOperator *op) { tPoseSlideOp *pso; - /* initialize data (from RNA-props) */ + /* Initialize data (from RNA-props). */ if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) { pose_slide_exit(op); return OPERATOR_CANCELLED; @@ -1845,7 +1908,7 @@ static int pose_slide_push_rest_exec(bContext *C, wmOperator *op) pso = op->customdata; - /* do common exec work */ + /* Do common exec work. */ return pose_slide_exec_common(C, op, pso); } @@ -1872,12 +1935,14 @@ void POSE_OT_push_rest(wmOperatorType *ot) /* ........................ */ -/* invoke() - for 'relax' mode */ +/** + * Operator `invoke()` - for 'relax' mode. + */ static int pose_slide_relax_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso; - /* initialize data */ + /* Initialize data. */ if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) { pose_slide_exit(op); return OPERATOR_CANCELLED; @@ -1887,19 +1952,21 @@ static int pose_slide_relax_rest_invoke(bContext *C, wmOperator *op, const wmEve pso->last_cursor_x = event->x; - /* Initialize percentage so that it won't pop on first mouse move. */ - pose_slide_mouse_update_percentage(pso, op, event); + /* Initialize factor so that it won't pop on first mouse move. */ + pose_slide_mouse_update_factor(pso, op, event); - /* do common setup work */ + /* Do common setup work. */ return pose_slide_invoke_common(C, op, pso); } -/* exec() - for relax */ +/** + * Operator `exec()` - for relax. + */ static int pose_slide_relax_rest_exec(bContext *C, wmOperator *op) { tPoseSlideOp *pso; - /* initialize data (from RNA-props) */ + /* Initialize data (from RNA-props). */ if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) { pose_slide_exit(op); return OPERATOR_CANCELLED; @@ -1907,7 +1974,7 @@ static int pose_slide_relax_rest_exec(bContext *C, wmOperator *op) pso = op->customdata; - /* do common exec work */ + /* Do common exec work. */ return pose_slide_exec_common(C, op, pso); } @@ -1934,12 +2001,14 @@ void POSE_OT_relax_rest(wmOperatorType *ot) /* ........................ */ -/* invoke() - for 'breakdown' mode */ +/** + * Operator `invoke()` - for 'breakdown' mode. + */ static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso; - /* initialize data */ + /* Initialize data. */ if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) { pose_slide_exit(op); return OPERATOR_CANCELLED; @@ -1949,19 +2018,21 @@ static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEven pso->last_cursor_x = event->x; - /* Initialize percentage so that it won't pop on first mouse move. */ - pose_slide_mouse_update_percentage(pso, op, event); + /* Initialize factor so that it won't pop on first mouse move. */ + pose_slide_mouse_update_factor(pso, op, event); - /* do common setup work */ + /* Do common setup work. */ return pose_slide_invoke_common(C, op, pso); } -/* exec() - for breakdown */ +/** + * Operator exec() - for breakdown. + */ static int pose_slide_breakdown_exec(bContext *C, wmOperator *op) { tPoseSlideOp *pso; - /* initialize data (from RNA-props) */ + /* Initialize data (from RNA-props). */ if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) { pose_slide_exit(op); return OPERATOR_CANCELLED; @@ -1969,7 +2040,7 @@ static int pose_slide_breakdown_exec(bContext *C, wmOperator *op) pso = op->customdata; - /* do common exec work */ + /* Do common exec work. */ return pose_slide_exec_common(C, op, pso); } @@ -1999,36 +2070,39 @@ void POSE_OT_breakdown(wmOperatorType *ot) /* "termination conditions" - i.e. when we stop */ typedef enum ePosePropagate_Termination { - /* stop after the current hold ends */ + /** Stop after the current hold ends. */ POSE_PROPAGATE_SMART_HOLDS = 0, - /* only do on the last keyframe */ + /** Only do on the last keyframe. */ POSE_PROPAGATE_LAST_KEY, - /* stop after the next keyframe */ + /** Stop after the next keyframe. */ POSE_PROPAGATE_NEXT_KEY, - /* stop after the specified frame */ + /** Stop after the specified frame. */ POSE_PROPAGATE_BEFORE_FRAME, - /* stop when we run out of keyframes */ + /** Stop when we run out of keyframes. */ POSE_PROPAGATE_BEFORE_END, - /* only do on keyframes that are selected */ + /** Only do on keyframes that are selected. */ POSE_PROPAGATE_SELECTED_KEYS, - /* only do on the frames where markers are selected */ + /** Only do on the frames where markers are selected. */ POSE_PROPAGATE_SELECTED_MARKERS, } ePosePropagate_Termination; -/* Termination data needed for some modes - - * assumes only one of these entries will be needed at a time. */ +/** + * Termination data needed for some modes - + * assumes only one of these entries will be needed at a time. + */ typedef union tPosePropagate_ModeData { - /* smart holds + before frame: frame number to stop on */ + /** Smart holds + before frame: frame number to stop on. */ float end_frame; - /* selected markers: listbase for CfraElem's marking these frames */ + /** Selected markers: listbase for CfraElem's marking these frames. */ ListBase sel_markers; } tPosePropagate_ModeData; /* --------------------------------- */ -/* get frame on which the "hold" for the bone ends +/** + * Get frame on which the "hold" for the bone ends. * XXX: this may not really work that well if a bone moves on some channels and not others * if this happens to be a major issue, scrap this, and just make this happen * independently per F-Curve @@ -2042,7 +2116,7 @@ static float pose_propagate_get_boneHoldEndFrame(tPChanFCurveLink *pfl, float st LinkData *ld; float endFrame = startFrame; - /* set up optimized data-structures for searching for relevant keyframes + holds */ + /* Set up optimized data-structures for searching for relevant keyframes + holds. */ BLI_dlrbTree_init(&keys); for (ld = pfl->fcurves.first; ld; ld = ld->next) { @@ -2050,7 +2124,7 @@ static float pose_propagate_get_boneHoldEndFrame(tPChanFCurveLink *pfl, float st fcurve_to_keylist(adt, fcu, &keys, 0); } - /* find the long keyframe (i.e. hold), and hence obtain the endFrame value + /* Find the long keyframe (i.e. hold), and hence obtain the endFrame value * - the best case would be one that starts on the frame itself */ ActKeyColumn *ab = (ActKeyColumn *)BLI_dlrbTree_search_exact( @@ -2064,67 +2138,68 @@ static float pose_propagate_get_boneHoldEndFrame(tPChanFCurveLink *pfl, float st * otherwise forget it, as we'd be overwriting some valid data. */ if (ab == NULL) { - /* we've got case 1, so try the one after */ + /* We've got case 1, so try the one after. */ ab = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &startFrame); if ((actkeyblock_get_valid_hold(ab) & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) { - /* try the block before this frame then as last resort */ + /* Try the block before this frame then as last resort. */ ab = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &startFrame); } } - /* whatever happens, stop searching now... */ + /* Whatever happens, stop searching now.... */ if ((actkeyblock_get_valid_hold(ab) & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) { - /* restrict range to just the frame itself - * i.e. everything is in motion, so no holds to safely overwrite - */ + /* Restrict range to just the frame itself + * i.e. everything is in motion, so no holds to safely overwrite. */ ab = NULL; } - /* check if we can go any further than we've already gone */ + /* Check if we can go any further than we've already gone. */ if (ab) { - /* go to next if it is also valid and meets "extension" criteria */ + /* Go to next if it is also valid and meets "extension" criteria. */ while (ab->next) { ActKeyColumn *abn = ab->next; - /* must be valid */ + /* Must be valid. */ if ((actkeyblock_get_valid_hold(abn) & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) { break; } - /* should have the same number of curves */ + /* Should have the same number of curves. */ if (ab->totblock != abn->totblock) { break; } - /* we can extend the bounds to the end of this "next" block now */ + /* We can extend the bounds to the end of this "next" block now. */ ab = abn; } - /* end frame can now take the value of the end of the block */ + /* End frame can now take the value of the end of the block. */ endFrame = ab->next->cfra; } - /* free temp memory */ + /* Free temp memory. */ BLI_dlrbTree_free(&keys); - /* return the end frame we've found */ + /* Return the end frame we've found. */ return endFrame; } -/* get reference value from F-Curve using RNA */ +/** + * Get reference value from F-Curve using RNA. + */ static bool pose_propagate_get_refVal(Object *ob, FCurve *fcu, float *value) { PointerRNA id_ptr, ptr; PropertyRNA *prop; bool found = false; - /* base pointer is always the object -> id_ptr */ + /* Base pointer is always the `object -> id_ptr`. */ RNA_id_pointer_create(&ob->id, &id_ptr); - /* resolve the property... */ + /* Resolve the property. */ if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) { if (RNA_property_array_check(prop)) { - /* array */ + /* Array. */ if (fcu->array_index < RNA_property_array_length(&ptr, prop)) { found = true; switch (RNA_property_type(prop)) { @@ -2144,7 +2219,7 @@ static bool pose_propagate_get_refVal(Object *ob, FCurve *fcu, float *value) } } else { - /* not an array */ + /* Not an array. */ found = true; switch (RNA_property_type(prop)) { case PROP_BOOLEAN: @@ -2169,7 +2244,9 @@ static bool pose_propagate_get_refVal(Object *ob, FCurve *fcu, float *value) return found; } -/* propagate just works along each F-Curve in turn */ +/** + * Propagate just works along each F-Curve in turn. + */ static void pose_propagate_fcurve( wmOperator *op, Object *ob, FCurve *fcu, float startFrame, tPosePropagate_ModeData modeData) { @@ -2178,31 +2255,31 @@ static void pose_propagate_fcurve( BezTriple *bezt; float refVal = 0.0f; bool keyExists; - int i, match; + int i; bool first = true; - /* skip if no keyframes to edit */ + /* Skip if no keyframes to edit. */ if ((fcu->bezt == NULL) || (fcu->totvert < 2)) { return; } - /* find the reference value from bones directly, which means that the user + /* Find the reference value from bones directly, which means that the user * doesn't need to firstly keyframe the pose (though this doesn't mean that - * they can't either) - */ + * they can't either). */ if (!pose_propagate_get_refVal(ob, fcu, &refVal)) { return; } - /* find the first keyframe to start propagating from + /* Find the first keyframe to start propagating from: * - if there's a keyframe on the current frame, we probably want to save this value there too - * since it may be as of yet unkeyed + * since it may be as of yet un-keyed * - if starting before the starting frame, don't touch the key, as it may have had some valid * values * - if only doing selected keyframes, start from the first one */ if (mode != POSE_PROPAGATE_SELECTED_KEYS) { - match = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, startFrame, fcu->totvert, &keyExists); + const int match = BKE_fcurve_bezt_binarysearch_index( + fcu->bezt, startFrame, fcu->totvert, &keyExists); if (fcu->bezt[match].vec[1][0] < startFrame) { i = match + 1; @@ -2212,58 +2289,58 @@ static void pose_propagate_fcurve( } } else { - /* selected - start from first keyframe */ + /* Selected - start from first keyframe. */ i = 0; } for (bezt = &fcu->bezt[i]; i < fcu->totvert; i++, bezt++) { - /* additional termination conditions based on the operator 'mode' property go here... */ + /* Additional termination conditions based on the operator 'mode' property go here. */ if (ELEM(mode, POSE_PROPAGATE_BEFORE_FRAME, POSE_PROPAGATE_SMART_HOLDS)) { - /* stop if keyframe is outside the accepted range */ + /* Stop if keyframe is outside the accepted range. */ if (bezt->vec[1][0] > modeData.end_frame) { break; } } else if (mode == POSE_PROPAGATE_NEXT_KEY) { - /* stop after the first keyframe has been processed */ + /* Stop after the first keyframe has been processed. */ if (first == false) { break; } } else if (mode == POSE_PROPAGATE_LAST_KEY) { - /* only affect this frame if it will be the last one */ + /* Only affect this frame if it will be the last one. */ if (i != (fcu->totvert - 1)) { continue; } } else if (mode == POSE_PROPAGATE_SELECTED_MARKERS) { - /* only allow if there's a marker on this frame */ + /* Only allow if there's a marker on this frame. */ CfraElem *ce = NULL; - /* stop on matching marker if there is one */ + /* Stop on matching marker if there is one. */ for (ce = modeData.sel_markers.first; ce; ce = ce->next) { if (ce->cfra == round_fl_to_int(bezt->vec[1][0])) { break; } } - /* skip this keyframe if no marker */ + /* Skip this keyframe if no marker. */ if (ce == NULL) { continue; } } else if (mode == POSE_PROPAGATE_SELECTED_KEYS) { - /* only allow if this keyframe is already selected - skip otherwise */ + /* Only allow if this keyframe is already selected - skip otherwise. */ if (BEZT_ISSEL_ANY(bezt) == 0) { continue; } } - /* just flatten handles, since values will now be the same either side... */ + /* Just flatten handles, since values will now be the same either side. */ /* TODO: perhaps a fade-out modulation of the value is required here (optional once again)? */ bezt->vec[0][1] = bezt->vec[1][1] = bezt->vec[2][1] = refVal; - /* select keyframe to indicate that it's been changed */ + /* Select keyframe to indicate that it's been changed. */ bezt->f2 |= SELECT; first = false; } @@ -2283,7 +2360,7 @@ static int pose_propagate_exec(bContext *C, wmOperator *op) tPosePropagate_ModeData modeData; const int mode = RNA_enum_get(op->ptr, "mode"); - /* isolate F-Curves related to the selected bones */ + /* Isolate F-Curves related to the selected bones. */ poseAnim_mapping_get(C, &pflinks); if (BLI_listbase_is_empty(&pflinks)) { @@ -2294,42 +2371,41 @@ static int pose_propagate_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* mode-specific data preprocessing (requiring no access to curves) */ + /* Mode-specific data preprocessing (requiring no access to curves). */ if (mode == POSE_PROPAGATE_SELECTED_MARKERS) { - /* get a list of selected markers */ + /* Get a list of selected markers. */ ED_markers_make_cfra_list(&scene->markers, &modeData.sel_markers, SELECT); } else { - /* assume everything else wants endFrame */ + /* Assume everything else wants endFrame. */ modeData.end_frame = RNA_float_get(op->ptr, "end_frame"); } - /* for each bone, perform the copying required */ + /* For each bone, perform the copying required. */ for (pfl = pflinks.first; pfl; pfl = pfl->next) { LinkData *ld; - /* mode-specific data preprocessing (requiring access to all curves) */ + /* Mode-specific data preprocessing (requiring access to all curves). */ if (mode == POSE_PROPAGATE_SMART_HOLDS) { - /* we store in endFrame the end frame of the "long keyframe" (i.e. a held value) starting - * from the keyframe that occurs after the current frame - */ + /* We store in endFrame the end frame of the "long keyframe" (i.e. a held value) starting + * from the keyframe that occurs after the current frame. */ modeData.end_frame = pose_propagate_get_boneHoldEndFrame(pfl, (float)CFRA); } - /* go through propagating pose to keyframes, curve by curve */ + /* Go through propagating pose to keyframes, curve by curve. */ for (ld = pfl->fcurves.first; ld; ld = ld->next) { pose_propagate_fcurve(op, pfl->ob, (FCurve *)ld->data, (float)CFRA, modeData); } } - /* free temp data */ + /* Free temp data. */ poseAnim_mapping_free(&pflinks); if (mode == POSE_PROPAGATE_SELECTED_MARKERS) { BLI_freelistN(&modeData.sel_markers); } - /* updates + notifiers */ + /* Updates + notifiers. */ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { poseAnim_mapping_refresh(C, scene, ob); } diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 43ab20eb71c..1118e84ef4f 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -144,26 +144,25 @@ static void applyarmature_transfer_properties(EditBone *curbone, if (pchan->bone->segments > 1) { /* Combine rest/pose values. */ curbone->curve_in_x += pchan_eval->curve_in_x; - curbone->curve_in_y += pchan_eval->curve_in_y; + curbone->curve_in_z += pchan_eval->curve_in_z; curbone->curve_out_x += pchan_eval->curve_out_x; - curbone->curve_out_y += pchan_eval->curve_out_y; + curbone->curve_out_z += pchan_eval->curve_out_z; curbone->roll1 += pchan_eval->roll1; curbone->roll2 += pchan_eval->roll2; curbone->ease1 += pchan_eval->ease1; curbone->ease2 += pchan_eval->ease2; - curbone->scale_in_x *= pchan_eval->scale_in_x; - curbone->scale_in_y *= pchan_eval->scale_in_y; - curbone->scale_out_x *= pchan_eval->scale_out_x; - curbone->scale_out_y *= pchan_eval->scale_out_y; + mul_v3_v3(curbone->scale_in, pchan_eval->scale_in); + mul_v3_v3(curbone->scale_out, pchan_eval->scale_out); /* Reset pose values. */ pchan->curve_in_x = pchan->curve_out_x = 0.0f; - pchan->curve_in_y = pchan->curve_out_y = 0.0f; + pchan->curve_in_z = pchan->curve_out_z = 0.0f; pchan->roll1 = pchan->roll2 = 0.0f; pchan->ease1 = pchan->ease2 = 0.0f; - pchan->scale_in_x = pchan->scale_in_y = 1.0f; - pchan->scale_out_x = pchan->scale_out_y = 1.0f; + + copy_v3_fl(pchan->scale_in, 1.0f); + copy_v3_fl(pchan->scale_out, 1.0f); } /* Clear transform values for pchan. */ @@ -458,7 +457,7 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) /* For the affected bones, reset specific constraints that are now known to be invalid. */ applyarmature_reset_constraints(pose, use_selected); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); @@ -558,7 +557,7 @@ static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op)) DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); } @@ -699,18 +698,17 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, /* B-Bone posing options should also be included... */ pchan->curve_in_x = chan->curve_in_x; - pchan->curve_in_y = chan->curve_in_y; + pchan->curve_in_z = chan->curve_in_z; pchan->curve_out_x = chan->curve_out_x; - pchan->curve_out_y = chan->curve_out_y; + pchan->curve_out_z = chan->curve_out_z; pchan->roll1 = chan->roll1; pchan->roll2 = chan->roll2; pchan->ease1 = chan->ease1; pchan->ease2 = chan->ease2; - pchan->scale_in_x = chan->scale_in_x; - pchan->scale_in_y = chan->scale_in_y; - pchan->scale_out_x = chan->scale_out_x; - pchan->scale_out_y = chan->scale_out_y; + + copy_v3_v3(pchan->scale_in, chan->scale_in); + copy_v3_v3(pchan->scale_out, chan->scale_out); /* paste flipped pose? */ if (flip) { @@ -972,8 +970,9 @@ static void pchan_clear_scale(bPoseChannel *pchan) pchan->ease1 = 0.0f; pchan->ease2 = 0.0f; - pchan->scale_in_x = pchan->scale_in_y = 1.0f; - pchan->scale_out_x = pchan->scale_out_y = 1.0f; + + copy_v3_fl(pchan->scale_in, 1.0f); + copy_v3_fl(pchan->scale_out, 1.0f); } /* Clear the scale. When X-mirror is enabled, * also clear the scale of the mirrored pose channel. */ @@ -1136,9 +1135,9 @@ static void pchan_clear_rot(bPoseChannel *pchan) pchan->roll2 = 0.0f; pchan->curve_in_x = 0.0f; - pchan->curve_in_y = 0.0f; + pchan->curve_in_z = 0.0f; pchan->curve_out_x = 0.0f; - pchan->curve_out_y = 0.0f; + pchan->curve_out_z = 0.0f; } /* Clear the rotation. When X-mirror is enabled, * also clear the rotation of the mirrored pose channel. */ @@ -1229,7 +1228,7 @@ static int pose_clear_transform_generic_exec(bContext *C, DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob_iter); } } @@ -1384,7 +1383,7 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op) BKE_animsys_evaluate_animdata( &workob.id, workob.adt, &anim_eval_context, ADT_RECALC_ANIM, false); - /* copy back values, but on selected bones only */ + /* Copy back values, but on selected bones only. */ for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) { pose_bone_do_paste(ob, pchan, only_select, 0); } diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c index 75348c2b196..500b9663a6c 100644 --- a/source/blender/editors/armature/pose_utils.c +++ b/source/blender/editors/armature/pose_utils.c @@ -116,15 +116,14 @@ static void fcurves_to_pchan_links_get(ListBase *pfLinks, pfl->roll1 = pchan->roll1; pfl->roll2 = pchan->roll2; pfl->curve_in_x = pchan->curve_in_x; - pfl->curve_in_y = pchan->curve_in_y; + pfl->curve_in_z = pchan->curve_in_z; pfl->curve_out_x = pchan->curve_out_x; - pfl->curve_out_y = pchan->curve_out_y; + pfl->curve_out_z = pchan->curve_out_z; pfl->ease1 = pchan->ease1; pfl->ease2 = pchan->ease2; - pfl->scale_in_x = pchan->scale_in_x; - pfl->scale_in_y = pchan->scale_in_y; - pfl->scale_out_x = pchan->scale_out_x; - pfl->scale_out_y = pchan->scale_out_y; + + copy_v3_v3(pfl->scale_in, pchan->scale_in); + copy_v3_v3(pfl->scale_out, pchan->scale_out); /* make copy of custom properties */ if (pchan->prop && (transFlags & ACT_TRANS_PROP)) { @@ -145,7 +144,9 @@ Object *poseAnim_object_get(Object *ob_) return NULL; } -/* get sets of F-Curves providing transforms for the bones in the Pose */ +/** + * Get sets of F-Curves providing transforms for the bones in the Pose. + */ void poseAnim_mapping_get(bContext *C, ListBase *pfLinks) { /* for each Pose-Channel which gets affected, get the F-Curves for that channel @@ -191,7 +192,7 @@ void poseAnim_mapping_get(bContext *C, ListBase *pfLinks) } } -/* free F-Curve <-> PoseChannel links */ +/* Free F-Curve <-> PoseChannel links. */ void poseAnim_mapping_free(ListBase *pfLinks) { tPChanFCurveLink *pfl, *pfln = NULL; @@ -251,15 +252,14 @@ void poseAnim_mapping_reset(ListBase *pfLinks) pchan->roll1 = pfl->roll1; pchan->roll2 = pfl->roll2; pchan->curve_in_x = pfl->curve_in_x; - pchan->curve_in_y = pfl->curve_in_y; + pchan->curve_in_z = pfl->curve_in_z; pchan->curve_out_x = pfl->curve_out_x; - pchan->curve_out_y = pfl->curve_out_y; + pchan->curve_out_z = pfl->curve_out_z; pchan->ease1 = pfl->ease1; pchan->ease2 = pfl->ease2; - pchan->scale_in_x = pfl->scale_in_x; - pchan->scale_in_y = pfl->scale_in_y; - pchan->scale_out_x = pfl->scale_out_x; - pchan->scale_out_y = pfl->scale_out_y; + + copy_v3_v3(pchan->scale_in, pfl->scale_in); + copy_v3_v3(pchan->scale_out, pfl->scale_out); /* just overwrite values of properties from the stored copies (there should be some) */ if (pfl->oldprops) { diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 535ccaa06fd..e7d97ce343c 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -1929,7 +1929,7 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d) } /* Never allow the order to exceed the number of points - * - note, this is ok but changes unselected nurbs, disable for now */ + * NOTE: this is ok but changes unselected nurbs, disable for now. */ #if 0 if ((nu != NULL) && (nu->type == CU_NURBS)) { clamp_nurb_order_u(nu); @@ -1988,7 +1988,7 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d) nu->bp = bp1; /* Never allow the order to exceed the number of points - * - note, this is ok but changes unselected nurbs, disable for now */ + * NOTE: this is ok but changes unselected nurbs, disable for now. */ #if 0 if (nu->type == CU_NURBS) { clamp_nurb_order_u(nu); @@ -3747,8 +3747,8 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts) } if (sel) { /* U ! */ - /* Inserting U points is sort of 'default' Flat curves only get */ - /* U points inserted in them. */ + /* Inserting U points is sort of 'default' Flat curves only get + * U points inserted in them. */ bpn = bpnew = MEM_mallocN((sel + nu->pntsu) * nu->pntsv * sizeof(BPoint), "subdivideNurb4"); bp = nu->bp; @@ -3786,7 +3786,7 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts) MEM_freeN(usel); MEM_freeN(vsel); - } /* End of 'if (nu->type == CU_NURBS)' */ + } /* End of `if (nu->type == CU_NURBS)`. */ } } @@ -6646,7 +6646,7 @@ void CURVE_OT_dissolve_verts(wmOperatorType *ot) static bool nurb_bezt_flag_any(const Nurb *nu, const char flag_test) { - BezTriple *bezt = nu->bezt; + const BezTriple *bezt; int i; for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { @@ -6877,7 +6877,7 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { Nurb *newnu = BKE_nurb_duplicate(nu); - if (ob_active->totcol) { /* TODO, merge material lists */ + if (ob_active->totcol) { /* TODO: merge material lists. */ CLAMP(newnu->mat_nr, 0, ob_active->totcol - 1); } else { diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index 065763764c1..2be55accd3a 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -485,7 +485,7 @@ Nurb *ED_curve_add_nurbs_primitive( break; default: /* should never happen */ - BLI_assert(!"invalid nurbs type"); + BLI_assert_msg(0, "invalid nurbs type"); return NULL; } diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index 8842274e017..26906b0ddcd 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -128,6 +128,7 @@ struct CurveDrawData { } prev; ViewContext vc; + ViewDepths *depths; enum { CURVE_DRAW_IDLE = 0, CURVE_DRAW_PAINTING = 1, @@ -188,7 +189,6 @@ static bool stroke_elem_project(const struct CurveDrawData *cdd, float r_normal_world[3]) { ARegion *region = cdd->vc.region; - RegionView3D *rv3d = cdd->vc.rv3d; bool is_location_world_set = false; @@ -204,13 +204,13 @@ static bool stroke_elem_project(const struct CurveDrawData *cdd, } } else { - const ViewDepths *depths = rv3d->depths; + const ViewDepths *depths = cdd->depths; if (depths && ((uint)mval_i[0] < depths->w) && ((uint)mval_i[1] < depths->h)) { float depth_fl = 1.0f; ED_view3d_depth_read_cached(depths, mval_i, 0, &depth_fl); const double depth = (double)depth_fl; if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { - if (ED_view3d_depth_unproject(region, mval_i, depth, r_location_world)) { + if (ED_view3d_depth_unproject_v3(region, mval_i, depth, r_location_world)) { is_location_world_set = true; if (r_normal_world) { zero_v3(r_normal_world); @@ -219,7 +219,7 @@ static bool stroke_elem_project(const struct CurveDrawData *cdd, if (surface_offset != 0.0f) { const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius; float normal[3]; - if (ED_view3d_depth_read_cached_normal(&cdd->vc, mval_i, normal)) { + if (ED_view3d_depth_read_cached_normal(region, depths, mval_i, normal)) { madd_v3_v3fl(r_location_world, normal, offset * surface_offset); if (r_normal_world) { copy_v3_v3(r_normal_world, normal); @@ -387,7 +387,6 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), GPU_matrix_translate_3f(selem->location_local[0] - location_prev[0], selem->location_local[1] - location_prev[1], selem->location_local[2] - location_prev[2]); - location_prev = selem->location_local; const float radius = stroke_elem_radius(cdd, selem); @@ -529,7 +528,7 @@ static void curve_draw_event_add_first(wmOperator *op, const wmEvent *event) if (ELEM(cps->surface_plane, CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW, CURVE_PAINT_SURFACE_PLANE_NORMAL_SURFACE)) { - if (ED_view3d_depth_read_cached_normal(&cdd->vc, event->mval, normal)) { + if (ED_view3d_depth_read_cached_normal(cdd->vc.region, cdd->depths, event->mval, normal)) { if (cps->surface_plane == CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW) { float cross_a[3], cross_b[3]; cross_v3_v3v3(cross_a, rv3d->viewinv[2], normal); @@ -623,6 +622,9 @@ static void curve_draw_exit(wmOperator *op) BLI_mempool_destroy(cdd->stroke_elem_pool); } + if (cdd->depths) { + ED_view3d_depths_free(cdd->depths); + } MEM_freeN(cdd); op->customdata = NULL; } @@ -696,7 +698,7 @@ static void curve_draw_exec_precalc(wmOperator *op) } if ((cps->radius_taper_start != 0.0f) || (cps->radius_taper_end != 0.0f)) { - /* note, we could try to de-duplicate the length calculations above */ + /* NOTE: we could try to de-duplicate the length calculations above. */ const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool); BLI_mempool_iter iter; @@ -1085,10 +1087,14 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* needed or else the draw matrix can be incorrect */ view3d_operator_needs_opengl(C); - ED_view3d_depth_override( - cdd->vc.depsgraph, cdd->vc.region, cdd->vc.v3d, NULL, V3D_DEPTH_NO_GPENCIL, true); + ED_view3d_depth_override(cdd->vc.depsgraph, + cdd->vc.region, + cdd->vc.v3d, + NULL, + V3D_DEPTH_NO_GPENCIL, + &cdd->depths); - if (cdd->vc.rv3d->depths != NULL) { + if (cdd->depths != NULL) { cdd->project.use_depth = true; } else { diff --git a/source/blender/editors/curve/editcurve_query.c b/source/blender/editors/curve/editcurve_query.c index 56392aab5bf..a8fd3ea2803 100644 --- a/source/blender/editors/curve/editcurve_query.c +++ b/source/blender/editors/curve/editcurve_query.c @@ -168,8 +168,8 @@ bool ED_curve_pick_vert(ViewContext *vc, void ED_curve_nurb_vert_selected_find( Curve *cu, View3D *v3d, Nurb **r_nu, BezTriple **r_bezt, BPoint **r_bp) { - /* in nu and (bezt or bp) selected are written if there's 1 sel. */ - /* if more points selected in 1 spline: return only nu, bezt and bp are 0 */ + /* In nu and (bezt or bp) selected are written if there's 1 sel. */ + /* If more points selected in 1 spline: return only nu, bezt and bp are 0. */ ListBase *editnurb = &cu->editnurb->nurbs; BezTriple *bezt1; BPoint *bp1; diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index 90cefef38ee..721aa7afecc 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -56,6 +56,10 @@ #include "DEG_depsgraph.h" +/* -------------------------------------------------------------------- */ +/** \name Utilities + * \{ */ + /* returns 1 in case (de)selection was successful */ bool select_beztriple(BezTriple *bezt, bool selstatus, uint8_t flag, eVisible_Types hidden) { @@ -107,10 +111,10 @@ static bool swap_selection_bpoint(BPoint *bp) return select_bpoint(bp, SELECT, SELECT, VISIBLE); } -bool ED_curve_nurb_select_check(View3D *v3d, Nurb *nu) +bool ED_curve_nurb_select_check(const View3D *v3d, const Nurb *nu) { if (nu->type == CU_BEZIER) { - BezTriple *bezt; + const BezTriple *bezt; int i; for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { @@ -120,7 +124,7 @@ bool ED_curve_nurb_select_check(View3D *v3d, Nurb *nu) } } else { - BPoint *bp; + const BPoint *bp; int i; for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { @@ -132,12 +136,12 @@ bool ED_curve_nurb_select_check(View3D *v3d, Nurb *nu) return false; } -int ED_curve_nurb_select_count(View3D *v3d, Nurb *nu) +int ED_curve_nurb_select_count(const View3D *v3d, const Nurb *nu) { int sel = 0; if (nu->type == CU_BEZIER) { - BezTriple *bezt; + const BezTriple *bezt; int i; for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { @@ -147,7 +151,7 @@ int ED_curve_nurb_select_count(View3D *v3d, Nurb *nu) } } else { - BPoint *bp; + const BPoint *bp; int i; for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { @@ -223,7 +227,7 @@ bool ED_curve_nurb_deselect_all(const Nurb *nu) return changed; } -int ED_curve_select_count(View3D *v3d, struct EditNurb *editnurb) +int ED_curve_select_count(const View3D *v3d, const EditNurb *editnurb) { int sel = 0; Nurb *nu; @@ -235,9 +239,9 @@ int ED_curve_select_count(View3D *v3d, struct EditNurb *editnurb) return sel; } -bool ED_curve_select_check(View3D *v3d, struct EditNurb *editnurb) +bool ED_curve_select_check(const View3D *v3d, const EditNurb *editnurb) { - LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { + LISTBASE_FOREACH (const Nurb *, nu, &editnurb->nurbs) { if (ED_curve_nurb_select_check(v3d, nu)) { return true; } @@ -398,12 +402,18 @@ static void select_adjacent_cp(ListBase *editnurb, } } -/**************** select start/end operators **************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Start/End Operators + * \{ */ -/* (de)selects first or last of visible part of each Nurb depending on selFirst - * selFirst: defines the end of which to select - * doswap: defines if selection state of each first/last control point is swapped - * selstatus: selection status in case doswap is false +/** + * (De)selects first or last of visible part of each #Nurb depending on `selfirst`. + * + * \param selfirst: defines the end of which to select. + * \param doswap: defines if selection state of each first/last control point is swapped. + * \param selstatus: selection status in case `doswap` is false. */ static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus) { @@ -543,6 +553,12 @@ void CURVE_OT_de_select_last(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select All Operator + * \{ */ + static int de_select_all_exec(bContext *C, wmOperator *op) { int action = RNA_enum_get(op->ptr, "action"); @@ -612,7 +628,11 @@ void CURVE_OT_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } -/***************** select linked operator ******************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked Operator + * \{ */ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -668,7 +688,11 @@ void CURVE_OT_select_linked(wmOperatorType *ot) /* properties */ } -/***************** select linked pick operator ******************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked Pick Operator + * \{ */ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -740,7 +764,11 @@ void CURVE_OT_select_linked_pick(wmOperatorType *ot) "Deselect linked control points rather than selecting them"); } -/***************** select row operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Row Operator + * \{ */ static int select_row_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -802,7 +830,11 @@ void CURVE_OT_select_row(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/***************** select next operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Next Operator + * \{ */ static int select_next_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -839,7 +871,11 @@ void CURVE_OT_select_next(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/***************** select previous operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Previous Operator + * \{ */ static int select_previous_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -876,7 +912,11 @@ void CURVE_OT_select_previous(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/***************** select more operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select More Operator + * \{ */ static void curve_select_more(Object *obedit) { @@ -885,10 +925,10 @@ static void curve_select_more(Object *obedit) int a; short sel = 0; - /* note that NURBS surface is a special case because we mimic */ - /* the behavior of "select more" of mesh tools. */ - /* The algorithm is designed to work in planar cases so it */ - /* may not be optimal always (example: end of NURBS sphere) */ + /* NOTE: NURBS surface is a special case because we mimic + * the behavior of "select more" of mesh tools. + * The algorithm is designed to work in planar cases so it + * may not be optimal always (example: end of NURBS sphere). */ if (obedit->type == OB_SURF) { LISTBASE_FOREACH (Nurb *, nu, editnurb) { BLI_bitmap *selbpoints; @@ -984,7 +1024,11 @@ void CURVE_OT_select_more(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/******************** select less operator *****************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Less Operator + * \{ */ /* basic method: deselect if control point doesn't have all neighbors selected */ static void curve_select_less(Object *obedit) @@ -1198,46 +1242,11 @@ void CURVE_OT_select_less(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** select random *********************/ - -static void curve_select_random(ListBase *editnurb, float randfac, int seed, bool select) -{ - BezTriple *bezt; - BPoint *bp; - int a; - - RNG *rng = BLI_rng_new_srandom(seed); - - LISTBASE_FOREACH (Nurb *, nu, editnurb) { - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - if (!bezt->hide) { - if (BLI_rng_get_float(rng) < randfac) { - select_beztriple(bezt, select, SELECT, VISIBLE); - } - } - bezt++; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - - while (a--) { - if (!bp->hide) { - if (BLI_rng_get_float(rng) < randfac) { - select_bpoint(bp, select, SELECT, VISIBLE); - } - } - bp++; - } - } - } +/** \} */ - BLI_rng_free(rng); -} +/* -------------------------------------------------------------------- */ +/** \name Select Random Operator + * \{ */ static int curve_select_random_exec(bContext *C, wmOperator *op) { @@ -1260,9 +1269,71 @@ static int curve_select_random_exec(bContext *C, wmOperator *op) seed_iter += BLI_ghashutil_strhash_p(obedit->id.name); } - curve_select_random(editnurb, randfac, seed_iter, select); - BKE_curve_nurb_vert_active_validate(obedit->data); + int totvert = 0; + LISTBASE_FOREACH (Nurb *, nu, editnurb) { + if (nu->type == CU_BEZIER) { + int a = nu->pntsu; + BezTriple *bezt = nu->bezt; + while (a--) { + if (!bezt->hide) { + totvert++; + } + bezt++; + } + } + else { + int a = nu->pntsu * nu->pntsv; + BPoint *bp = nu->bp; + while (a--) { + if (!bp->hide) { + totvert++; + } + bp++; + } + } + } + + BLI_bitmap *verts_selection_mask = BLI_BITMAP_NEW(totvert, __func__); + const int count_select = totvert * randfac; + for (int i = 0; i < count_select; i++) { + BLI_BITMAP_SET(verts_selection_mask, i, true); + } + BLI_bitmap_randomize(verts_selection_mask, totvert, seed_iter); + + int bit_index = 0; + LISTBASE_FOREACH (Nurb *, nu, editnurb) { + if (nu->type == CU_BEZIER) { + int a = nu->pntsu; + BezTriple *bezt = nu->bezt; + + while (a--) { + if (!bezt->hide) { + if (BLI_BITMAP_TEST(verts_selection_mask, bit_index)) { + select_beztriple(bezt, select, SELECT, VISIBLE); + } + bit_index++; + } + bezt++; + } + } + else { + int a = nu->pntsu * nu->pntsv; + BPoint *bp = nu->bp; + while (a--) { + if (!bp->hide) { + if (BLI_BITMAP_TEST(verts_selection_mask, bit_index)) { + select_bpoint(bp, select, SELECT, VISIBLE); + } + bit_index++; + } + bp++; + } + } + } + + MEM_freeN(verts_selection_mask); + BKE_curve_nurb_vert_active_validate(obedit->data); DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -1289,7 +1360,11 @@ void CURVE_OT_select_random(wmOperatorType *ot) WM_operator_properties_select_random(ot); } -/********************* every nth number of point *******************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Every Nth Number of Point Operator + * \{ */ static void select_nth_bezt(Nurb *nu, BezTriple *bezt, const struct CheckerIntervalParams *params) { @@ -1421,6 +1496,8 @@ void CURVE_OT_select_nth(wmOperatorType *ot) WM_operator_properties_checker_interval(ot, false); } +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Select Similar Operator * \{ */ diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c index b07c3c85f4a..210411c6eb5 100644 --- a/source/blender/editors/curve/editcurve_undo.c +++ b/source/blender/editors/curve/editcurve_undo.c @@ -97,7 +97,7 @@ static void undocurve_to_editcurve(Main *bmain, UndoCurve *ucu, Curve *cu, short BKE_fcurves_copy(&ad->drivers, &ucu->drivers); } - /* copy */ + /* Copy. */ for (nu = undobase->first; nu; nu = nu->next) { newnu = BKE_nurb_duplicate(nu); @@ -139,7 +139,7 @@ static void undocurve_from_editcurve(UndoCurve *ucu, Curve *cu, const short shap BKE_fcurves_copy(&ucu->drivers, &ad->drivers); } - /* copy */ + /* Copy. */ for (nu = nubase->first; nu; nu = nu->next) { newnu = BKE_nurb_duplicate(nu); @@ -267,7 +267,7 @@ static void curve_undosys_step_decode(struct bContext *C, } undocurve_to_editcurve(bmain, &elem->data, obedit->data, &obedit->shapenr); cu->editnurb->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 80771df3572..e43e4194c51 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -656,7 +656,7 @@ static void txt_add_object(bContext *C, obedit = BKE_object_add(bmain, view_layer, OB_FONT, NULL); base = view_layer->basact; - /* seems to assume view align ? TODO - look into this, could be an operator option */ + /* seems to assume view align ? TODO: look into this, could be an operator option. */ ED_object_base_init_transform_on_add(base->object, NULL, rot); BKE_object_where_is_calc(depsgraph, scene, obedit); @@ -1573,7 +1573,8 @@ static int delete_exec(bContext *C, wmOperator *op) else if (*sel >= range[1]) { *sel -= len_remove; } - else if (*sel < range[1]) { + else { + BLI_assert(*sel < range[1]); /* pass */ *sel = range[0]; } diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c index a305a997d50..6eaf8971eb0 100644 --- a/source/blender/editors/curve/editfont_undo.c +++ b/source/blender/editors/curve/editfont_undo.c @@ -341,7 +341,7 @@ static Object *editfont_object_from_context(bContext *C) typedef struct FontUndoStep { UndoStep step; - /* note: will split out into list for multi-object-editmode. */ + /* NOTE: will split out into list for multi-object-editmode. */ UndoRefID_Object obedit_ref; UndoFont data; } FontUndoStep; @@ -379,7 +379,7 @@ static void font_undosys_step_decode(struct bContext *C, Curve *cu = obedit->data; undofont_to_editfont(&us->data, cu); - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY); ED_undo_object_set_active_or_warn( CTX_data_scene(C), CTX_data_view_layer(C), obedit, us_p->name, &LOG); diff --git a/source/blender/editors/geometry/geometry_attributes.c b/source/blender/editors/geometry/geometry_attributes.c index 12f6bb90677..9b034d82a51 100644 --- a/source/blender/editors/geometry/geometry_attributes.c +++ b/source/blender/editors/geometry/geometry_attributes.c @@ -52,12 +52,16 @@ static const EnumPropertyItem *geometry_attribute_domain_itemf(bContext *C, PropertyRNA *UNUSED(prop), bool *r_free) { + if (C == NULL) { + return DummyRNA_NULL_items; + } + Object *ob = ED_object_context(C); - if (ob != NULL) { - return rna_enum_attribute_domain_itemf(ob->data, r_free); + if (ob == NULL) { + return DummyRNA_NULL_items; } - return DummyRNA_NULL_items; + return rna_enum_attribute_domain_itemf(ob->data, r_free); } static int geometry_attribute_add_exec(bContext *C, wmOperator *op) @@ -105,14 +109,6 @@ void GEOMETRY_OT_attribute_add(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_enum(ot->srna, - "data_type", - rna_enum_attribute_type_items, - CD_PROP_FLOAT, - "Data Type", - "Type of data stored in attribute"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_enum(ot->srna, "domain", rna_enum_attribute_domain_items, ATTR_DOMAIN_POINT, @@ -120,6 +116,14 @@ void GEOMETRY_OT_attribute_add(wmOperatorType *ot) "Type of element that attribute is stored on"); RNA_def_enum_funcs(prop, geometry_attribute_domain_itemf); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_enum(ot->srna, + "data_type", + rna_enum_attribute_type_items, + CD_PROP_FLOAT, + "Data Type", + "Type of data stored in attribute"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } static int geometry_attribute_remove_exec(bContext *C, wmOperator *op) @@ -136,6 +140,11 @@ static int geometry_attribute_remove_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + int *active_index = BKE_id_attributes_active_index_p(id); + if (*active_index > 0) { + *active_index -= 1; + } + DEG_id_tag_update(id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_GEOM | ND_DATA, id); diff --git a/source/blender/editors/gizmo_library/gizmo_draw_utils.c b/source/blender/editors/gizmo_library/gizmo_draw_utils.c index 2896aa25930..2ec287a62e9 100644 --- a/source/blender/editors/gizmo_library/gizmo_draw_utils.c +++ b/source/blender/editors/gizmo_library/gizmo_draw_utils.c @@ -51,7 +51,7 @@ void wm_gizmo_geometryinfo_draw(const GizmoGeomInfo *info, const bool UNUSED(select), const float color[4]) { - /* TODO store the Batches inside the GizmoGeomInfo and updated it when geom changes + /* TODO: store the Batches inside the GizmoGeomInfo and updated it when geom changes * So we don't need to re-created and discard it every time */ GPUVertBuf *vbo; diff --git a/source/blender/editors/gizmo_library/gizmo_library_presets.c b/source/blender/editors/gizmo_library/gizmo_library_presets.c index 4e56ceb9fd4..f842c20b74f 100644 --- a/source/blender/editors/gizmo_library/gizmo_library_presets.c +++ b/source/blender/editors/gizmo_library/gizmo_library_presets.c @@ -41,7 +41,7 @@ #include "ED_gizmo_library.h" /* own include */ #include "gizmo_library_intern.h" /* own include */ -/* TODO, this is to be used by RNA. might move to ED_gizmo_library */ +/* TODO: this is to be used by RNA. might move to ED_gizmo_library. */ /** * Given a single axis, orient the matrix to a different direction. diff --git a/source/blender/editors/gizmo_library/gizmo_library_utils.c b/source/blender/editors/gizmo_library/gizmo_library_utils.c index 847f3e3916c..7d0ae5afb9b 100644 --- a/source/blender/editors/gizmo_library/gizmo_library_utils.c +++ b/source/blender/editors/gizmo_library/gizmo_library_utils.c @@ -118,10 +118,10 @@ void gizmo_property_data_update(wmGizmo *gz, const bool inverted) { if (gz_prop->custom_func.value_get_fn != NULL) { - /* pass */ + /* Pass. */ } else if (gz_prop->prop != NULL) { - /* pass */ + /* Pass. */ } else { data->offset = 0.0f; @@ -237,7 +237,7 @@ bool gizmo_window_project_3d( if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) { View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); - /* Note: we might want a custom reference point passed in, + /* NOTE: we might want a custom reference point passed in, * instead of the gizmo center. */ ED_view3d_win_to_3d(v3d, region, mat[3], mval, r_co); invert_m4(mat); 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 d99ce25451c..f286d3930e2 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c @@ -82,7 +82,7 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz, GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - /* TODO, other draw styles */ + /* TODO: other draw styles. */ if (color[3] == 1.0 && fill_alpha == 1.0 && select == false) { immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv(color); diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c index deb89319f4f..6fd06b47656 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c @@ -774,7 +774,7 @@ static int gizmo_cage2d_get_cursor(wmGizmo *gz) case ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y: return WM_CURSOR_Y_MOVE; - /* TODO diagonal cursor */ + /* TODO: diagonal cursor. */ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y: case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y: return WM_CURSOR_NSEW_SCROLL; diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c index b2d3a2e1576..31ab5eca974 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c @@ -319,9 +319,9 @@ bool ED_gizmotypes_snap_3d_invert_snap_get(struct wmGizmo *gz) #endif } -bool ED_gizmotypes_snap_3d_is_enabled(wmGizmo *gz) +bool ED_gizmotypes_snap_3d_is_enabled(const wmGizmo *gz) { - SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; + const SnapGizmo3D *snap_gizmo = (const SnapGizmo3D *)gz; return snap_gizmo->is_enabled; } diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt index f7ab72a8a43..bff7310e9f7 100644 --- a/source/blender/editors/gpencil/CMakeLists.txt +++ b/source/blender/editors/gpencil/CMakeLists.txt @@ -41,6 +41,7 @@ set(SRC gpencil_add_monkey.c gpencil_add_stroke.c gpencil_armature.c + gpencil_bake_animation.c gpencil_convert.c gpencil_data.c gpencil_edit.c diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c index fe1c5efc747..196fb88ea55 100644 --- a/source/blender/editors/gpencil/annotate_draw.c +++ b/source/blender/editors/gpencil/annotate_draw.c @@ -348,7 +348,7 @@ static void annotation_draw_stroke_3d( /* If there was a significant pressure change, stop the curve, * change the thickness of the stroke, and continue drawing again * (since line-width cannot change in middle of GL_LINE_STRIP) - * Note: we want more visible levels of pressures when thickness is bigger. + * NOTE: we want more visible levels of pressures when thickness is bigger. */ if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) { /* if the pressure changes before get at least 2 vertices, @@ -760,15 +760,15 @@ static void annotation_draw_data_all(Scene *scene, int winy, int cfra, int dflag, - const char spacetype) + const eSpace_Type space_type) { bGPdata *gpd_source = NULL; if (scene) { - if (spacetype == SPACE_VIEW3D) { + if (space_type == SPACE_VIEW3D) { gpd_source = (scene->gpd ? scene->gpd : NULL); } - else if (spacetype == SPACE_CLIP && scene->clip) { + else if (space_type == SPACE_CLIP && scene->clip) { /* currently drawing only gpencil data from either clip or track, * but not both - XXX fix logic behind */ gpd_source = (scene->clip->gpd ? scene->clip->gpd : NULL); @@ -901,7 +901,7 @@ void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d) } /* draw annotations sketches to specified 3d-view assuming that matrices are already set - * correctly Note: this gets called twice - first time with only3d=true to draw 3d-strokes, + * correctly NOTE: this gets called twice - first time with only3d=true to draw 3d-strokes, * second time with only3d=false for screen-aligned strokes */ void ED_annotation_draw_view3d( Scene *scene, struct Depsgraph *depsgraph, View3D *v3d, ARegion *region, bool only3d) diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index c155587e95a..4b0c5ccd285 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -667,7 +667,7 @@ static short annotation_stroke_addpoint(tGPsdata *p, (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? V3D_DEPTH_GPENCIL_ONLY : V3D_DEPTH_NO_GPENCIL, - false); + NULL); } /* convert screen-coordinates to appropriate coordinates (and store them) */ @@ -708,7 +708,7 @@ static void annotation_stroke_arrow_init_conv_point(bGPDspoint *pt, const float static void annotation_stroke_arrow_init_point( tGPsdata *p, tGPspoint *ptc, bGPDspoint *pt, const float co[8], const int co_idx) { - /* Note: provided co_idx should be always pair number as it's [x1, y1, x2, y2, x3, y3]. */ + /* NOTE: provided co_idx should be always pair number as it's [x1, y1, x2, y2, x3, y3]. */ const float real_co[2] = {co[co_idx], co[co_idx + 1]}; copy_v2_v2(&ptc->x, real_co); annotation_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); @@ -908,7 +908,7 @@ static void annotation_stroke_newfrombuffer(tGPsdata *p) CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); pt->time = ptc->time; - /** Create arrow strokes. **/ + /** Create arrow strokes. */ /* End arrow stroke. */ if ((runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_END) && (runtime.arrow_end_style != GP_STROKE_ARROWSTYLE_NONE)) { @@ -1079,17 +1079,6 @@ static void annotation_free_stroke(bGPDframe *gpf, bGPDstroke *gps) BLI_freelinkN(&gpf->strokes, gps); } -/** - * Which which point is in front (result should only be used for comparison). - */ -static float view3d_point_depth(const RegionView3D *rv3d, const float co[3]) -{ - if (rv3d->is_persp) { - return ED_view3d_calc_zfac(rv3d, co, NULL); - } - return -dot_v3v3(rv3d->viewinv[2], co); -} - /* only erase stroke points that are visible (3d view) */ static bool annotation_stroke_eraser_is_occluded(tGPsdata *p, const bGPDspoint *pt, @@ -1102,8 +1091,8 @@ static bool annotation_stroke_eraser_is_occluded(tGPsdata *p, float mval_3d[3]; if (ED_view3d_autodist_simple(p->region, mval_i, mval_3d, 0, NULL)) { - const float depth_mval = view3d_point_depth(rv3d, mval_3d); - const float depth_pt = view3d_point_depth(rv3d, &pt->x); + const float depth_mval = ED_view3d_calc_depth_for_comparison(rv3d, mval_3d); + const float depth_pt = ED_view3d_calc_depth_for_comparison(rv3d, &pt->x); if (depth_pt > depth_mval) { return true; @@ -1152,7 +1141,7 @@ static void annotation_stroke_eraser_dostroke(tGPsdata *p, /* Clear Tags * - * Note: It's better this way, as we are sure that + * NOTE: It's better this way, as we are sure that * we don't miss anything, though things will be * slightly slower as a result */ @@ -1183,7 +1172,7 @@ static void annotation_stroke_eraser_dostroke(tGPsdata *p, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { if ((annotation_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) || @@ -1226,7 +1215,7 @@ static void annotation_stroke_doeraser(tGPsdata *p) if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) { View3D *v3d = p->area->spacedata.first; view3d_region_operator_needs_opengl(p->win, p->region); - ED_view3d_depth_override(p->depsgraph, p->region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, false); + ED_view3d_depth_override(p->depsgraph, p->region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, NULL); } } @@ -1706,7 +1695,7 @@ static void annotation_paint_strokeend(tGPsdata *p) (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? V3D_DEPTH_GPENCIL_ONLY : V3D_DEPTH_NO_GPENCIL, - false); + NULL); } /* check if doing eraser or not */ @@ -2489,18 +2478,15 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve /* default exit state - pass through to support MMB view nav, etc. */ int estate = OPERATOR_PASS_THROUGH; - /* if (event->type == NDOF_MOTION) - * return OPERATOR_PASS_THROUGH; - * ------------------------------- - * [mce] Not quite what I was looking - * for, but a good start! GP continues to - * draw on the screen while the 3D mouse - * moves the viewpoint. Problem is that - * the stroke is converted to 3D only after - * it is finished. This approach should work - * better in tools that immediately apply - * in 3D space. - */ + /* NOTE(mike erwin): Not quite what I was looking for, but a good start! + * grease-pencil continues to draw on the screen while the 3D mouse moves the viewpoint. + * Problem is that the stroke is converted to 3D only after it is finished. + * This approach should work better in tools that immediately apply in 3D space. */ +#if 0 + if (event->type == NDOF_MOTION) { + return OPERATOR_PASS_THROUGH; + } +#endif if (p->status == GP_STATUS_IDLING) { ARegion *region = CTX_wm_region(C); diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 751f8333aaa..2160aaf705f 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -323,7 +323,7 @@ static void gpencil_draw_strokes(tGPDdraw *tgpw) MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : NULL; if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE) || - /* if onion and ghost flag do not draw*/ + /* If onion and ghost flag do not draw. */ (tgpw->onion && (gp_style->flag & GP_MATERIAL_HIDE_ONIONSKIN))) { continue; } diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index 166111c582c..fbdb7c8e520 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -107,7 +107,7 @@ void ED_gpencil_layer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlys /* Selection Tools */ /* check if one of the frames in this layer is selected */ -bool ED_gpencil_layer_frame_select_check(bGPDlayer *gpl) +bool ED_gpencil_layer_frame_select_check(const bGPDlayer *gpl) { /* error checking */ if (gpl == NULL) { @@ -115,7 +115,7 @@ bool ED_gpencil_layer_frame_select_check(bGPDlayer *gpl) } /* stop at the first one found */ - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (const bGPDframe *, gpf, &gpl->frames) { if (gpf->flag & GP_FRAME_SELECT) { return true; } @@ -268,7 +268,7 @@ void ED_gpencil_layer_frames_duplicate(bGPDlayer *gpl) return; } - /* duplicate selected frames */ + /* Duplicate selected frames. */ LISTBASE_FOREACH_MUTABLE (bGPDframe *, gpf, &gpl->frames) { /* duplicate this frame */ @@ -421,7 +421,7 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) return false; } - /* check if single channel in buffer (disregard names if so) */ + /* Check if single channel in buffer (disregard names if so). */ if (gpencil_anim_copybuf.first == gpencil_anim_copybuf.last) { no_name = true; } @@ -513,7 +513,7 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) static bool gpencil_frame_snap_nearest(bGPDframe *UNUSED(gpf), Scene *UNUSED(scene)) { -#if 0 /* note: gpf->framenum is already an int! */ +#if 0 /* NOTE: gpf->framenum is already an int! */ if (gpf->flag & GP_FRAME_SELECT) { gpf->framenum = (int)(floor(gpf->framenum + 0.5)); } diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c index d8734c4ae6b..8d60ef3ed12 100644 --- a/source/blender/editors/gpencil/gpencil_add_monkey.c +++ b/source/blender/editors/gpencil/gpencil_add_monkey.c @@ -39,6 +39,32 @@ #include "ED_gpencil.h" +/** + * Populate stroke with point data from data buffers. + * \param gps: Grease pencil stroke + * \param array: Flat array of point data values. Each entry has #GP_PRIM_DATABUF_SIZE values. + * \param totpoints: Total of points + * \param mat: 4x4 transform matrix to transform points into the right coordinate space. + */ +void ED_gpencil_stroke_init_data(bGPDstroke *gps, + const float *array, + const int totpoints, + const float mat[4][4]) +{ + for (int i = 0; i < totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + const int x = GP_PRIM_DATABUF_SIZE * i; + + pt->x = array[x]; + pt->y = array[x + 1]; + pt->z = array[x + 2]; + mul_m4_v3(mat, &pt->x); + + pt->pressure = array[x + 3]; + pt->strength = array[x + 4]; + } +} + /* Definition of the most important info from a color */ typedef struct ColorTemplate { const char *name; @@ -847,115 +873,115 @@ void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4]) /* generate strokes */ gps = BKE_gpencil_stroke_add(frameFills, color_Skin, 270, 75, false); - BKE_gpencil_stroke_add_points(gps, data0, 270, mat); + ED_gpencil_stroke_init_data(gps, data0, 270, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data1, 33, mat); + ED_gpencil_stroke_init_data(gps, data1, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 60, false); - BKE_gpencil_stroke_add_points(gps, data2, 18, mat); + ED_gpencil_stroke_init_data(gps, data2, 18, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false); - BKE_gpencil_stroke_add_points(gps, data3, 64, mat); + ED_gpencil_stroke_init_data(gps, data3, 64, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data4, 33, mat); + ED_gpencil_stroke_init_data(gps, data4, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false); - BKE_gpencil_stroke_add_points(gps, data5, 64, mat); + ED_gpencil_stroke_init_data(gps, data5, 64, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data6, 33, mat); + ED_gpencil_stroke_init_data(gps, data6, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 18, 40, false); - BKE_gpencil_stroke_add_points(gps, data7, 18, mat); + ED_gpencil_stroke_init_data(gps, data7, 18, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false); - BKE_gpencil_stroke_add_points(gps, data8, 49, mat); + ED_gpencil_stroke_init_data(gps, data8, 49, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data9, 33, mat); + ED_gpencil_stroke_init_data(gps, data9, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false); - BKE_gpencil_stroke_add_points(gps, data10, 49, mat); + ED_gpencil_stroke_init_data(gps, data10, 49, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false); - BKE_gpencil_stroke_add_points(gps, data11, 18, mat); + ED_gpencil_stroke_init_data(gps, data11, 18, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false); - BKE_gpencil_stroke_add_points(gps, data12, 18, mat); + ED_gpencil_stroke_init_data(gps, data12, 18, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data13, 33, mat); + ED_gpencil_stroke_init_data(gps, data13, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data14, 33, mat); + ED_gpencil_stroke_init_data(gps, data14, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 65, 60, false); - BKE_gpencil_stroke_add_points(gps, data15, 65, mat); + ED_gpencil_stroke_init_data(gps, data15, 65, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 60, false); - BKE_gpencil_stroke_add_points(gps, data16, 34, mat); + ED_gpencil_stroke_init_data(gps, data16, 34, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data17, 33, mat); + ED_gpencil_stroke_init_data(gps, data17, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 40, false); - BKE_gpencil_stroke_add_points(gps, data18, 33, mat); + ED_gpencil_stroke_init_data(gps, data18, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 40, false); - BKE_gpencil_stroke_add_points(gps, data19, 34, mat); + ED_gpencil_stroke_init_data(gps, data19, 34, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data20, 33, mat); + ED_gpencil_stroke_init_data(gps, data20, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 64, 60, false); - BKE_gpencil_stroke_add_points(gps, data21, 64, mat); + ED_gpencil_stroke_init_data(gps, data21, 64, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false); - BKE_gpencil_stroke_add_points(gps, data22, 26, mat); + ED_gpencil_stroke_init_data(gps, data22, 26, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false); - BKE_gpencil_stroke_add_points(gps, data23, 26, mat); + ED_gpencil_stroke_init_data(gps, data23, 26, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data24, 33, mat); + ED_gpencil_stroke_init_data(gps, data24, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false); - BKE_gpencil_stroke_add_points(gps, data25, 18, mat); + ED_gpencil_stroke_init_data(gps, data25, 18, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false); - BKE_gpencil_stroke_add_points(gps, data26, 18, mat); + ED_gpencil_stroke_init_data(gps, data26, 18, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data27, 33, mat); + ED_gpencil_stroke_init_data(gps, data27, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); /* update depsgraph */ diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c index e95496b51ee..73c4e64dd9a 100644 --- a/source/blender/editors/gpencil/gpencil_add_stroke.c +++ b/source/blender/editors/gpencil/gpencil_add_stroke.c @@ -235,7 +235,7 @@ void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4]) /* generate stroke */ gps = BKE_gpencil_stroke_add(frame_lines, color_black, 175, 75, false); - BKE_gpencil_stroke_add_points(gps, data0, 175, mat); + ED_gpencil_stroke_init_data(gps, data0, 175, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); /* update depsgraph */ diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c index 3271096c433..c800851bb08 100644 --- a/source/blender/editors/gpencil/gpencil_armature.c +++ b/source/blender/editors/gpencil/gpencil_armature.c @@ -384,7 +384,7 @@ static void gpencil_add_verts_to_dgroups( /* loop groups and assign weight */ for (j = 0; j < numbones; j++) { - int def_nr = BLI_findindex(&ob->defbase, dgrouplist[j]); + int def_nr = BLI_findindex(&gpd->vertex_group_names, dgrouplist[j]); if (def_nr < 0) { continue; } @@ -425,7 +425,7 @@ static void gpencil_add_verts_to_dgroups( } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -454,7 +454,7 @@ static void gpencil_object_vgroup_calc_from_armature(const bContext *C, bArmature *arm = ob_arm->data; /* always create groups */ - const int defbase_tot = BLI_listbase_count(&ob->defbase); + const int defbase_tot = BKE_object_defgroup_count(ob); int defbase_add; /* Traverse the bone list, trying to create empty vertex * groups corresponding to the bone. @@ -462,8 +462,8 @@ static void gpencil_object_vgroup_calc_from_armature(const bContext *C, defbase_add = gpencil_bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb); if (defbase_add) { - /* its possible there are DWeight's outside the range of the current - * objects deform groups, in this case the new groups wont be empty */ + /* It's possible there are DWeights outside the range of the current + * object's deform groups. In this case the new groups won't be empty */ ED_vgroup_data_clamp_range(ob->data, defbase_tot); } diff --git a/source/blender/editors/gpencil/gpencil_bake_animation.c b/source/blender/editors/gpencil/gpencil_bake_animation.c new file mode 100644 index 00000000000..2d299230124 --- /dev/null +++ b/source/blender/editors/gpencil/gpencil_bake_animation.c @@ -0,0 +1,453 @@ +/* + * 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) 2021 Blender Foundation + * This is a new part of Blender + */ + +/** \file + * \ingroup edgpencil + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_ghash.h" +#include "BLI_math.h" + +#include "DNA_anim_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_material_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" + +#include "BKE_anim_data.h" +#include "BKE_context.h" +#include "BKE_duplilist.h" +#include "BKE_gpencil.h" +#include "BKE_gpencil_geom.h" +#include "BKE_gpencil_modifier.h" +#include "BKE_layer.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_object.h" +#include "BKE_report.h" +#include "BKE_scene.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "ED_gpencil.h" +#include "ED_transform_snap_object_context.h" + +#include "gpencil_intern.h" + +const EnumPropertyItem rna_gpencil_reproject_type_items[] = { + {GP_REPROJECT_KEEP, "KEEP", 0, "No Reproject", ""}, + {GP_REPROJECT_FRONT, "FRONT", 0, "Front", "Reproject the strokes using the X-Z plane"}, + {GP_REPROJECT_SIDE, "SIDE", 0, "Side", "Reproject the strokes using the Y-Z plane"}, + {GP_REPROJECT_TOP, "TOP", 0, "Top", "Reproject the strokes using the X-Y plane"}, + {GP_REPROJECT_VIEW, + "VIEW", + 0, + "View", + "Reproject the strokes to end up on the same plane, as if drawn from the current " + "viewpoint " + "using 'Cursor' Stroke Placement"}, + {GP_REPROJECT_CURSOR, + "CURSOR", + 0, + "Cursor", + "Reproject the strokes using the orientation of 3D cursor"}, + {0, NULL, 0, NULL, NULL}, +}; + +/* Check frame_end is always > start frame! */ +static void gpencil_bake_set_frame_end(struct Main *UNUSED(main), + struct Scene *UNUSED(scene), + struct PointerRNA *ptr) +{ + int frame_start = RNA_int_get(ptr, "frame_start"); + int frame_end = RNA_int_get(ptr, "frame_end"); + + if (frame_end <= frame_start) { + RNA_int_set(ptr, "frame_end", frame_start + 1); + } +} + +/* Extract mesh animation to Grease Pencil. */ +static bool gpencil_bake_grease_pencil_animation_poll(bContext *C) +{ + Object *obact = CTX_data_active_object(C); + if (CTX_data_mode_enum(C) != CTX_MODE_OBJECT) { + return false; + } + + /* Check if grease pencil or empty for dupli groups. */ + if ((obact == NULL) || ((obact->type != OB_GPENCIL) && (obact->type != OB_EMPTY))) { + return false; + } + + /* Only if the current view is 3D View. */ + ScrArea *area = CTX_wm_area(C); + return (area && area->spacetype); +} + +typedef struct GpBakeOb { + struct GpBakeOb *next, *prev; + Object *ob; +} GpBakeOb; + +/* Get list of keyframes used by selected objects. */ +static void animdata_keyframe_list_get(ListBase *ob_list, + const bool only_selected, + GHash *r_keyframes) +{ + /* Loop all objects to get the list of keyframes used. */ + LISTBASE_FOREACH (GpBakeOb *, elem, ob_list) { + Object *ob = elem->ob; + AnimData *adt = BKE_animdata_from_id(&ob->id); + if ((adt == NULL) || (adt->action == NULL)) { + continue; + } + LISTBASE_FOREACH (FCurve *, fcurve, &adt->action->curves) { + int i; + BezTriple *bezt; + for (i = 0, bezt = fcurve->bezt; i < fcurve->totvert; i++, bezt++) { + /* Keyframe number is x value of point. */ + if ((bezt->f2 & SELECT) || (!only_selected)) { + /* Insert only one key for each keyframe number. */ + int key = (int)bezt->vec[1][0]; + if (!BLI_ghash_haskey(r_keyframes, POINTER_FROM_INT(key))) { + BLI_ghash_insert(r_keyframes, POINTER_FROM_INT(key), POINTER_FROM_INT(key)); + } + } + } + } + } +} + +static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *list) +{ + GpBakeOb *elem = NULL; + ListBase *lb; + DupliObject *dob; + lb = object_duplilist(depsgraph, scene, ob); + for (dob = lb->first; dob; dob = dob->next) { + if (dob->ob->type != OB_GPENCIL) { + continue; + } + + elem = MEM_callocN(sizeof(GpBakeOb), __func__); + elem->ob = dob->ob; + BLI_addtail(list, elem); + } + + free_object_duplilist(lb); +} + +static void gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene, ListBase *list) +{ + GpBakeOb *elem = NULL; + + /* Add active object. In some files this could not be in selected array. */ + Object *obact = CTX_data_active_object(C); + + if (obact->type == OB_GPENCIL) { + elem = MEM_callocN(sizeof(GpBakeOb), __func__); + elem->ob = obact; + BLI_addtail(list, elem); + } + /* Add duplilist. */ + else if (obact->type == OB_EMPTY) { + gpencil_bake_duplilist(depsgraph, scene, obact, list); + } + + /* Add other selected objects. */ + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { + if (ob == obact) { + continue; + } + /* Add selected objects. */ + if (ob->type == OB_GPENCIL) { + elem = MEM_callocN(sizeof(GpBakeOb), __func__); + elem->ob = ob; + BLI_addtail(list, elem); + } + + /* Add duplilist. */ + if (ob->type == OB_EMPTY) { + gpencil_bake_duplilist(depsgraph, scene, ob, list); + } + } + CTX_DATA_END; +} + +static void gpencil_bake_free_ob_list(ListBase *list) +{ + LISTBASE_FOREACH_MUTABLE (GpBakeOb *, elem, list) { + MEM_SAFE_FREE(elem); + } +} + +static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); + ARegion *region = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + + ListBase ob_selected_list = {NULL, NULL}; + gpencil_bake_ob_list(C, depsgraph, scene, &ob_selected_list); + + /* Grab all relevant settings. */ + const int step = RNA_int_get(op->ptr, "step"); + + const int frame_start = (scene->r.sfra > RNA_int_get(op->ptr, "frame_start")) ? + scene->r.sfra : + RNA_int_get(op->ptr, "frame_start"); + + const int frame_end = (scene->r.efra < RNA_int_get(op->ptr, "frame_end")) ? + scene->r.efra : + RNA_int_get(op->ptr, "frame_end"); + + const bool only_selected = RNA_boolean_get(op->ptr, "only_selected"); + const int frame_offset = RNA_int_get(op->ptr, "frame_target") - frame_start; + const int project_type = RNA_enum_get(op->ptr, "project_type"); + + /* Create a new grease pencil object. */ + Object *ob_gpencil = NULL; + ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; + ob_gpencil = ED_gpencil_add_object(C, scene->cursor.location, local_view_bits); + float invmat[4][4]; + invert_m4_m4(invmat, ob_gpencil->obmat); + + bGPdata *gpd_dst = (bGPdata *)ob_gpencil->data; + gpd_dst->draw_mode = GP_DRAWMODE_2D; + + /* Set cursor to indicate working. */ + WM_cursor_wait(true); + + GP_SpaceConversion gsc = {NULL}; + SnapObjectContext *sctx = NULL; + if (project_type != GP_REPROJECT_KEEP) { + /* Init space conversion stuff. */ + gpencil_point_conversion_init(C, &gsc); + /* Move the grease pencil object to conversion data. */ + gsc.ob = ob_gpencil; + + /* Init snap context for geometry projection. */ + sctx = ED_transform_snap_object_context_create_view3d(scene, 0, region, CTX_wm_view3d(C)); + } + + /* Loop all frame range. */ + int oldframe = (int)DEG_get_ctime(depsgraph); + int key = -1; + + /* Get list of keyframes. */ + GHash *keyframe_list = BLI_ghash_int_new(__func__); + if (only_selected) { + animdata_keyframe_list_get(&ob_selected_list, only_selected, keyframe_list); + } + + for (int i = frame_start; i < frame_end + 1; i++) { + key++; + /* Jump if not step limit but include last frame always. */ + if ((key % step != 0) && (i != frame_end)) { + continue; + } + + /* Check if frame is in the list of frames to be exported. */ + if ((only_selected) && (!BLI_ghash_haskey(keyframe_list, POINTER_FROM_INT(i)))) { + continue; + } + + /* Move scene to new frame. */ + CFRA = i; + BKE_scene_graph_update_for_newframe(depsgraph); + + /* Loop all objects in the list. */ + LISTBASE_FOREACH (GpBakeOb *, elem, &ob_selected_list) { + Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, elem->ob); + bGPdata *gpd_src = ob_eval->data; + + LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) { + /* Create destination layer. */ + char *layer_name; + layer_name = BLI_sprintfN("%s_%s", elem->ob->id.name + 2, gpl_src->info); + bGPDlayer *gpl_dst = BKE_gpencil_layer_named_get(gpd_dst, layer_name); + if (gpl_dst == NULL) { + gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, layer_name, true, false); + } + MEM_freeN(layer_name); + + /* Layer Transform matrix. */ + float matrix[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, elem->ob, gpl_src, matrix); + + /* Apply time modifier. */ + int remap_cfra = BKE_gpencil_time_modifier_cfra( + depsgraph, scene, elem->ob, gpl_src, CFRA, false); + /* Duplicate frame. */ + bGPDframe *gpf_src = BKE_gpencil_layer_frame_get( + gpl_src, remap_cfra, GP_GETFRAME_USE_PREV); + if (gpf_src == NULL) { + continue; + } + bGPDframe *gpf_dst = BKE_gpencil_frame_duplicate(gpf_src, true); + gpf_dst->framenum = CFRA + frame_offset; + gpf_dst->flag &= ~GP_FRAME_SELECT; + BLI_addtail(&gpl_dst->frames, gpf_dst); + + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf_dst->strokes) { + /* Create material of the stroke. */ + Material *ma_src = BKE_object_material_get(elem->ob, gps->mat_nr + 1); + bool found = false; + for (int index = 0; index < ob_gpencil->totcol; index++) { + Material *ma_dst = BKE_object_material_get(ob_gpencil, index + 1); + if (ma_src == ma_dst) { + found = true; + break; + } + } + if (!found) { + BKE_object_material_slot_add(bmain, ob_gpencil); + BKE_object_material_assign( + bmain, ob_gpencil, ma_src, ob_gpencil->totcol, BKE_MAT_ASSIGN_USERPREF); + } + + /* Set new material index. */ + gps->mat_nr = BKE_gpencil_object_material_index_get(ob_gpencil, ma_src); + + /* Update point location to new object space. */ + for (int j = 0; j < gps->totpoints; j++) { + bGPDspoint *pt = &gps->points[j]; + mul_m4_v3(matrix, &pt->x); + mul_m4_v3(invmat, &pt->x); + } + + /* Reproject stroke. */ + if (project_type != GP_REPROJECT_KEEP) { + ED_gpencil_stroke_reproject( + depsgraph, &gsc, sctx, gpl_dst, gpf_dst, gps, project_type, false); + } + else { + BKE_gpencil_stroke_geometry_update(gpd_dst, gps); + } + } + } + } + } + /* Return scene frame state and DB to original state. */ + CFRA = oldframe; + BKE_scene_graph_update_for_newframe(depsgraph); + + /* Free memory. */ + gpencil_bake_free_ob_list(&ob_selected_list); + if (sctx != NULL) { + ED_transform_snap_object_context_destroy(sctx); + } + /* Free temp hash table. */ + if (keyframe_list != NULL) { + BLI_ghash_free(keyframe_list, NULL, NULL); + } + + /* Notifiers. */ + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + DEG_id_tag_update(&gpd_dst->id, ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + + /* Reset cursor. */ + WM_cursor_wait(false); + + /* done */ + return OPERATOR_FINISHED; +} + +static int gpencil_bake_grease_pencil_animation_invoke(bContext *C, + wmOperator *op, + const wmEvent *UNUSED(event)) +{ + PropertyRNA *prop; + Scene *scene = CTX_data_scene(C); + + prop = RNA_struct_find_property(op->ptr, "frame_start"); + if (!RNA_property_is_set(op->ptr, prop)) { + const int frame_start = RNA_property_int_get(op->ptr, prop); + if (frame_start < scene->r.sfra) { + RNA_property_int_set(op->ptr, prop, scene->r.sfra); + } + } + + prop = RNA_struct_find_property(op->ptr, "frame_end"); + if (!RNA_property_is_set(op->ptr, prop)) { + const int frame_end = RNA_property_int_get(op->ptr, prop); + if (frame_end > scene->r.efra) { + RNA_property_int_set(op->ptr, prop, scene->r.efra); + } + } + + /* Show popup dialog to allow editing. */ + return WM_operator_props_dialog_popup(C, op, 250); +} + +void GPENCIL_OT_bake_grease_pencil_animation(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Bake Object Transform to Grease Pencil"; + ot->idname = "GPENCIL_OT_bake_grease_pencil_animation"; + ot->description = "Bake grease pencil object transform to grease pencil keyframes"; + + /* callbacks */ + ot->invoke = gpencil_bake_grease_pencil_animation_invoke; + ot->exec = gpencil_bake_grease_pencil_animation_exec; + ot->poll = gpencil_bake_grease_pencil_animation_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_int( + ot->srna, "frame_start", 1, 1, 100000, "Start Frame", "The start frame", 1, 100000); + + prop = RNA_def_int( + ot->srna, "frame_end", 250, 1, 100000, "End Frame", "The end frame of animation", 1, 100000); + RNA_def_property_update_runtime(prop, gpencil_bake_set_frame_end); + + prop = RNA_def_int(ot->srna, "step", 1, 1, 100, "Step", "Step between generated frames", 1, 100); + + RNA_def_boolean( + ot->srna, "only_selected", 0, "Only Selected Keyframes", "Convert only selected keyframes"); + RNA_def_int( + ot->srna, "frame_target", 1, 1, 100000, "Target Frame", "Destination frame", 1, 100000); + + RNA_def_enum(ot->srna, + "project_type", + rna_gpencil_reproject_type_items, + GP_REPROJECT_KEEP, + "Projection Type", + ""); +} diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 8ab413e907c..ee3536c2f3f 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -168,7 +168,7 @@ static void gpencil_strokepoint_convertcoords(bContext *C, ARegion *region = CTX_wm_region(C); /* TODO(sergey): This function might be called from a loop, but no tagging is happening in it, * so it's not that expensive to ensure evaluated depsgraph here. However, ideally all the - * parameters are to wrapped into a context style struct and queried from Context once.*/ + * parameters are to wrapped into a context style struct and queried from Context once. */ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Object *obact = CTX_data_active_object(C); bGPDspoint mypt, *pt; @@ -219,7 +219,7 @@ typedef struct tGpTimingData { int frame_range; /* Number of frames evaluated for path animation */ int start_frame, end_frame; bool realtime; /* Will overwrite end_frame in case of Original or CustomGap timing... */ - float gap_duration, gap_randomness; /* To be used with CustomGap mode*/ + float gap_duration, gap_randomness; /* To be used with CustomGap mode. */ int seed; /* Data set from points, used to compute final timing FCurve */ @@ -230,7 +230,7 @@ typedef struct tGpTimingData { float tot_dist; /* Times */ - float *times; /* Note: Gap times will be negative! */ + float *times; /* NOTE: Gap times will be negative! */ float tot_time, gap_tot_time; double inittime; @@ -1409,7 +1409,7 @@ static void gpencil_layer_to_curve(bContext *C, gtd); break; default: - BLI_assert(!"invalid mode"); + BLI_assert_msg(0, "invalid mode"); break; } prev_gps = gps; @@ -1806,7 +1806,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot) 0, 100); - /* Note: Internal use, this one will always be hidden by UI code... */ + /* NOTE: Internal use, this one will always be hidden by UI code... */ prop = RNA_def_boolean( ot->srna, "use_timing_data", diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index d9a807d17ab..b1e57079d28 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -828,7 +828,7 @@ static int gpencil_frame_clean_loose_exec(bContext *C, wmOperator *op) } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -871,20 +871,20 @@ void GPENCIL_OT_frame_clean_loose(wmOperatorType *ot) } /* ********************* Clean Duplicated Frames ************************** */ -static bool gpencil_frame_is_equal(bGPDframe *gpf_a, bGPDframe *gpf_b) +static bool gpencil_frame_is_equal(const bGPDframe *gpf_a, const bGPDframe *gpf_b) { if ((gpf_a == NULL) || (gpf_b == NULL)) { return false; } /* If the number of strokes is different, cannot be equal. */ - int totstrokes_a = BLI_listbase_count(&gpf_a->strokes); - int totstrokes_b = BLI_listbase_count(&gpf_b->strokes); + const int totstrokes_a = BLI_listbase_count(&gpf_a->strokes); + const int totstrokes_b = BLI_listbase_count(&gpf_b->strokes); if ((totstrokes_a == 0) || (totstrokes_b == 0) || (totstrokes_a != totstrokes_b)) { return false; } /* Loop all strokes and check. */ - bGPDstroke *gps_a = gpf_a->strokes.first; - bGPDstroke *gps_b = gpf_b->strokes.first; + const bGPDstroke *gps_a = gpf_a->strokes.first; + const bGPDstroke *gps_b = gpf_b->strokes.first; for (int i = 0; i < totstrokes_a; i++) { /* If the number of points is different, cannot be equal. */ if (gps_a->totpoints != gps_b->totpoints) { @@ -924,8 +924,8 @@ static bool gpencil_frame_is_equal(bGPDframe *gpf_a, bGPDframe *gpf_b) /* Loop points and check if equals or not. */ for (int p = 0; p < gps_a->totpoints; p++) { - bGPDspoint *pt_a = &gps_a->points[p]; - bGPDspoint *pt_b = &gps_b->points[p]; + const bGPDspoint *pt_a = &gps_a->points[p]; + const bGPDspoint *pt_b = &gps_b->points[p]; if (!equals_v3v3(&pt_a->x, &pt_b->x)) { return false; } @@ -1572,7 +1572,7 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op) continue; } bool gpf_lock = false; - /* some stroke is already at front*/ + /* Some stroke is already at front. */ if (ELEM(direction, GP_STROKE_MOVE_TOP, GP_STROKE_MOVE_UP)) { if (gps == gpf->strokes.last) { gpf_lock = true; @@ -1664,7 +1664,7 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op) BLI_freelistN(&selected); } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -1772,7 +1772,7 @@ static int gpencil_stroke_change_color_exec(bContext *C, wmOperator *op) } } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -2165,7 +2165,9 @@ static bool gpencil_vertex_group_poll(bContext *C) Object *ob = CTX_data_active_object(C); if ((ob) && (ob->type == OB_GPENCIL)) { - if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) { + const bGPdata *gpd = (const bGPdata *)ob->data; + if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && + !BLI_listbase_is_empty(&gpd->vertex_group_names)) { if (ELEM(ob->mode, OB_MODE_EDIT_GPENCIL, OB_MODE_SCULPT_GPENCIL)) { return true; } @@ -2180,7 +2182,9 @@ static bool gpencil_vertex_group_weight_poll(bContext *C) Object *ob = CTX_data_active_object(C); if ((ob) && (ob->type == OB_GPENCIL)) { - if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) { + const bGPdata *gpd = (const bGPdata *)ob->data; + if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && + !BLI_listbase_is_empty(&gpd->vertex_group_names)) { if (ob->mode == OB_MODE_WEIGHT_GPENCIL) { return true; } @@ -2333,6 +2337,7 @@ static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *op) { ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); + bGPdata *gpd = ob->data; /* sanity checks */ if (ELEM(NULL, ts, ob, ob->data)) { @@ -2340,8 +2345,9 @@ static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *op) } MDeformVert *dvert; - const int def_nr = ob->actdef - 1; - bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr); + const int def_nr = gpd->vertex_group_active_index - 1; + + bDeformGroup *defgroup = BLI_findlink(&gpd->vertex_group_names, def_nr); if (defgroup == NULL) { return OPERATOR_CANCELLED; } @@ -2373,7 +2379,6 @@ static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* notifiers */ - bGPdata *gpd = ob->data; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); @@ -2403,14 +2408,15 @@ static int gpencil_vertex_group_smooth_exec(bContext *C, wmOperator *op) ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); + bGPdata *gpd = ob->data; /* sanity checks */ if (ELEM(NULL, ts, ob, ob->data)) { return OPERATOR_CANCELLED; } - const int def_nr = ob->actdef - 1; - bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr); + const int def_nr = gpd->vertex_group_active_index - 1; + bDeformGroup *defgroup = BLI_findlink(&gpd->vertex_group_names, def_nr); if (defgroup == NULL) { return OPERATOR_CANCELLED; } @@ -2470,7 +2476,6 @@ static int gpencil_vertex_group_smooth_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* notifiers */ - bGPdata *gpd = ob->data; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); @@ -2500,6 +2505,7 @@ static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op) { ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); + bGPdata *gpd = ob->data; /* sanity checks */ if (ELEM(NULL, ts, ob, ob->data)) { @@ -2508,8 +2514,8 @@ static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op) MDeformVert *dvert = NULL; MDeformWeight *dw = NULL; - const int def_nr = ob->actdef - 1; - bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr); + const int def_nr = gpd->vertex_group_active_index - 1; + bDeformGroup *defgroup = BLI_findlink(&gpd->vertex_group_names, def_nr); if (defgroup == NULL) { return OPERATOR_CANCELLED; } @@ -2548,7 +2554,6 @@ static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* notifiers */ - bGPdata *gpd = ob->data; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); @@ -2576,6 +2581,7 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op) ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); bool lock_active = RNA_boolean_get(op->ptr, "lock_active"); + bGPdata *gpd = ob->data; /* sanity checks */ if (ELEM(NULL, ts, ob, ob->data)) { @@ -2585,8 +2591,8 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op) bDeformGroup *defgroup = NULL; MDeformVert *dvert = NULL; MDeformWeight *dw = NULL; - const int def_nr = ob->actdef - 1; - const int defbase_tot = BLI_listbase_count(&ob->defbase); + const int def_nr = gpd->vertex_group_active_index - 1; + const int defbase_tot = BLI_listbase_count(&gpd->vertex_group_names); if (defbase_tot == 0) { return OPERATOR_CANCELLED; } @@ -2603,7 +2609,7 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op) for (int i = 0; i < gps->totpoints; i++) { dvert = &gps->dvert[i]; for (int v = 0; v < defbase_tot; v++) { - defgroup = BLI_findlink(&ob->defbase, v); + defgroup = BLI_findlink(&gpd->vertex_group_names, v); /* skip NULL or locked groups */ if ((defgroup == NULL) || (defgroup->flag & DG_LOCK_WEIGHT)) { continue; @@ -2629,7 +2635,7 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op) dvert = &gps->dvert[i]; for (int v = 0; v < defbase_tot; v++) { - defgroup = BLI_findlink(&ob->defbase, v); + defgroup = BLI_findlink(&gpd->vertex_group_names, v); /* skip NULL or locked groups */ if ((defgroup == NULL) || (defgroup->flag & DG_LOCK_WEIGHT)) { continue; @@ -2653,7 +2659,6 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* notifiers */ - bGPdata *gpd = ob->data; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); @@ -2718,9 +2723,8 @@ static void gpencil_joined_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data) fcu->rna_path = BKE_animsys_fix_rna_path_rename( id, fcu->rna_path, "layers", old_name, new_name, 0, 0, false); - /* we don't want to apply a second remapping on this F-Curve now, - * so stop trying to fix names names - */ + /* We don't want to apply a second remapping on this F-Curve now, + * so stop trying to fix names. */ break; } } @@ -2770,7 +2774,6 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Object *ob_active = CTX_data_active_object(C); - bGPdata *gpd_dst = NULL; bool ok = false; /* Ensure we're in right mode and that the active object is correct */ @@ -2808,7 +2811,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - gpd_dst = ob_active->data; + bGPdata *gpd_dst = ob_active->data; Object *ob_dst = ob_active; /* loop and join all data */ @@ -2829,11 +2832,11 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) /* copy vertex groups to the base one's */ int old_idx = 0; - LISTBASE_FOREACH (bDeformGroup *, dg, &ob_iter->defbase) { + LISTBASE_FOREACH (bDeformGroup *, dg, &gpd_src->vertex_group_names) { bDeformGroup *vgroup = MEM_dupallocN(dg); - int idx = BLI_listbase_count(&ob_active->defbase); + int idx = BLI_listbase_count(&gpd_dst->vertex_group_names); BKE_object_defgroup_unique_name(vgroup, ob_active); - BLI_addtail(&ob_active->defbase, vgroup); + BLI_addtail(&gpd_dst->vertex_group_names, vgroup); /* update vertex groups in strokes in original data */ LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd->layers) { LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_src->frames) { @@ -2853,8 +2856,9 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) } old_idx++; } - if (ob_active->defbase.first && ob_active->actdef == 0) { - ob_active->actdef = 1; + if (!BLI_listbase_is_empty(&gpd_dst->vertex_group_names) && + gpd_dst->vertex_group_active_index == 0) { + gpd_dst->vertex_group_active_index = 1; } /* add missing materials reading source materials and checking in destination object */ @@ -2865,7 +2869,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) BKE_gpencil_object_material_ensure(bmain, ob_dst, tmp_ma); } - /* duplicate bGPDlayers */ + /* Duplicate #bGPDlayers. */ tJoinGPencil_AdtFixData afd = {0}; afd.src_gpd = gpd_src; afd.tar_gpd = gpd_dst; @@ -3356,7 +3360,7 @@ static int gpencil_material_unlock_all_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - /* make all layers editable again*/ + /* Make all layers editable again. */ MaterialGPencilStyle *gp_style = NULL; for (short i = 0; i < *totcol; i++) { @@ -3410,7 +3414,7 @@ static int gpencil_material_select_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* read all strokes and select*/ + /* Read all strokes and select. */ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; @@ -3452,7 +3456,7 @@ static int gpencil_material_select_exec(bContext *C, wmOperator *op) } } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index e65afa1abff..8d1f841da6c 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -863,7 +863,7 @@ static void gpencil_duplicate_points(bGPdata *gpd, start_idx = i; } } - else { + if ((start_idx != -1) || (start_idx == gps->totpoints - 1)) { size_t len = 0; /* is this the end of current island yet? @@ -2779,7 +2779,7 @@ void GPENCIL_OT_dissolve(wmOperatorType *ot) /* Poll callback for snap operators */ /* NOTE: For now, we only allow these in the 3D view, as other editors do not - * define a cursor or gridstep which can be used + * define a cursor or grid-step which can be used. */ static bool gpencil_snap_poll(bContext *C) { @@ -3285,7 +3285,7 @@ static int gpencil_stroke_cyclical_set_exec(bContext *C, wmOperator *op) } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -3443,7 +3443,7 @@ void GPENCIL_OT_stroke_caps_set(wmOperatorType *ot) {GP_STROKE_CAPS_TOGGLE_BOTH, "TOGGLE", 0, "Both", ""}, {GP_STROKE_CAPS_TOGGLE_START, "START", 0, "Start", ""}, {GP_STROKE_CAPS_TOGGLE_END, "END", 0, "End", ""}, - {GP_STROKE_CAPS_TOGGLE_DEFAULT, "TOGGLE", 0, "Default", "Set as default rounded"}, + {GP_STROKE_CAPS_TOGGLE_DEFAULT, "DEFAULT", 0, "Default", "Set as default rounded"}, {0, NULL, 0, NULL, NULL}, }; @@ -3555,7 +3555,7 @@ static int gpencil_stroke_join_exec(bContext *C, wmOperator *op) BLI_assert(ELEM(type, GP_STROKE_JOIN, GP_STROKE_JOINCOPY)); int tot_strokes = 0; - /** Alloc memory */ + /** Alloc memory. */ tJoinStrokes *strokes_list = MEM_malloc_arrayN(sizeof(tJoinStrokes), max_join_strokes, __func__); tJoinStrokes *elem = NULL; /* Read all selected strokes to create a list. */ @@ -4478,7 +4478,7 @@ static int gpencil_stroke_trim_exec(bContext *C, wmOperator *op) } } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -4618,6 +4618,9 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op) /* add layer if not created before */ if (gpl_dst == NULL) { gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl->info, false, false); + BKE_gpencil_layer_copy_settings(gpl, gpl_dst); + /* Copy masks. */ + BKE_gpencil_layer_mask_copy(gpl, gpl_dst); } /* add frame if not created before */ @@ -4678,7 +4681,7 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op) } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -4736,6 +4739,9 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op) } ob_dst->actcol = actcol; + /* Remove any invalid Mask relationship. */ + BKE_gpencil_layer_mask_cleanup_all_layers(gpd_dst); + DEG_id_tag_update(&gpd_src->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); DEG_id_tag_update(&gpd_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); @@ -4854,7 +4860,7 @@ static int gpencil_stroke_split_exec(bContext *C, wmOperator *op) } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -5081,7 +5087,7 @@ static int gpencil_cutter_lasso_select(bContext *C, BKE_gpencil_stroke_select_index_reset(gps); } } - /* if not multiedit, exit loop. */ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -5145,7 +5151,7 @@ static int gpencil_cutter_lasso_select(bContext *C, } } } - /* if not multiedit, exit loop. */ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -5164,7 +5170,7 @@ static int gpencil_cutter_lasso_select(bContext *C, gpencil_cutter_dissolve(gpd, gpl, gps, flat_caps); } } - /* if not multiedit, exit loop. */ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -5347,3 +5353,181 @@ void GPENCIL_OT_stroke_merge_by_distance(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Normalize Operator + * \{ */ + +typedef enum eGP_NormalizeMode { + GP_NORMALIZE_THICKNESS = 0, + GP_NORMALIZE_OPACITY, +} eGP_NormalizeMode; + +static bool gpencil_stroke_normalize_poll(bContext *C) +{ + Object *ob = CTX_data_active_object(C); + if ((ob == NULL) || (ob->type != OB_GPENCIL)) { + return false; + } + bGPdata *gpd = (bGPdata *)ob->data; + if (gpd == NULL) { + return false; + } + + bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); + + return ((gpl != NULL) && (ob->mode == OB_MODE_EDIT_GPENCIL)); +} + +static void gpencil_stroke_normalize_ui(bContext *UNUSED(C), wmOperator *op) +{ + uiLayout *layout = op->layout; + uiLayout *row; + + const eGP_NormalizeMode mode = RNA_enum_get(op->ptr, "mode"); + + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + row = uiLayoutRow(layout, true); + uiItemR(row, op->ptr, "mode", 0, NULL, ICON_NONE); + + if (mode == GP_NORMALIZE_THICKNESS) { + row = uiLayoutRow(layout, true); + uiItemR(row, op->ptr, "value", 0, NULL, ICON_NONE); + } + else if (mode == GP_NORMALIZE_OPACITY) { + row = uiLayoutRow(layout, true); + uiItemR(row, op->ptr, "factor", 0, NULL, ICON_NONE); + } +} + +static int gpencil_stroke_normalize_exec(bContext *C, wmOperator *op) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + + /* Sanity checks. */ + if (ELEM(NULL, gpd)) { + return OPERATOR_CANCELLED; + } + + const eGP_NormalizeMode mode = RNA_enum_get(op->ptr, "mode"); + const int value = RNA_int_get(op->ptr, "value"); + const float factor = RNA_float_get(op->ptr, "factor"); + + /* Go through each editable + selected stroke. */ + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); + + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + 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) { + + /* Skip strokes that are invalid for current view. */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; + } + + bool selected = (is_curve_edit) ? gps->editcurve->flag |= GP_CURVE_SELECT : + (gps->flag & GP_STROKE_SELECT); + if (!selected) { + continue; + } + + float stroke_thickness_inv = 1.0f / max_ii(gps->thickness, 1); + /* Fill opacity need to be managed before. */ + if (mode == GP_NORMALIZE_OPACITY) { + gps->fill_opacity_fac = factor; + CLAMP(gps->fill_opacity_fac, 0.0f, 1.0f); + } + + /* Loop all Polyline points. */ + if (!is_curve_edit) { + for (int i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + if (mode == GP_NORMALIZE_THICKNESS) { + pt->pressure = max_ff((float)value * stroke_thickness_inv, 0.0f); + } + else if (mode == GP_NORMALIZE_OPACITY) { + pt->strength = factor; + CLAMP(pt->strength, 0.0f, 1.0f); + } + } + } + else { + /* Loop all Bezier points. */ + for (int i = 0; i < gps->editcurve->tot_curve_points; i++) { + bGPDcurve_point *gpc_pt = &gps->editcurve->curve_points[i]; + if (mode == GP_NORMALIZE_THICKNESS) { + gpc_pt->pressure = max_ff((float)value * stroke_thickness_inv, 0.0f); + } + else if (mode == GP_NORMALIZE_OPACITY) { + gpc_pt->strength = factor; + CLAMP(gpc_pt->strength, 0.0f, 1.0f); + } + } + + gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE; + BKE_gpencil_stroke_geometry_update(gpd, gps); + } + } + /* If not multi-edit, exit loop. */ + if (!is_multiedit) { + break; + } + } + } + } + CTX_DATA_END; + + /* notifiers */ + DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_stroke_normalize(wmOperatorType *ot) +{ + static const EnumPropertyItem prop_gpencil_normalize_modes[] = { + {GP_NORMALIZE_THICKNESS, + "THICKNESS", + 0, + "Thickness", + "Normalizes the stroke thickness by making all points use the same thickness value"}, + {GP_NORMALIZE_OPACITY, + "OPACITY", + 0, + "Opacity", + "Normalizes the stroke opacity by making all points use the same opacity value"}, + {0, NULL, 0, NULL, NULL}, + }; + + /* identifiers */ + ot->name = "Normalize Stroke"; + ot->idname = "GPENCIL_OT_stroke_normalize"; + ot->description = "Normalize stroke attributes"; + + /* api callbacks */ + ot->exec = gpencil_stroke_normalize_exec; + ot->poll = gpencil_stroke_normalize_poll; + ot->ui = gpencil_stroke_normalize_ui; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + ot->prop = RNA_def_enum( + ot->srna, "mode", prop_gpencil_normalize_modes, 0, "Mode", "Attribute to be normalized"); + RNA_def_float(ot->srna, "factor", 1.0f, 0.0f, 1.0f, "Factor", "", 0.0f, 1.0f); + RNA_def_int(ot->srna, "value", 10, 0, 1000, "Value", "Value", 0, 1000); +} + +/** \} */ diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index f74e211dd65..67e1bd5294b 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -125,7 +125,7 @@ typedef struct tGPDfill { struct bGPDframe *gpf; /** Temp mouse position stroke. */ struct bGPDstroke *gps_mouse; - /** Pointer to report messages. */ + /** Pointer to report messages. */ struct ReportList *reports; /** flags */ short flag; @@ -810,7 +810,7 @@ static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index } } else { - /* edge of image*/ + /* Edge of image. */ t_a = true; } /* pixels on bottom */ @@ -822,7 +822,7 @@ static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index } } else { - /* edge of image*/ + /* Edge of image. */ t_b = true; } } @@ -846,7 +846,7 @@ static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index } } else { - t_a = true; /* edge of image*/ + t_a = true; /* Edge of image. */ } /* pixels to left */ pt = index + extreme; @@ -1373,7 +1373,7 @@ static void gpencil_get_depth_array(tGPDfill *tgpf) /* need to restore the original projection settings before packing up */ view3d_region_operator_needs_opengl(tgpf->win, tgpf->region); ED_view3d_depth_override( - tgpf->depsgraph, tgpf->region, tgpf->v3d, NULL, V3D_DEPTH_NO_GPENCIL, false); + tgpf->depsgraph, tgpf->region, tgpf->v3d, NULL, V3D_DEPTH_NO_GPENCIL, NULL); /* Since strokes are so fine, when using their depth we need a margin * otherwise they might get missed. */ @@ -1522,8 +1522,8 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) pt = gps->points; point2D = (tGPspoint *)tgpf->sbuffer; - const int def_nr = tgpf->ob->actdef - 1; - const bool have_weight = (bool)BLI_findlink(&tgpf->ob->defbase, def_nr); + const int def_nr = tgpf->gpd->vertex_group_active_index - 1; + const bool have_weight = (bool)BLI_findlink(&tgpf->gpd->vertex_group_names, def_nr); if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) { BKE_gpencil_dvert_ensure(gps); @@ -1625,7 +1625,7 @@ static void gpencil_draw_boundary_lines(const bContext *UNUSED(C), tGPDfill *tgp static void gpencil_fill_draw_3d(const bContext *C, ARegion *UNUSED(region), void *arg) { tGPDfill *tgpf = (tGPDfill *)arg; - /* draw only in the region that originated operator. This is required for multiwindow */ + /* Draw only in the region that originated operator. This is required for multi-window. */ ARegion *region = CTX_wm_region(C); if (region != tgpf->region) { return; @@ -1869,7 +1869,7 @@ static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE DEG_id_tag_update(&tgpf->gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); - /* add a modal handler for this operator*/ + /* Add a modal handler for this operator. */ WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; @@ -2123,7 +2123,7 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) gpencil_stroke_convertcoords_tpoint( tgpf->scene, tgpf->region, tgpf->ob, &point2D, NULL, &pt->x); - /* Hash of selected frames.*/ + /* Hash of selected frames. */ GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64); /* If not multiframe and there is no frame in CFRA for the active layer, create diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 9f48c81c8f1..d1a1e417d9e 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -444,6 +444,7 @@ void GPENCIL_OT_frame_clean_duplicate(struct wmOperatorType *ot); void GPENCIL_OT_convert(struct wmOperatorType *ot); void GPENCIL_OT_bake_mesh_animation(struct wmOperatorType *ot); +void GPENCIL_OT_bake_grease_pencil_animation(struct wmOperatorType *ot); void GPENCIL_OT_image_to_grease_pencil(struct wmOperatorType *ot); void GPENCIL_OT_trace_image(struct wmOperatorType *ot); @@ -487,6 +488,7 @@ void GPENCIL_OT_stroke_trim(struct wmOperatorType *ot); void GPENCIL_OT_stroke_merge_by_distance(struct wmOperatorType *ot); void GPENCIL_OT_stroke_merge_material(struct wmOperatorType *ot); void GPENCIL_OT_stroke_reset_vertex_color(struct wmOperatorType *ot); +void GPENCIL_OT_stroke_normalize(struct wmOperatorType *ot); void GPENCIL_OT_material_to_vertex_color(struct wmOperatorType *ot); void GPENCIL_OT_extract_palette_vertex(struct wmOperatorType *ot); @@ -547,51 +549,6 @@ void GPENCIL_OT_convert_old_files(struct wmOperatorType *ot); void GPENCIL_OT_generate_weights(struct wmOperatorType *ot); /* ****************************************************** */ -/* FILTERED ACTION DATA - TYPES ---> XXX DEPRECATED OLD ANIM SYSTEM CODE! */ - -/* XXX - TODO: replace this with the modern bAnimListElem... */ -/* This struct defines a structure used for quick access */ -typedef struct bActListElem { - struct bActListElem *next, *prev; - - void *data; /* source data this elem represents */ - int type; /* one of the ACTTYPE_* values */ - int flag; /* copy of elem's flags for quick access */ - int index; /* copy of adrcode where applicable */ - - void *key_data; /* motion data - ipo or ipo-curve */ - short datatype; /* type of motion data to expect */ - - struct bActionGroup *grp; /* action group that owns the channel */ - - void *owner; /* will either be an action channel or fake IPO-channel (for keys) */ - short ownertype; /* type of owner */ -} bActListElem; - -/* ****************************************************** */ -/* FILTER ACTION DATA - METHODS/TYPES */ - -/* filtering flags - under what circumstances should a channel be added */ -typedef enum ACTFILTER_FLAGS { - ACTFILTER_VISIBLE = (1 << 0), /* should channels be visible */ - ACTFILTER_SEL = (1 << 1), /* should channels be selected */ - ACTFILTER_FOREDIT = (1 << 2), /* does editable status matter */ - ACTFILTER_CHANNELS = (1 << 3), /* do we only care that it is a channel */ - ACTFILTER_IPOKEYS = (1 << 4), /* only channels referencing IPO's */ - ACTFILTER_ONLYICU = (1 << 5), /* only reference ipo-curves */ - ACTFILTER_FORDRAWING = (1 << 6), /* make list for interface drawing */ - ACTFILTER_ACTGROUPED = (1 << 7), /* belongs to the active group */ -} ACTFILTER_FLAGS; - -/* Action Editor - Main Data types */ -typedef enum ACTCONT_TYPES { - ACTCONT_NONE = 0, - ACTCONT_ACTION, - ACTCONT_SHAPEKEY, - ACTCONT_GPENCIL, -} ACTCONT_TYPES; - -/* ****************************************************** */ /* Stroke Iteration Utilities */ struct GP_EditableStrokes_Iter { @@ -635,7 +592,7 @@ struct GP_EditableStrokes_Iter { if (ED_gpencil_stroke_material_editable(obact_, gpl, gps) == false) { \ continue; \ } \ - /* ... Do Stuff With Strokes ... */ + /* ... Do Stuff With Strokes ... */ #define GP_EDITABLE_STROKES_END(gpstroke_iter) \ } \ @@ -685,7 +642,7 @@ struct GP_EditableStrokes_Iter { if (gps->editcurve == NULL) \ continue; \ bGPDcurve *gpc = gps->editcurve; \ - /* ... Do Stuff With Strokes ... */ + /* ... Do Stuff With Strokes ... */ #define GP_EDITABLE_CURVES_END(gpstroke_iter) \ } \ @@ -736,7 +693,7 @@ struct GP_EditableStrokes_Iter { if (ED_gpencil_stroke_material_editable(obact_, gpl, gps) == false) { \ continue; \ } \ - /* ... Do Stuff With Strokes ... */ + /* ... Do Stuff With Strokes ... */ #define GP_EVALUATED_STROKES_END(gpstroke_iter) \ } \ @@ -750,4 +707,7 @@ struct GP_EditableStrokes_Iter { } \ (void)0 +/* Reused items for bake operators. */ +extern const EnumPropertyItem rna_gpencil_reproject_type_items[]; + /* ****************************************************** */ diff --git a/source/blender/editors/gpencil/gpencil_mesh.c b/source/blender/editors/gpencil/gpencil_mesh.c index b7ed77801c0..1882285a230 100644 --- a/source/blender/editors/gpencil/gpencil_mesh.c +++ b/source/blender/editors/gpencil/gpencil_mesh.c @@ -159,7 +159,7 @@ static bool gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene if (ob == obact) { continue; } - /* Add selected meshes.*/ + /* Add selected meshes. */ if (ob->type == OB_MESH) { elem = MEM_callocN(sizeof(GpBakeOb), __func__); elem->ob = ob; @@ -402,25 +402,6 @@ static int gpencil_bake_mesh_animation_invoke(bContext *C, void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) { - static const EnumPropertyItem reproject_type[] = { - {GP_REPROJECT_KEEP, "KEEP", 0, "No Reproject", ""}, - {GP_REPROJECT_FRONT, "FRONT", 0, "Front", "Reproject the strokes using the X-Z plane"}, - {GP_REPROJECT_SIDE, "SIDE", 0, "Side", "Reproject the strokes using the Y-Z plane"}, - {GP_REPROJECT_TOP, "TOP", 0, "Top", "Reproject the strokes using the X-Y plane"}, - {GP_REPROJECT_VIEW, - "VIEW", - 0, - "View", - "Reproject the strokes to end up on the same plane, as if drawn from the current viewpoint " - "using 'Cursor' Stroke Placement"}, - {GP_REPROJECT_CURSOR, - "CURSOR", - 0, - "Cursor", - "Reproject the strokes using the orientation of 3D cursor"}, - {0, NULL, 0, NULL, NULL}, - }; - static const EnumPropertyItem target_object_modes[] = { {GP_TARGET_OB_NEW, "NEW", 0, "New Object", ""}, {GP_TARGET_OB_SELECTED, "SELECTED", 0, "Selected Object", ""}, @@ -491,5 +472,10 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) RNA_def_int( ot->srna, "frame_target", 1, 1, 100000, "Target Frame", "Destination frame", 1, 100000); - RNA_def_enum(ot->srna, "project_type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", ""); + RNA_def_enum(ot->srna, + "project_type", + rna_gpencil_reproject_type_items, + GP_REPROJECT_VIEW, + "Projection Type", + ""); } diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 698d784c3b0..35640cf3b66 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -622,6 +622,7 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_convert); WM_operatortype_append(GPENCIL_OT_bake_mesh_animation); + WM_operatortype_append(GPENCIL_OT_bake_grease_pencil_animation); WM_operatortype_append(GPENCIL_OT_image_to_grease_pencil); #ifdef WITH_POTRACE @@ -648,6 +649,7 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_stroke_merge_by_distance); WM_operatortype_append(GPENCIL_OT_stroke_merge_material); WM_operatortype_append(GPENCIL_OT_stroke_reset_vertex_color); + WM_operatortype_append(GPENCIL_OT_stroke_normalize); WM_operatortype_append(GPENCIL_OT_material_to_vertex_color); WM_operatortype_append(GPENCIL_OT_extract_palette_vertex); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 30d85b09974..d6f6dbb2b10 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -938,8 +938,8 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) Depsgraph *depsgraph = p->depsgraph; Object *obact = (Object *)p->ownerPtr.data; RegionView3D *rv3d = p->region->regiondata; - const int def_nr = obact->actdef - 1; - const bool have_weight = (bool)BLI_findlink(&obact->defbase, def_nr); + const int def_nr = gpd->vertex_group_active_index - 1; + const bool have_weight = (bool)BLI_findlink(&gpd->vertex_group_names, def_nr); const char align_flag = ts->gpencil_v3d_align; const bool is_depth = (bool)(align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE)); const bool is_lock_axis_view = (bool)(ts->gp_sculpt.lock_axis == 0); @@ -1319,20 +1319,9 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) /* --- 'Eraser' for 'Paint' Tool ------ */ -/** - * Which which point is in front (result should only be used for comparison). - */ -static float view3d_point_depth(const RegionView3D *rv3d, const float co[3]) -{ - if (rv3d->is_persp) { - return ED_view3d_calc_zfac(rv3d, co, NULL); - } - return -dot_v3v3(rv3d->viewinv[2], co); -} - /* only erase stroke points that are visible */ static bool gpencil_stroke_eraser_is_occluded( - tGPsdata *p, bGPDlayer *gpl, const bGPDspoint *pt, const int x, const int y) + tGPsdata *p, bGPDlayer *gpl, bGPDspoint *pt, const int x, const int y) { Object *obact = (Object *)p->ownerPtr.data; Brush *brush = p->brush; @@ -1359,12 +1348,16 @@ static bool gpencil_stroke_eraser_is_occluded( 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); + const float depth_mval = ED_view3d_calc_depth_for_comparison(rv3d, mval_3d); mul_v3_m4v3(fpt, diff_mat, &pt->x); - const float depth_pt = view3d_point_depth(rv3d, fpt); + const float depth_pt = ED_view3d_calc_depth_for_comparison(rv3d, fpt); + /* Checked occlusion flag. */ + pt->flag |= GP_SPOINT_TEMP_TAG; if (depth_pt > depth_mval) { + /* Is occluded. */ + pt->flag |= GP_SPOINT_TEMP_TAG2; return true; } } @@ -1429,7 +1422,7 @@ static void gpencil_stroke_soft_refine(bGPDstroke *gps) bGPDspoint *pt2 = NULL; int i; - /* check if enough points*/ + /* Check if enough points. */ if (gps->totpoints < 3) { return; } @@ -1533,13 +1526,17 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p, /* Clear Tags * - * Note: It's better this way, as we are sure that + * NOTE: It's better this way, as we are sure that * we don't miss anything, though things will be * slightly slower as a result */ for (i = 0; i < gps->totpoints; i++) { bGPDspoint *pt = &gps->points[i]; pt->flag &= ~GP_SPOINT_TAG; + /* Occlusion already checked. */ + pt->flag &= ~GP_SPOINT_TEMP_TAG; + /* Point is occluded. */ + pt->flag &= ~GP_SPOINT_TEMP_TAG2; } /* First Pass: Loop over the points in the stroke @@ -1582,12 +1579,26 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(mval, radius, pc0[0], pc0[1], pc2[0], pc2[1])) { - 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)) { + + bool is_occluded_pt0, is_occluded_pt1, is_occluded_pt2 = true; + is_occluded_pt0 = (pt0 && ((pt0->flag & GP_SPOINT_TEMP_TAG) != 0)) ? + ((pt0->flag & GP_SPOINT_TEMP_TAG2) != 0) : + gpencil_stroke_eraser_is_occluded(p, gpl, pt0, pc0[0], pc0[1]); + if (is_occluded_pt0) { + is_occluded_pt1 = ((pt1->flag & GP_SPOINT_TEMP_TAG) != 0) ? + ((pt1->flag & GP_SPOINT_TEMP_TAG2) != 0) : + gpencil_stroke_eraser_is_occluded(p, gpl, pt1, pc1[0], pc1[1]); + if (is_occluded_pt1) { + is_occluded_pt2 = ((pt2->flag & GP_SPOINT_TEMP_TAG) != 0) ? + ((pt2->flag & GP_SPOINT_TEMP_TAG2) != 0) : + gpencil_stroke_eraser_is_occluded(p, gpl, pt2, pc2[0], pc2[1]); + } + } + + if (!is_occluded_pt0 || !is_occluded_pt1 || !is_occluded_pt2) { /* Point is affected: */ /* Adjust thickness * - Influence of eraser falls off with distance from the middle of the eraser @@ -1722,7 +1733,7 @@ static void gpencil_stroke_doeraser(tGPsdata *p) if ((gp_settings != NULL) && (gp_settings->flag & GP_BRUSH_OCCLUDE_ERASER)) { View3D *v3d = p->area->spacedata.first; view3d_region_operator_needs_opengl(p->win, p->region); - ED_view3d_depth_override(p->depsgraph, p->region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, false); + ED_view3d_depth_override(p->depsgraph, p->region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, NULL); } } @@ -1770,7 +1781,7 @@ static void gpencil_stroke_doeraser(tGPsdata *p) } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -2163,7 +2174,7 @@ static void gpencil_paint_initstroke(tGPsdata *p, /* Add a new frame if needed (and based off the active frame, * as we need some existing strokes to erase) * - * Note: We don't add a new frame if there's nothing there now, so + * NOTE: We don't add a new frame if there's nothing there now, so * -> If there are no frames at all, don't add one * -> If there are no strokes in that frame, don't add a new empty frame */ @@ -2312,7 +2323,7 @@ static void gpencil_paint_strokeend(tGPsdata *p) (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? V3D_DEPTH_GPENCIL_ONLY : V3D_DEPTH_NO_GPENCIL, - false); + NULL); } /* check if doing eraser or not */ @@ -3156,7 +3167,7 @@ static void gpencil_guide_event_handling(bContext *C, guide->type = GP_GUIDE_CIRCULAR; } } - /* Change line angle */ + /* Change line angle. */ else if (ELEM(event->type, EVT_JKEY, EVT_KKEY) && (event->val == KM_RELEASE)) { add_notifier = true; float angle = guide->angle; @@ -3265,7 +3276,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event gpencil_guide_event_handling(C, op, event, p); } - if (ob && (ob->type == OB_GPENCIL) && ((p->gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0)) { + if ((ob->type == OB_GPENCIL) && ((p->gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0)) { /* FIXME: use the mode switching operator, this misses notifiers, messages. */ /* Just set paintmode flag... */ p->gpd->flag |= GP_DATA_STROKE_PAINTMODE; @@ -3438,7 +3449,7 @@ static void gpencil_add_arc_points(tGPsdata *p, const float mval[2], int segment interp_v4_v4v4( pt->vert_color, pt_before->vert_color, pt_prev->vert_color, stepcolor * (i + 1)); - /* Apply angle of stroke to brush size to interpolated points but slightly attenuated.. */ + /* Apply angle of stroke to brush size to interpolated points but slightly attenuated. */ if (brush_settings->draw_angle_factor != 0.0f) { gpencil_brush_angle_segment(p, pt_step, pt); CLAMP(pt->pressure, pt_prev->pressure * 0.5f, 1.0f); @@ -3591,18 +3602,15 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* default exit state - pass through to support MMB view nav, etc. */ int estate = OPERATOR_PASS_THROUGH; - /* if (event->type == NDOF_MOTION) - * return OPERATOR_PASS_THROUGH; - * ------------------------------- - * [mce] Not quite what I was looking - * for, but a good start! GP continues to - * draw on the screen while the 3D mouse - * moves the viewpoint. Problem is that - * the stroke is converted to 3D only after - * it is finished. This approach should work - * better in tools that immediately apply - * in 3D space. - */ + /* NOTE(mike erwin): Not quite what I was looking for, but a good start! + * grease-pencil continues to draw on the screen while the 3D mouse moves the viewpoint. + * Problem is that the stroke is converted to 3D only after it is finished. + * This approach should work better in tools that immediately apply in 3D space. */ +#if 0 + if (event->type == NDOF_MOTION) { + return OPERATOR_PASS_THROUGH; + } +#endif if (p->status == GP_STATUS_IDLING) { ARegion *region = CTX_wm_region(C); @@ -3749,7 +3757,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else if (p->region) { - /* Perform bounds check using */ + /* Perform bounds check using. */ const rcti *region_rect = ED_region_visible_rect(p->region); in_bounds = BLI_rcti_isect_pt_v(region_rect, event->mval); } diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 1b0a40b1be1..78eaab01b1a 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -792,7 +792,7 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? V3D_DEPTH_GPENCIL_ONLY : V3D_DEPTH_NO_GPENCIL, - false); + NULL); depth_arr = MEM_mallocN(sizeof(float) * gps->totpoints, "depth_points"); tGPspoint *ptc = &points2D[0]; @@ -1315,8 +1315,9 @@ static void gpencil_primitive_interaction_end(bContext *C, Brush *brush = tgpi->brush; BrushGpencilSettings *brush_settings = brush->gpencil_settings; - const int def_nr = tgpi->ob->actdef - 1; - const bool have_weight = (bool)BLI_findlink(&tgpi->ob->defbase, def_nr); + const int def_nr = tgpi->gpd->vertex_group_active_index - 1; + const ListBase *defbase = BKE_object_defgroup_list(tgpi->ob); + const bool have_weight = (bool)BLI_findlink(defbase, def_nr); /* return to normal cursor and header status */ ED_workspace_status_text(C, NULL); @@ -1536,24 +1537,22 @@ static void gpencil_primitive_strength(tGPDprimitive *tgpi, bool reset) Brush *brush = tgpi->brush; BrushGpencilSettings *brush_settings = brush->gpencil_settings; - if (brush) { - if (reset) { - brush_settings->draw_strength = tgpi->brush_strength; - tgpi->brush_strength = 0.0f; - } - else { - if (tgpi->brush_strength == 0.0f) { - tgpi->brush_strength = brush_settings->draw_strength; - } - float move[2]; - sub_v2_v2v2(move, tgpi->mval, tgpi->mvalo); - float adjust = (move[1] > 0.0f) ? 0.01f : -0.01f; - brush_settings->draw_strength += adjust * fabsf(len_manhattan_v2(move)); + if (reset) { + brush_settings->draw_strength = tgpi->brush_strength; + tgpi->brush_strength = 0.0f; + } + else { + if (tgpi->brush_strength == 0.0f) { + tgpi->brush_strength = brush_settings->draw_strength; } - - /* limit low limit because below 0.2f the stroke is invisible */ - CLAMP(brush_settings->draw_strength, 0.2f, 1.0f); + float move[2]; + sub_v2_v2v2(move, tgpi->mval, tgpi->mvalo); + float adjust = (move[1] > 0.0f) ? 0.01f : -0.01f; + brush_settings->draw_strength += adjust * fabsf(len_manhattan_v2(move)); } + + /* limit low limit because below 0.2f the stroke is invisible */ + CLAMP(brush_settings->draw_strength, 0.2f, 1.0f); } /* brush size */ diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index 2b8800e5136..462462cf341 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -1096,7 +1096,7 @@ static void gpencil_brush_clone_adjust(tGP_BrushEditData *gso) } } -/* Entrypoint for applying "clone" brush */ +/* Entry-point for applying "clone" brush. */ static bool gpencil_sculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso) { /* Which "mode" are we operating in? */ @@ -1177,8 +1177,8 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op) gso->object = ob; if (ob) { invert_m4_m4(gso->inv_mat, ob->obmat); - gso->vrgroup = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, gso->vrgroup)) { + gso->vrgroup = gso->gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gso->gpd->vertex_group_names, gso->vrgroup)) { gso->vrgroup = -1; } /* Check if some modifier can transform the stroke. */ @@ -1381,7 +1381,7 @@ static float gpencil_sculpt_rotation_eval_get(tGP_BrushEditData *gso, return 0.0f; } - GP_SpaceConversion *gsc = &gso->gsc; + const GP_SpaceConversion *gsc = &gso->gsc; bGPDstroke *gps_orig = (gps_eval->runtime.gps_orig) ? gps_eval->runtime.gps_orig : gps_eval; bGPDspoint *pt_orig = &gps_orig->points[pt_eval->runtime.idx_orig]; bGPDspoint *pt_prev_eval = NULL; @@ -1500,7 +1500,7 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * brush region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { /* Apply operation to these points */ @@ -2020,7 +2020,7 @@ static int gpencil_sculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent /* The operator can be in 2 states: Painting and Idling */ if (gso->is_painting) { - /* Painting */ + /* Painting. */ switch (event->type) { /* Mouse Move = Apply somewhere else */ case MOUSEMOVE: diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index e1776988186..69734fa1ba8 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -689,7 +689,7 @@ static int gpencil_select_grouped_exec(bContext *C, wmOperator *op) break; default: - BLI_assert(!"unhandled select grouped gpencil mode"); + BLI_assert_msg(0, "unhandled select grouped gpencil mode"); break; } @@ -1276,7 +1276,7 @@ static bool gpencil_stroke_do_circle_sel(bGPdata *gpd, pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; bGPDspoint pt_temp; - gpencil_point_to_parent_space(pt_active, diff_mat, &pt_temp); + gpencil_point_to_parent_space(pt, diff_mat, &pt_temp); gpencil_point_to_xy(gsc, gps, &pt_temp, &x0, &y0); /* do boundbox check first */ @@ -1374,7 +1374,7 @@ static bool gpencil_do_curve_circle_sel(bContext *C, const bool handles_visible = (v3d->overlay.handle_display != CURVE_HANDLE_NONE) && (!only_selected || BEZT_ISSEL_ANY(bezt)); - /* if the handles are not visible only check ctrl point (vec[1])*/ + /* If the handles are not visible only check control point (vec[1]). */ int from = (!handles_visible) ? 1 : 0; int to = (!handles_visible) ? 2 : 3; @@ -1719,7 +1719,7 @@ static bool gpencil_generic_curve_select(bContext *C, } } } - /* if the handles are not visible only check ctrl point (vec[1])*/ + /* If the handles are not visible only check ctrl point (vec[1]). */ else { const bool is_select = bezt->f2; bool is_inside = is_inside_fn(region, gps_iter.diff_mat, bezt->vec[1], user_data); @@ -1847,7 +1847,7 @@ static bool gpencil_generic_stroke_select(bContext *C, bGPDspoint *pt; int i; bool hit = false; - for (i = 0, pt = gps_active->points; i < gps_active->totpoints; i++, pt++) { + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; /* convert point coords to screenspace */ @@ -1889,7 +1889,7 @@ static bool gpencil_generic_stroke_select(bContext *C, mval[0] = (box.xmax + box.xmin) / 2; mval[1] = (box.ymax + box.ymin) / 2; - whole = ED_gpencil_stroke_point_is_inside(gps_active, &gsc, mval, gpstroke_iter.diff_mat); + whole = ED_gpencil_stroke_point_is_inside(gps, &gsc, mval, gpstroke_iter.diff_mat); } /* if stroke mode expand selection. */ @@ -2153,7 +2153,7 @@ static void gpencil_select_curve_point(bContext *C, const bool handles_visible = (v3d->overlay.handle_display != CURVE_HANDLE_NONE) && (!only_selected || BEZT_ISSEL_ANY(bezt)); - /* if the handles are not visible only check ctrl point (vec[1])*/ + /* If the handles are not visible only check control point (vec[1]). */ int from = (!handles_visible) ? 1 : 0; int to = (!handles_visible) ? 2 : 3; @@ -2252,7 +2252,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) int i; /* firstly, check for hit-point */ - for (i = 0, pt = gps_active->points; i < gps_active->totpoints; i++, pt++) { + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { int xy[2]; bGPDspoint pt2; diff --git a/source/blender/editors/gpencil/gpencil_trace_utils.c b/source/blender/editors/gpencil/gpencil_trace_utils.c index 482f7015720..970afc3ff6b 100644 --- a/source/blender/editors/gpencil/gpencil_trace_utils.c +++ b/source/blender/editors/gpencil/gpencil_trace_utils.c @@ -250,7 +250,7 @@ void ED_gpencil_trace_data_to_strokes(Main *bmain, const int32_t thickness) { #define MAX_LENGTH 100.0f - /* Find materials and create them if not found. */ + /* Find materials and create them if not found. */ int32_t mat_fill_idx = BKE_gpencil_material_find_index_by_name_prefix(ob, "Stroke"); int32_t mat_mask_idx = BKE_gpencil_material_find_index_by_name_prefix(ob, "Holdout"); @@ -281,7 +281,6 @@ void ED_gpencil_trace_data_to_strokes(Main *bmain, mat_mask_idx = ob->totcol - 1; } - potrace_path_t *path = st->plist; int n, *tag; potrace_dpoint_t(*c)[3]; @@ -289,7 +288,7 @@ void ED_gpencil_trace_data_to_strokes(Main *bmain, * good results using the Potrace data. */ const float scalef = 0.008f * scale; /* Draw each curve. */ - path = st->plist; + potrace_path_t *path = st->plist; while (path != NULL) { n = path->curve.n; tag = path->curve.tag; diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 04764587ebe..ba3d3b584d7 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -565,7 +565,7 @@ bool ED_gpencil_layer_has_selected_stroke(const bGPDlayer *gpl, const bool is_mu return true; } } - /* If not multiedit, exit loop. */ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -680,7 +680,7 @@ void gpencil_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc) view3d_operator_needs_opengl(C); view3d_region_operator_needs_opengl(win, region); - ED_view3d_depth_override(depsgraph, region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, false); + ED_view3d_depth_override(depsgraph, region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, NULL); /* for camera view set the subrect */ if (rv3d->persp == RV3D_CAMOB) { @@ -1227,7 +1227,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, float xy[2]; /* 3D to Screen-space */ - /* Note: We can't use gpencil_point_to_xy() here because that uses ints for the screen-space + /* NOTE: We can't use gpencil_point_to_xy() here because that uses ints for the screen-space * coordinates, resulting in lost precision, which in turn causes stair-stepping * artifacts in the final points. */ @@ -1276,6 +1276,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, } else { /* Geometry - Snap to surfaces of visible geometry */ + float ray_start[3]; float ray_normal[3]; /* magic value for initial depth copied from the default * value of Python's Scene.ray_cast function @@ -1284,14 +1285,17 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, float location[3] = {0.0f, 0.0f, 0.0f}; float normal[3] = {0.0f, 0.0f, 0.0f}; - ED_view3d_win_to_vector(region, xy, &ray_normal[0]); BLI_assert(gps->flag & GP_STROKE_3DSPACE); + BLI_assert(gsc->area && gsc->area->spacetype == SPACE_VIEW3D); + const View3D *v3d = gsc->area->spacedata.first; + ED_view3d_win_to_ray_clipped( + depsgraph, region, v3d, xy, &ray_start[0], &ray_normal[0], true); if (ED_transform_snap_object_project_ray(sctx, depsgraph, &(const struct SnapObjectParams){ .snap_select = SNAP_ALL, }, - &pt2.x, + &ray_start[0], &ray_normal[0], &depth, &location[0], @@ -1596,8 +1600,8 @@ void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight) { bGPdata *gpd = (bGPdata *)ob->data; const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const int def_nr = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) { + const int def_nr = gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) { return; } @@ -1636,7 +1640,7 @@ void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight) } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -1650,8 +1654,8 @@ void ED_gpencil_vgroup_remove(bContext *C, Object *ob) { bGPdata *gpd = (bGPdata *)ob->data; const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const int def_nr = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) { + const int def_nr = gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) { return; } @@ -1689,7 +1693,7 @@ void ED_gpencil_vgroup_remove(bContext *C, Object *ob) } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -1703,8 +1707,8 @@ void ED_gpencil_vgroup_select(bContext *C, Object *ob) { bGPdata *gpd = (bGPdata *)ob->data; const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const int def_nr = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) { + const int def_nr = gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) { return; } @@ -1744,7 +1748,7 @@ void ED_gpencil_vgroup_select(bContext *C, Object *ob) } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -1758,8 +1762,8 @@ void ED_gpencil_vgroup_deselect(bContext *C, Object *ob) { bGPdata *gpd = (bGPdata *)ob->data; const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const int def_nr = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) { + const int def_nr = gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) { return; } @@ -1794,7 +1798,7 @@ void ED_gpencil_vgroup_deselect(bContext *C, Object *ob) } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -2211,7 +2215,7 @@ void ED_gpencil_tpoint_to_point(ARegion *region, void ED_gpencil_update_color_uv(Main *bmain, Material *mat) { Material *gps_ma = NULL; - /* read all strokes */ + /* Read all strokes. */ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { if (ob->type == OB_GPENCIL) { bGPdata *gpd = ob->data; @@ -2474,7 +2478,7 @@ int ED_gpencil_select_stroke_segment(bGPdata *gpd, return 0; } - /* convert all gps points to 2d and save in a hash to avoid recalculation */ + /* Convert all gps points to 2d and save in a hash to avoid recalculation. */ int direction = 0; float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points"); @@ -3102,8 +3106,8 @@ void ED_gpencil_sbuffer_vertex_color_set(Depsgraph *depsgraph, } /* Get the bigger 2D bound box points. */ -void ED_gpencil_projected_2d_bound_box(GP_SpaceConversion *gsc, - bGPDstroke *gps, +void ED_gpencil_projected_2d_bound_box(const GP_SpaceConversion *gsc, + const bGPDstroke *gps, const float diff_mat[4][4], float r_min[2], float r_max[2]) @@ -3136,7 +3140,7 @@ void ED_gpencil_projected_2d_bound_box(GP_SpaceConversion *gsc, } /* Check if the stroke collides with brush. */ -bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc, +bool ED_gpencil_stroke_check_collision(const GP_SpaceConversion *gsc, bGPDstroke *gps, const float mouse[2], const int radius, @@ -3171,9 +3175,9 @@ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc, * \param diff_mat: View matrix. * \return True if the point is inside. */ -bool ED_gpencil_stroke_point_is_inside(bGPDstroke *gps, - GP_SpaceConversion *gsc, - int mouse[2], +bool ED_gpencil_stroke_point_is_inside(const bGPDstroke *gps, + const GP_SpaceConversion *gsc, + const int mouse[2], const float diff_mat[4][4]) { bool hit = false; @@ -3186,7 +3190,7 @@ bool ED_gpencil_stroke_point_is_inside(bGPDstroke *gps, mcoords = MEM_mallocN(sizeof(int[2]) * len, __func__); /* Convert stroke to 2D array of points. */ - bGPDspoint *pt; + const bGPDspoint *pt; int i; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { bGPDspoint pt2; @@ -3210,7 +3214,7 @@ bool ED_gpencil_stroke_point_is_inside(bGPDstroke *gps, } bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C, - GP_SpaceConversion *gsc, + const GP_SpaceConversion *gsc, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, @@ -3298,7 +3302,7 @@ bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C, return gps_rtn; } -/* Join two stroke using a contact point index and trimming the rest. */ +/* Join two stroke using a contact point index and trimming the rest. */ bGPDstroke *ED_gpencil_stroke_join_and_trim( bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *gps_dst, const int pt_index) { diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c index bf46fa2544f..402bccce2f7 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_ops.c +++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c @@ -99,7 +99,7 @@ static bool is_any_stroke_selected(bContext *C, const bool is_multiedit, const b } } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -204,7 +204,7 @@ static int gpencil_vertexpaint_brightness_contrast_exec(bContext *C, wmOperator } } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -325,7 +325,7 @@ static int gpencil_vertexpaint_hsv_exec(bContext *C, wmOperator *op) } } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -419,7 +419,7 @@ static int gpencil_vertexpaint_invert_exec(bContext *C, wmOperator *op) } } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -510,7 +510,7 @@ static int gpencil_vertexpaint_levels_exec(bContext *C, wmOperator *op) } } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -605,7 +605,7 @@ static int gpencil_vertexpaint_set_exec(bContext *C, wmOperator *op) } } } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } @@ -1113,7 +1113,7 @@ static int gpencil_stroke_reset_vertex_color_exec(bContext *C, wmOperator *op) changed = true; } - /* if not multiedit, exit loop*/ + /* If not multi-edit, exit loop. */ if (!is_multiedit) { break; } diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index a05cc3c4dbd..16605b6c634 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -910,7 +910,7 @@ static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * brush region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { @@ -1107,7 +1107,7 @@ static bool gpencil_vertexpaint_brush_do_frame(bContext *C, break; } } - /* Clear the selected array, but keep the memory allocation.*/ + /* Clear the selected array, but keep the memory allocation. */ gso->pbuffer = gpencil_select_buffer_ensure( gso->pbuffer, &gso->pbuffer_size, &gso->pbuffer_used, true); @@ -1335,7 +1335,7 @@ static int gpencil_vertexpaint_brush_modal(bContext *C, wmOperator *op, const wm /* The operator can be in 2 states: Painting and Idling */ if (gso->is_painting) { - /* Painting */ + /* Painting. */ switch (event->type) { /* Mouse Move = Apply somewhere else */ case MOUSEMOVE: diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c index a3e5ece5862..d14322e12b5 100644 --- a/source/blender/editors/gpencil/gpencil_weight_paint.c +++ b/source/blender/editors/gpencil/gpencil_weight_paint.c @@ -252,7 +252,7 @@ static bool brush_draw_apply(tGP_BrushWeightpaintData *gso, } } else { - bDeformGroup *defgroup = BLI_findlink(&gso->object->defbase, gso->vrgroup); + bDeformGroup *defgroup = BLI_findlink(&gso->gpd->vertex_group_names, gso->vrgroup); if (defgroup->flag & DG_LOCK_WEIGHT) { return false; } @@ -308,8 +308,8 @@ static bool gpencil_weightpaint_brush_init(bContext *C, wmOperator *op) gso->scene = scene; gso->object = ob; if (ob) { - gso->vrgroup = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, gso->vrgroup)) { + gso->vrgroup = gso->gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gso->gpd->vertex_group_names, gso->vrgroup)) { gso->vrgroup = -1; } } @@ -448,7 +448,7 @@ static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * brush region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { @@ -555,7 +555,7 @@ static bool gpencil_weightpaint_brush_do_frame(bContext *C, break; } } - /* Clear the selected array, but keep the memory allocation.*/ + /* Clear the selected array, but keep the memory allocation. */ gso->pbuffer = gpencil_select_buffer_ensure( gso->pbuffer, &gso->pbuffer_size, &gso->pbuffer_used, true); @@ -774,7 +774,7 @@ static int gpencil_weightpaint_brush_modal(bContext *C, wmOperator *op, const wm /* The operator can be in 2 states: Painting and Idling */ if (gso->is_painting) { - /* Painting */ + /* Painting. */ switch (event->type) { /* Mouse Move = Apply somewhere else */ case MOUSEMOVE: diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 4b440aa7367..5cf2a9c9dd0 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -177,9 +177,9 @@ typedef struct bAnimListElem { * action's ID. But if this is a f-curve which is a driver, then the owner * is set to, for example, object. * - * Note, that this is different from id above. The id above will be set to - * an object if the f-curve is coming from action associated with that - * object. */ + * NOTE: this is different from id above. The id above will be set to + * an object if the f-curve is coming from action associated with that object. + */ struct ID *fcurve_owner_id; /** diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h index 8015a665970..44c5897d3a3 100644 --- a/source/blender/editors/include/ED_curve.h +++ b/source/blender/editors/include/ED_curve.h @@ -60,21 +60,21 @@ bool ED_curve_editnurb_select_pick( struct Nurb *ED_curve_add_nurbs_primitive( struct bContext *C, struct Object *obedit, float mat[4][4], int type, int newob); -bool ED_curve_nurb_select_check(struct View3D *v3d, struct Nurb *nu); -int ED_curve_nurb_select_count(struct View3D *v3d, struct Nurb *nu); +bool ED_curve_nurb_select_check(const struct View3D *v3d, const struct Nurb *nu); +int ED_curve_nurb_select_count(const struct View3D *v3d, const struct Nurb *nu); bool ED_curve_nurb_select_all(const struct Nurb *nu); bool ED_curve_nurb_deselect_all(const struct Nurb *nu); int ED_curve_join_objects_exec(struct bContext *C, struct wmOperator *op); /* editcurve_select.c */ -bool ED_curve_select_check(struct View3D *v3d, struct EditNurb *editnurb); +bool ED_curve_select_check(const struct View3D *v3d, const struct EditNurb *editnurb); bool ED_curve_deselect_all(struct EditNurb *editnurb); bool ED_curve_deselect_all_multi_ex(struct Base **bases, int bases_len); bool ED_curve_deselect_all_multi(struct bContext *C); bool ED_curve_select_all(struct EditNurb *editnurb); bool ED_curve_select_swap(struct EditNurb *editnurb, bool hide_handles); -int ED_curve_select_count(struct View3D *v3d, struct EditNurb *editnurb); +int ED_curve_select_count(const struct View3D *v3d, const struct EditNurb *editnurb); /* editcurve_undo.c */ void ED_curve_undosys_type(struct UndoType *ut); diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h index 40b0a8d96b1..59e0e014933 100644 --- a/source/blender/editors/include/ED_datafiles.h +++ b/source/blender/editors/include/ED_datafiles.h @@ -30,275 +30,275 @@ extern "C" { /* Datafiles embedded in Blender */ extern int datatoc_startup_blend_size; -extern char datatoc_startup_blend[]; +extern const char datatoc_startup_blend[]; extern int datatoc_preview_blend_size; -extern char datatoc_preview_blend[]; +extern const char datatoc_preview_blend[]; extern int datatoc_preview_grease_pencil_blend_size; -extern char datatoc_preview_grease_pencil_blend[]; +extern const char datatoc_preview_grease_pencil_blend[]; extern int datatoc_blender_icons16_png_size; -extern char datatoc_blender_icons16_png[]; +extern const char datatoc_blender_icons16_png[]; extern int datatoc_blender_icons32_png_size; -extern char datatoc_blender_icons32_png[]; +extern const char datatoc_blender_icons32_png[]; extern int datatoc_prvicons_png_size; -extern char datatoc_prvicons_png[]; +extern const char datatoc_prvicons_png[]; extern int datatoc_alert_icons_png_size; -extern char datatoc_alert_icons_png[]; +extern const char datatoc_alert_icons_png[]; extern int datatoc_blender_logo_png_size; -extern char datatoc_blender_logo_png[]; +extern const char datatoc_blender_logo_png[]; extern int datatoc_splash_png_size; -extern char datatoc_splash_png[]; +extern const char datatoc_splash_png[]; extern int datatoc_bfont_pfb_size; -extern char datatoc_bfont_pfb[]; +extern const char datatoc_bfont_pfb[]; /* Brush icon datafiles */ /* TODO: this could be simplified by putting all * the brush icons in one file */ extern int datatoc_add_png_size; -extern char datatoc_add_png[]; +extern const char datatoc_add_png[]; extern int datatoc_blob_png_size; -extern char datatoc_blob_png[]; +extern const char datatoc_blob_png[]; extern int datatoc_blur_png_size; -extern char datatoc_blur_png[]; +extern const char datatoc_blur_png[]; extern int datatoc_clay_png_size; -extern char datatoc_clay_png[]; +extern const char datatoc_clay_png[]; extern int datatoc_claystrips_png_size; -extern char datatoc_claystrips_png[]; +extern const char datatoc_claystrips_png[]; extern int datatoc_clone_png_size; -extern char datatoc_clone_png[]; +extern const char datatoc_clone_png[]; extern int datatoc_crease_png_size; -extern char datatoc_crease_png[]; +extern const char datatoc_crease_png[]; extern int datatoc_darken_png_size; -extern char datatoc_darken_png[]; +extern const char datatoc_darken_png[]; extern int datatoc_draw_png_size; -extern char datatoc_draw_png[]; +extern const char datatoc_draw_png[]; extern int datatoc_fill_png_size; -extern char datatoc_fill_png[]; +extern const char datatoc_fill_png[]; extern int datatoc_flatten_png_size; -extern char datatoc_flatten_png[]; +extern const char datatoc_flatten_png[]; extern int datatoc_grab_png_size; -extern char datatoc_grab_png[]; +extern const char datatoc_grab_png[]; extern int datatoc_inflate_png_size; -extern char datatoc_inflate_png[]; +extern const char datatoc_inflate_png[]; extern int datatoc_layer_png_size; -extern char datatoc_layer_png[]; +extern const char datatoc_layer_png[]; extern int datatoc_lighten_png_size; -extern char datatoc_lighten_png[]; +extern const char datatoc_lighten_png[]; extern int datatoc_mask_png_size; -extern char datatoc_mask_png[]; +extern const char datatoc_mask_png[]; extern int datatoc_mix_png_size; -extern char datatoc_mix_png[]; +extern const char datatoc_mix_png[]; extern int datatoc_multiply_png_size; -extern char datatoc_multiply_png[]; +extern const char datatoc_multiply_png[]; extern int datatoc_nudge_png_size; -extern char datatoc_nudge_png[]; +extern const char datatoc_nudge_png[]; extern int datatoc_pinch_png_size; -extern char datatoc_pinch_png[]; +extern const char datatoc_pinch_png[]; extern int datatoc_scrape_png_size; -extern char datatoc_scrape_png[]; +extern const char datatoc_scrape_png[]; extern int datatoc_smear_png_size; -extern char datatoc_smear_png[]; +extern const char datatoc_smear_png[]; extern int datatoc_smooth_png_size; -extern char datatoc_smooth_png[]; +extern const char datatoc_smooth_png[]; extern int datatoc_snake_hook_png_size; -extern char datatoc_snake_hook_png[]; +extern const char datatoc_snake_hook_png[]; extern int datatoc_soften_png_size; -extern char datatoc_soften_png[]; +extern const char datatoc_soften_png[]; extern int datatoc_subtract_png_size; -extern char datatoc_subtract_png[]; +extern const char datatoc_subtract_png[]; extern int datatoc_texdraw_png_size; -extern char datatoc_texdraw_png[]; +extern const char datatoc_texdraw_png[]; extern int datatoc_texfill_png_size; -extern char datatoc_texfill_png[]; +extern const char datatoc_texfill_png[]; extern int datatoc_texmask_png_size; -extern char datatoc_texmask_png[]; +extern const char datatoc_texmask_png[]; extern int datatoc_thumb_png_size; -extern char datatoc_thumb_png[]; +extern const char datatoc_thumb_png[]; extern int datatoc_twist_png_size; -extern char datatoc_twist_png[]; +extern const char datatoc_twist_png[]; extern int datatoc_vertexdraw_png_size; -extern char datatoc_vertexdraw_png[]; +extern const char datatoc_vertexdraw_png[]; /* Matcap files */ extern int datatoc_mc01_jpg_size; -extern char datatoc_mc01_jpg[]; +extern const char datatoc_mc01_jpg[]; extern int datatoc_mc02_jpg_size; -extern char datatoc_mc02_jpg[]; +extern const char datatoc_mc02_jpg[]; extern int datatoc_mc03_jpg_size; -extern char datatoc_mc03_jpg[]; +extern const char datatoc_mc03_jpg[]; extern int datatoc_mc04_jpg_size; -extern char datatoc_mc04_jpg[]; +extern const char datatoc_mc04_jpg[]; extern int datatoc_mc05_jpg_size; -extern char datatoc_mc05_jpg[]; +extern const char datatoc_mc05_jpg[]; extern int datatoc_mc06_jpg_size; -extern char datatoc_mc06_jpg[]; +extern const char datatoc_mc06_jpg[]; extern int datatoc_mc07_jpg_size; -extern char datatoc_mc07_jpg[]; +extern const char datatoc_mc07_jpg[]; extern int datatoc_mc08_jpg_size; -extern char datatoc_mc08_jpg[]; +extern const char datatoc_mc08_jpg[]; extern int datatoc_mc09_jpg_size; -extern char datatoc_mc09_jpg[]; +extern const char datatoc_mc09_jpg[]; extern int datatoc_mc10_jpg_size; -extern char datatoc_mc10_jpg[]; +extern const char datatoc_mc10_jpg[]; extern int datatoc_mc11_jpg_size; -extern char datatoc_mc11_jpg[]; +extern const char datatoc_mc11_jpg[]; extern int datatoc_mc12_jpg_size; -extern char datatoc_mc12_jpg[]; +extern const char datatoc_mc12_jpg[]; extern int datatoc_mc13_jpg_size; -extern char datatoc_mc13_jpg[]; +extern const char datatoc_mc13_jpg[]; extern int datatoc_mc14_jpg_size; -extern char datatoc_mc14_jpg[]; +extern const char datatoc_mc14_jpg[]; extern int datatoc_mc15_jpg_size; -extern char datatoc_mc15_jpg[]; +extern const char datatoc_mc15_jpg[]; extern int datatoc_mc16_jpg_size; -extern char datatoc_mc16_jpg[]; +extern const char datatoc_mc16_jpg[]; extern int datatoc_mc17_jpg_size; -extern char datatoc_mc17_jpg[]; +extern const char datatoc_mc17_jpg[]; extern int datatoc_mc18_jpg_size; -extern char datatoc_mc18_jpg[]; +extern const char datatoc_mc18_jpg[]; extern int datatoc_mc19_jpg_size; -extern char datatoc_mc19_jpg[]; +extern const char datatoc_mc19_jpg[]; extern int datatoc_mc20_jpg_size; -extern char datatoc_mc20_jpg[]; +extern const char datatoc_mc20_jpg[]; extern int datatoc_mc21_jpg_size; -extern char datatoc_mc21_jpg[]; +extern const char datatoc_mc21_jpg[]; extern int datatoc_mc22_jpg_size; -extern char datatoc_mc22_jpg[]; +extern const char datatoc_mc22_jpg[]; extern int datatoc_mc23_jpg_size; -extern char datatoc_mc23_jpg[]; +extern const char datatoc_mc23_jpg[]; extern int datatoc_mc24_jpg_size; -extern char datatoc_mc24_jpg[]; +extern const char datatoc_mc24_jpg[]; /* grease pencil sculpt brushes files */ extern int datatoc_gp_brush_smooth_png_size; -extern char datatoc_gp_brush_smooth_png[]; +extern const char datatoc_gp_brush_smooth_png[]; extern int datatoc_gp_brush_thickness_png_size; -extern char datatoc_gp_brush_thickness_png[]; +extern const char datatoc_gp_brush_thickness_png[]; extern int datatoc_gp_brush_strength_png_size; -extern char datatoc_gp_brush_strength_png[]; +extern const char datatoc_gp_brush_strength_png[]; extern int datatoc_gp_brush_grab_png_size; -extern char datatoc_gp_brush_grab_png[]; +extern const char datatoc_gp_brush_grab_png[]; extern int datatoc_gp_brush_push_png_size; -extern char datatoc_gp_brush_push_png[]; +extern const char datatoc_gp_brush_push_png[]; extern int datatoc_gp_brush_twist_png_size; -extern char datatoc_gp_brush_twist_png[]; +extern const char datatoc_gp_brush_twist_png[]; extern int datatoc_gp_brush_pinch_png_size; -extern char datatoc_gp_brush_pinch_png[]; +extern const char datatoc_gp_brush_pinch_png[]; extern int datatoc_gp_brush_randomize_png_size; -extern char datatoc_gp_brush_randomize_png[]; +extern const char datatoc_gp_brush_randomize_png[]; extern int datatoc_gp_brush_clone_png_size; -extern char datatoc_gp_brush_clone_png[]; +extern const char datatoc_gp_brush_clone_png[]; extern int datatoc_gp_brush_weight_png_size; -extern char datatoc_gp_brush_weight_png[]; +extern const char datatoc_gp_brush_weight_png[]; extern int datatoc_gp_brush_pencil_png_size; -extern char datatoc_gp_brush_pencil_png[]; +extern const char datatoc_gp_brush_pencil_png[]; extern int datatoc_gp_brush_pen_png_size; -extern char datatoc_gp_brush_pen_png[]; +extern const char datatoc_gp_brush_pen_png[]; extern int datatoc_gp_brush_ink_png_size; -extern char datatoc_gp_brush_ink_png[]; +extern const char datatoc_gp_brush_ink_png[]; extern int datatoc_gp_brush_inknoise_png_size; -extern char datatoc_gp_brush_inknoise_png[]; +extern const char datatoc_gp_brush_inknoise_png[]; extern int datatoc_gp_brush_block_png_size; -extern char datatoc_gp_brush_block_png[]; +extern const char datatoc_gp_brush_block_png[]; extern int datatoc_gp_brush_marker_png_size; -extern char datatoc_gp_brush_marker_png[]; +extern const char datatoc_gp_brush_marker_png[]; extern int datatoc_gp_brush_fill_png_size; -extern char datatoc_gp_brush_fill_png[]; +extern const char datatoc_gp_brush_fill_png[]; extern int datatoc_gp_brush_airbrush_png_size; -extern char datatoc_gp_brush_airbrush_png[]; +extern const char datatoc_gp_brush_airbrush_png[]; extern int datatoc_gp_brush_chisel_png_size; -extern char datatoc_gp_brush_chisel_png[]; +extern const char datatoc_gp_brush_chisel_png[]; extern int datatoc_gp_brush_erase_soft_png_size; -extern char datatoc_gp_brush_erase_soft_png[]; +extern const char datatoc_gp_brush_erase_soft_png[]; extern int datatoc_gp_brush_erase_hard_png_size; -extern char datatoc_gp_brush_erase_hard_png[]; +extern const char datatoc_gp_brush_erase_hard_png[]; extern int datatoc_gp_brush_erase_stroke_png_size; -extern char datatoc_gp_brush_erase_stroke_png[]; +extern const char datatoc_gp_brush_erase_stroke_png[]; #ifdef __cplusplus } diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index 8118e3c6c69..e57e2316d93 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -66,7 +66,7 @@ typedef struct FileAttributeColumn { } FileAttributeColumn; typedef struct FileLayout { - /* view settings - XXX - move into own struct */ + /* view settings - XXX: move into own struct. */ int offset_top; /* Height of the header for the different FileAttributeColumn's. */ int attribute_column_header_h; @@ -136,13 +136,9 @@ void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y); void ED_operatormacros_file(void); -void ED_fileselect_clear(struct wmWindowManager *wm, - struct Scene *owner_scene, - struct SpaceFile *sfile); +void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile); -void ED_fileselect_exit(struct wmWindowManager *wm, - struct Scene *owner_scene, - struct SpaceFile *sfile); +void ED_fileselect_exit(struct wmWindowManager *wm, struct SpaceFile *sfile); bool ED_fileselect_is_asset_browser(const struct SpaceFile *sfile); struct ID *ED_fileselect_active_asset_get(const struct SpaceFile *sfile); @@ -166,7 +162,7 @@ int ED_file_icon(const struct FileDirEntry *file); void ED_file_read_bookmarks(void); -void ED_file_change_dir_ex(struct bContext *C, struct bScreen *screen, struct ScrArea *area); +void ED_file_change_dir_ex(struct bContext *C, struct ScrArea *area); void ED_file_change_dir(struct bContext *C); void ED_file_path_button(struct bScreen *screen, diff --git a/source/blender/editors/include/ED_gizmo_library.h b/source/blender/editors/include/ED_gizmo_library.h index 571519e52f7..357d5e10fa7 100644 --- a/source/blender/editors/include/ED_gizmo_library.h +++ b/source/blender/editors/include/ED_gizmo_library.h @@ -275,7 +275,7 @@ void ED_gizmotypes_snap_3d_flag_clear(struct wmGizmo *gz, eSnapGizmo flag); bool ED_gizmotypes_snap_3d_flag_test(struct wmGizmo *gz, eSnapGizmo flag); bool ED_gizmotypes_snap_3d_invert_snap_get(struct wmGizmo *gz); -bool ED_gizmotypes_snap_3d_is_enabled(struct wmGizmo *gz); +bool ED_gizmotypes_snap_3d_is_enabled(const struct wmGizmo *gz); short ED_gizmotypes_snap_3d_update(struct wmGizmo *gz, struct Depsgraph *depsgraph, diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index bad080e1609..8a8d91a570c 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -189,7 +189,7 @@ bool ED_gpencil_layer_frames_looper(struct bGPDlayer *gpl, bool (*gpf_cb)(struct bGPDframe *, struct Scene *)); void ED_gpencil_layer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, bool onlysel); -bool ED_gpencil_layer_frame_select_check(struct bGPDlayer *gpl); +bool ED_gpencil_layer_frame_select_check(const struct bGPDlayer *gpl); void ED_gpencil_layer_frame_select_set(struct bGPDlayer *gpl, short mode); void ED_gpencil_layer_frames_select_box(struct bGPDlayer *gpl, float min, @@ -251,6 +251,13 @@ void ED_gpencil_brush_draw_eraser(struct Brush *brush, int x, int y); /* ----------- Add Primitive Utilities -------------- */ +/* Number of values defining each point in the built-in data buffers for primitives. */ +#define GP_PRIM_DATABUF_SIZE 5 +void ED_gpencil_stroke_init_data(struct bGPDstroke *gps, + const float *array, + const int totpoints, + const float mat[4][4]); + void ED_gpencil_create_blank(struct bContext *C, struct Object *ob, float mat[4][4]); void ED_gpencil_create_monkey(struct bContext *C, struct Object *ob, float mat[4][4]); void ED_gpencil_create_stroke(struct bContext *C, struct Object *ob, float mat[4][4]); @@ -364,23 +371,23 @@ void ED_gpencil_init_random_settings(struct Brush *brush, const int mval[2], struct GpRandomSettings *random_settings); -bool ED_gpencil_stroke_check_collision(struct GP_SpaceConversion *gsc, +bool ED_gpencil_stroke_check_collision(const struct GP_SpaceConversion *gsc, struct bGPDstroke *gps, const float mouse[2], const int radius, const float diff_mat[4][4]); -bool ED_gpencil_stroke_point_is_inside(struct bGPDstroke *gps, - struct GP_SpaceConversion *gsc, - int mouse[2], +bool ED_gpencil_stroke_point_is_inside(const struct bGPDstroke *gps, + const struct GP_SpaceConversion *gsc, + const int mouse[2], const float diff_mat[4][4]); -void ED_gpencil_projected_2d_bound_box(struct GP_SpaceConversion *gsc, - struct bGPDstroke *gps, +void ED_gpencil_projected_2d_bound_box(const struct GP_SpaceConversion *gsc, + const 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, + const struct GP_SpaceConversion *gsc, struct bGPDlayer *gpl, struct bGPDframe *gpf, struct bGPDstroke *gps, diff --git a/source/blender/editors/include/ED_info.h b/source/blender/editors/include/ED_info.h index 9ac6b6c1085..dde26c072d0 100644 --- a/source/blender/editors/include/ED_info.h +++ b/source/blender/editors/include/ED_info.h @@ -27,9 +27,10 @@ extern "C" { #endif struct Main; +struct wmWindowManager; /* info_stats.c */ -void ED_info_stats_clear(struct ViewLayer *view_layer); +void ED_info_stats_clear(struct wmWindowManager *wm, struct ViewLayer *view_layer); const char *ED_info_statusbar_string(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer); @@ -41,6 +42,7 @@ const char *ED_info_statistics_string(struct Main *bmain, void ED_info_draw_stats(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, + struct View3D *v3d_local, int x, int *y, int height); diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index cf90a21f799..e29ff3ed890 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -160,7 +160,7 @@ typedef struct KeyframeEditData { /* generic properties/data access */ /** temp list for storing custom list of data to check */ ListBase list; - /** pointer to current scene - many tools need access to cfra/etc. */ + /** pointer to current scene - many tools need access to cfra/etc. */ struct Scene *scene; /** pointer to custom data - usually 'Object' but also 'rectf', but could be other types too */ void *data; diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 179c9d5b30d..673f629d6ef 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -434,7 +434,7 @@ void ANIM_copy_as_driver(struct ID *target_id, const char *target_path, const ch /* check if auto-keyframing is enabled (per scene takes precedence) */ #define IS_AUTOKEY_ON(scene) \ ((scene) ? ((scene)->toolsettings->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON)) -/* check the mode for auto-keyframing (per scene takes precedence) */ +/* Check the mode for auto-keyframing (per scene takes precedence). */ #define IS_AUTOKEY_MODE(scene, mode) \ ((scene) ? ((scene)->toolsettings->autokey_mode == AUTOKEY_MODE_##mode) : \ (U.autokey_mode == AUTOKEY_MODE_##mode)) @@ -452,7 +452,7 @@ bool autokeyframe_cfra_can_key(const struct Scene *scene, struct ID *id); /* Lesser Keyframe Checking API call: * - Used for the buttons to check for keyframes... */ -bool fcurve_frame_has_keyframe(struct FCurve *fcu, float frame, short filter); +bool fcurve_frame_has_keyframe(const struct FCurve *fcu, float frame, short filter); /* Lesser Keyframe Checking API call: * - Returns whether the current value of a given property differs from the interpolated value. @@ -468,7 +468,7 @@ bool fcurve_is_changed(struct PointerRNA ptr, * Checks whether a keyframe exists for the given ID-block one the given frame. * - It is recommended to call this method over the other keyframe-checkers directly, * in case some detail of the implementation changes... - * - frame: the value of this is quite often result of #BKE_scene_frame_get() + * - frame: the value of this is quite often result of #BKE_scene_ctime_get() */ bool id_frame_has_keyframe(struct ID *id, float frame, short filter); diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 247911bdc55..c2fdbc160de 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -100,7 +100,7 @@ bool ED_masklayer_frames_looper(struct MaskLayer *mask_layer, struct Scene *)); void ED_masklayer_make_cfra_list(struct MaskLayer *mask_layer, ListBase *elems, bool onlysel); -bool ED_masklayer_frame_select_check(struct MaskLayer *mask_layer); +bool ED_masklayer_frame_select_check(const struct MaskLayer *mask_layer); void ED_masklayer_frame_select_set(struct MaskLayer *mask_layer, short mode); void ED_masklayer_frames_select_box(struct MaskLayer *mask_layer, float min, diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index b8e9f6e8871..2b73194afb2 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -27,6 +27,8 @@ extern "C" { #endif +#include "BLI_compiler_attrs.h" + struct ARegion; struct BMBVHTree; struct BMEdge; @@ -36,6 +38,7 @@ struct BMFace; struct BMLoop; struct BMVert; struct BMesh; +struct BMeshNormalsUpdate_Params; struct Base; struct Depsgraph; struct ID; @@ -76,19 +79,21 @@ struct BMFace *EDBM_verts_mirror_get_face(struct BMEditMesh *em, struct BMFace * void EDBM_verts_mirror_cache_clear(struct BMEditMesh *em, struct BMVert *v); void EDBM_verts_mirror_cache_end(struct BMEditMesh *em); +void EDBM_mesh_normals_update_ex(struct BMEditMesh *em, + const struct BMeshNormalsUpdate_Params *params); void EDBM_mesh_normals_update(struct BMEditMesh *em); void EDBM_mesh_clear(struct BMEditMesh *em); void EDBM_selectmode_to_scene(struct bContext *C); void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index); -void EDBM_mesh_free(struct BMEditMesh *em); +void EDBM_mesh_free_data(struct BMEditMesh *em); void EDBM_mesh_load_ex(struct Main *bmain, struct Object *ob, bool free_data); void EDBM_mesh_load(struct Main *bmain, struct Object *ob); /* flushes based on the current select mode. if in vertex select mode, * verts select/deselect edges and faces, if in edge select mode, * edges select/deselect faces and vertices, and in face select mode faces select/deselect - * edges and vertices.*/ + * edges and vertices. */ void EDBM_select_more(struct BMEditMesh *em, const bool use_face_step); void EDBM_select_less(struct BMEditMesh *em, const bool use_face_step); @@ -103,7 +108,14 @@ bool EDBM_vert_color_check(struct BMEditMesh *em); bool EDBM_mesh_hide(struct BMEditMesh *em, bool swap); bool EDBM_mesh_reveal(struct BMEditMesh *em, bool select); -void EDBM_update_generic(struct Mesh *me, const bool do_tessellation, const bool is_destructive); +struct EDBMUpdate_Params { + uint calc_looptri : 1; + uint calc_normals : 1; + uint is_destructive : 1; +}; + +void EDBM_update(struct Mesh *me, const struct EDBMUpdate_Params *params); +void EDBM_update_extern(struct Mesh *me, const bool do_tessellation, const bool is_destructive); struct UvElementMap *BM_uv_element_map_create(struct BMesh *bm, const struct Scene *scene, @@ -445,12 +457,14 @@ typedef struct BMBackup { struct BMesh *bmcopy; } BMBackup; -/* save a copy of the bmesh for restoring later */ struct BMBackup EDBM_redo_state_store(struct BMEditMesh *em); /* restore a bmesh from backup */ -void EDBM_redo_state_restore(struct BMBackup, struct BMEditMesh *em, int recalctess); -/* delete the backup, optionally flushing it to an editmesh */ -void EDBM_redo_state_free(struct BMBackup *, struct BMEditMesh *em, int recalctess); +void EDBM_redo_state_restore(struct BMBackup *backup, struct BMEditMesh *em, bool recalc_looptri) + ATTR_NONNULL(1, 2); +void EDBM_redo_state_restore_and_free(struct BMBackup *backup, + struct BMEditMesh *em, + bool recalc_looptri) ATTR_NONNULL(1, 2); +void EDBM_redo_state_free(struct BMBackup *backup) ATTR_NONNULL(1); /* *** meshtools.c *** */ int ED_mesh_join_objects_exec(struct bContext *C, struct wmOperator *op); @@ -471,9 +485,8 @@ int ED_mesh_mirror_spatial_table_lookup(struct Object *ob, void ED_mesh_mirror_topo_table_begin(struct Object *ob, struct Mesh *me_eval); void ED_mesh_mirror_topo_table_end(struct Object *ob); -/* retrieves mirrored cache vert, or NULL if there isn't one. - * note: calling this without ensuring the mirror cache state - * is bad.*/ +/* Retrieves mirrored cache vert, or NULL if there isn't one. + * NOTE: calling this without ensuring the mirror cache state is bad. */ int mesh_get_x_mirror_vert(struct Object *ob, struct Mesh *me_eval, int index, diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 67a50b83bd6..058d4fa91a3 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -40,6 +40,7 @@ struct bNodeSocketType; struct bNodeTree; struct bNodeTreeType; struct bNodeType; +struct SpaceNode; typedef enum { NODE_TOP = 1, @@ -49,6 +50,11 @@ typedef enum { } NodeBorder; #define NODE_GRID_STEPS 5 +#define NODE_EDGE_PAN_INSIDE_PAD 2 +#define NODE_EDGE_PAN_OUTSIDE_PAD 0 /* Disable clamping for node panning, use whole screen. */ +#define NODE_EDGE_PAN_SPEED_RAMP 1 +#define NODE_EDGE_PAN_MAX_SPEED 40 /* In UI units per second, slower than default. */ +#define NODE_EDGE_PAN_DELAY 1.0f /* space_node.c */ @@ -105,10 +111,11 @@ bool ED_node_is_geometry(struct SpaceNode *snode); void ED_node_shader_default(const struct bContext *C, struct ID *id); void ED_node_composit_default(const struct bContext *C, struct Scene *scene); void ED_node_texture_default(const struct bContext *C, struct Tex *tex); -bool ED_node_select_check(ListBase *lb); +bool ED_node_select_check(const ListBase *lb); void ED_node_select_all(ListBase *lb, int action); void ED_node_post_apply_transform(struct bContext *C, struct bNodeTree *ntree); void ED_node_set_active(struct Main *bmain, + struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node, bool *r_active_texture_changed); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 6f88ab4253a..888dcd9d428 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -62,7 +62,8 @@ struct Object *ED_object_active_context(const struct bContext *C); void ED_collection_hide_menu_draw(const struct bContext *C, struct uiLayout *layout); Object **ED_object_array_in_mode_or_selected(struct bContext *C, - bool (*filter_fn)(struct Object *ob, void *user_data), + bool (*filter_fn)(const struct Object *ob, + void *user_data), void *filter_user_data, uint *r_objects_len); @@ -295,12 +296,12 @@ void ED_object_add_mesh_props(struct wmOperatorType *ot); bool ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, const char view_align_axis, - float loc[3], - float rot[3], - float scale[3], - bool *enter_editmode, - unsigned short *local_view_bits, - bool *is_view_aligned); + float r_loc[3], + float r_rot[3], + float r_scale[3], + bool *r_enter_editmode, + unsigned short *r_local_view_bits, + bool *r_is_view_aligned); struct Object *ED_object_add_type_with_obdata(struct bContext *C, const int type, @@ -387,7 +388,7 @@ void ED_object_mode_generic_exit(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); -bool ED_object_mode_generic_has_data(struct Depsgraph *depsgraph, struct Object *ob); +bool ED_object_mode_generic_has_data(struct Depsgraph *depsgraph, const struct Object *ob); void ED_object_posemode_set_for_weight_paint(struct bContext *C, struct Main *bmain, diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h index e84298bd9c2..6d0172e724a 100644 --- a/source/blender/editors/include/ED_particle.h +++ b/source/blender/editors/include/ED_particle.h @@ -34,6 +34,7 @@ struct ParticleSystem; struct Scene; struct UndoType; struct ViewLayer; +struct wmGenericUserData; struct bContext; struct rcti; @@ -68,7 +69,11 @@ void PE_update_object(struct Depsgraph *depsgraph, bool PE_mouse_particles( struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); bool PE_box_select(struct bContext *C, const struct rcti *rect, const int sel_op); -bool PE_circle_select(struct bContext *C, const int sel_op, const int mval[2], float rad); +bool PE_circle_select(struct bContext *C, + struct wmGenericUserData *wm_userdata, + const int sel_op, + const int mval[2], + float rad); int PE_lasso_select(struct bContext *C, const int mcoords[][2], const int mcoords_len, diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index bdd7ec571dc..823050b46f7 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -215,7 +215,7 @@ void ED_screen_restore_temp_type(struct bContext *C, ScrArea *area); ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *area, int type); void ED_screen_full_prevspace(struct bContext *C, ScrArea *area); void ED_screen_full_restore(struct bContext *C, ScrArea *area); -ScrArea *ED_screen_state_maximized_create(struct bContext *C); +bScreen *ED_screen_state_maximized_create(struct bContext *C); struct ScrArea *ED_screen_state_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *area, @@ -317,6 +317,7 @@ bool ED_operator_animview_active(struct bContext *C); bool ED_operator_outliner_active(struct bContext *C); bool ED_operator_outliner_active_no_editobject(struct bContext *C); bool ED_operator_file_active(struct bContext *C); +bool ED_operator_spreadsheet_active(struct bContext *C); bool ED_operator_action_active(struct bContext *C); bool ED_operator_buttons_active(struct bContext *C); bool ED_operator_node_active(struct bContext *C); @@ -354,6 +355,7 @@ bool ED_operator_uvedit(struct bContext *C); bool ED_operator_uvedit_space_image(struct bContext *C); bool ED_operator_uvmap(struct bContext *C); bool ED_operator_posemode_exclusive(struct bContext *C); +bool ED_operator_object_active_local_editable_posemode_exclusive(struct bContext *C); bool ED_operator_posemode_context(struct bContext *C); bool ED_operator_posemode(struct bContext *C); bool ED_operator_posemode_local(struct bContext *C); diff --git a/source/blender/editors/include/ED_sequencer.h b/source/blender/editors/include/ED_sequencer.h index 11eff2d583b..606b4c9cad0 100644 --- a/source/blender/editors/include/ED_sequencer.h +++ b/source/blender/editors/include/ED_sequencer.h @@ -42,6 +42,8 @@ bool ED_space_sequencer_maskedit_poll(struct bContext *C); bool ED_space_sequencer_check_show_imbuf(struct SpaceSeq *sseq); bool ED_space_sequencer_check_show_strip(struct SpaceSeq *sseq); +bool ED_space_sequencer_has_playback_animation(const struct SpaceSeq *sseq, + const struct Scene *scene); void ED_operatormacros_sequencer(void); diff --git a/source/blender/editors/include/ED_spreadsheet.h b/source/blender/editors/include/ED_spreadsheet.h index 3a07b1b9d4b..ff77135a51c 100644 --- a/source/blender/editors/include/ED_spreadsheet.h +++ b/source/blender/editors/include/ED_spreadsheet.h @@ -21,6 +21,9 @@ struct SpaceSpreadsheet; struct SpaceNode; struct ID; struct bNode; +struct Main; +struct bContext; +struct Object; #ifdef __cplusplus extern "C" { @@ -29,14 +32,25 @@ extern "C" { struct SpreadsheetContext *ED_spreadsheet_context_new(int type); void ED_spreadsheet_context_free(struct SpreadsheetContext *context); void ED_spreadsheet_context_path_clear(struct SpaceSpreadsheet *sspreadsheet); -void ED_spreadsheet_context_path_update_tag(struct SpaceSpreadsheet *sspreadsheet); -uint64_t ED_spreadsheet_context_path_hash(struct SpaceSpreadsheet *sspreadsheet); +bool ED_spreadsheet_context_path_update_tag(struct SpaceSpreadsheet *sspreadsheet); +uint64_t ED_spreadsheet_context_path_hash(const struct SpaceSpreadsheet *sspreadsheet); -struct ID *ED_spreadsheet_get_current_id(struct SpaceSpreadsheet *sspreadsheet); +struct ID *ED_spreadsheet_get_current_id(const struct SpaceSpreadsheet *sspreadsheet); -void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsheet, - struct SpaceNode *snode, - struct bNode *node); +void ED_spreadsheet_context_path_set_geometry_node(struct SpaceSpreadsheet *sspreadsheet, + struct SpaceNode *snode, + struct bNode *node); +void ED_spreadsheet_context_paths_set_geometry_node(struct Main *bmain, + struct SpaceNode *snode, + struct bNode *node); +void ED_spreadsheet_context_path_set_evaluated_object(struct SpaceSpreadsheet *sspreadsheet, + struct Object *object); + +void ED_spreadsheet_context_path_guess(const struct bContext *C, + struct SpaceSpreadsheet *sspreadsheet); +bool ED_spreadsheet_context_path_is_active(const struct bContext *C, + struct SpaceSpreadsheet *sspreadsheet); +bool ED_spreadsheet_context_path_exists(struct Main *bmain, struct SpaceSpreadsheet *sspreadsheet); #ifdef __cplusplus } diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h index ed1ec96a13f..059277e1466 100644 --- a/source/blender/editors/include/ED_undo.h +++ b/source/blender/editors/include/ED_undo.h @@ -53,7 +53,7 @@ void ED_OT_undo_redo(struct wmOperatorType *ot); void ED_OT_undo_history(struct wmOperatorType *ot); int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op); -/* convenience since UI callbacks use this mostly*/ +/* Convenience since UI callbacks use this mostly. */ void ED_undo_operator_repeat_cb(struct bContext *C, void *arg_op, void *arg_unused); void ED_undo_operator_repeat_cb_evt(struct bContext *C, void *arg_op, int arg_unused); diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 4de97411059..ea3d921f2c5 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -42,6 +42,7 @@ struct SpaceImage; struct ToolSettings; struct ViewLayer; struct bNode; +struct bNodeTree; struct wmKeyConfig; /* uvedit_ops.c */ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 499f28beb60..2c958d282f9 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -90,8 +90,6 @@ typedef struct ViewDepths { short x, y; /* only for temp use for sub-rects, added to region->winx/y */ float *depths; double depth_range[2]; - - bool damaged; } ViewDepths; /* Rotate 3D cursor on placement. */ @@ -154,19 +152,20 @@ void ED_view3d_depth_override(struct Depsgraph *depsgraph, struct View3D *v3d, struct Object *obact, eV3DDepthOverrideMode mode, - bool update_cache); + struct ViewDepths **r_depths); +void ED_view3d_depths_free(ViewDepths *depths); bool ED_view3d_depth_read_cached(const ViewDepths *vd, const int mval[2], int margin, float *r_depth); -bool ED_view3d_depth_read_cached_normal(const ViewContext *vc, +bool ED_view3d_depth_read_cached_normal(const struct ARegion *region, + const ViewDepths *depths, const int mval[2], float r_normal[3]); -bool ED_view3d_depth_unproject(const struct ARegion *region, - const int mval[2], - const double depth, - float r_location_world[3]); -void ED_view3d_depth_tag_update(struct RegionView3D *rv3d); +bool ED_view3d_depth_unproject_v3(const struct ARegion *region, + const int mval[2], + const double depth, + float r_location_world[3]); /* Projection */ #define IS_CLIPPED 12000 @@ -196,12 +195,38 @@ typedef enum { V3D_PROJ_TEST_CLIP_NEAR = (1 << 2), V3D_PROJ_TEST_CLIP_FAR = (1 << 3), V3D_PROJ_TEST_CLIP_ZERO = (1 << 4), + /** + * Clip the contents of the data being iterated over. + * Currently this is only used to edges when projecting into screen space. + * + * Clamp the edge within the viewport limits defined by + * #V3D_PROJ_TEST_CLIP_WIN, #V3D_PROJ_TEST_CLIP_NEAR & #V3D_PROJ_TEST_CLIP_FAR. + * This resolves the problem of a visible edge having one of it's vertices + * behind the viewport. See: T32214. + * + * This is not default behavior as it may be important for the screen-space location + * of an edges vertex to represent that vertices location (instead of a location along the edge). + * + * \note Perspective views should enable #V3D_PROJ_TEST_CLIP_WIN along with + * #V3D_PROJ_TEST_CLIP_NEAR as the near-plane-clipped location of a point + * may become very large (even infinite) when projected into screen-space. + * Unless that point happens to coincide with the camera's point of view. + * + * Use #V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT instead of #V3D_PROJ_TEST_CLIP_CONTENT, + * to avoid accidentally enabling near clipping without clipping by window bounds. + */ + V3D_PROJ_TEST_CLIP_CONTENT = (1 << 5), } eV3DProjTest; #define V3D_PROJ_TEST_CLIP_DEFAULT \ (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) #define V3D_PROJ_TEST_ALL \ - (V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_FAR | V3D_PROJ_TEST_CLIP_ZERO) + (V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_FAR | V3D_PROJ_TEST_CLIP_ZERO | \ + V3D_PROJ_TEST_CLIP_CONTENT) + +#define V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT \ + (V3D_PROJ_TEST_CLIP_CONTENT | V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_FAR | \ + V3D_PROJ_TEST_CLIP_WIN) /* view3d_iterators.c */ @@ -341,6 +366,8 @@ float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3]); float ED_view3d_pixel_size_no_ui_scale(const struct RegionView3D *rv3d, const float co[3]); float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip); +float ED_view3d_calc_depth_for_comparison(const struct RegionView3D *rv3d, const float co[3]); + bool ED_view3d_clip_segment(const struct RegionView3D *rv3d, float ray_start[3], float ray_end[3]); bool ED_view3d_win_to_ray_clipped(struct Depsgraph *depsgraph, const struct ARegion *region, @@ -404,14 +431,19 @@ bool ED_view3d_win_to_segment_clipped(struct Depsgraph *depsgraph, float r_ray_end[3], const bool do_clip); void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, - struct Object *ob, + const struct Object *ob, float r_pmat[4][4]); void ED_view3d_ob_project_mat_get_from_obmat(const struct RegionView3D *rv3d, const float obmat[4][4], float r_pmat[4][4]); -void ED_view3d_project(const struct ARegion *region, const float world[3], float r_region_co[3]); -bool ED_view3d_unproject( +void ED_view3d_project_v3(const struct ARegion *region, + const float world[3], + float r_region_co[3]); +void ED_view3d_project_v2(const struct ARegion *region, + const float world[3], + float r_region_co[2]); +bool ED_view3d_unproject_v3( const struct ARegion *region, float regionx, float regiony, float regionz, float world[3]); /* end */ @@ -454,7 +486,7 @@ bool ED_view3d_calc_render_border(const struct Scene *scene, struct ARegion *region, struct rcti *rect); -void ED_view3d_clipping_calc_from_boundbox(float clip[6][4], +void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const struct BoundBox *clipbb, const bool is_flip); void ED_view3d_clipping_calc(struct BoundBox *bb, @@ -573,8 +605,8 @@ bool ED_view3d_area_user_region(const struct ScrArea *area, struct ARegion **r_region); bool ED_operator_rv3d_user_region_poll(struct bContext *C); -void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d); -void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d); +void ED_view3d_init_mats_rv3d(const struct Object *ob, struct RegionView3D *rv3d); +void ED_view3d_init_mats_rv3d_gl(const struct Object *ob, struct RegionView3D *rv3d); #ifdef DEBUG void ED_view3d_clear_mats_rv3d(struct RegionView3D *rv3d); void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d); @@ -690,7 +722,7 @@ float ED_view3d_grid_scale(const struct Scene *scene, void ED_view3d_grid_steps(const struct Scene *scene, struct View3D *v3d, struct RegionView3D *rv3d, - float *r_grid_steps); + float r_grid_steps[8]); float ED_view3d_grid_view_scale(struct Scene *scene, struct View3D *v3d, struct ARegion *region, diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index f0a4b3c462e..7ccdc49d291 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -21,7 +21,7 @@ * \ingroup editorui */ -/* Note: this is included multiple times with different #defines for DEF_ICON. */ +/* NOTE: this is included multiple times with different #defines for DEF_ICON. */ /* Auto define more specific types for places that do not need the distinction. */ #ifndef DEF_ICON_SCENE @@ -989,7 +989,7 @@ DEF_ICON_VECTOR(COLLECTION_COLOR_06) DEF_ICON_VECTOR(COLLECTION_COLOR_07) DEF_ICON_VECTOR(COLLECTION_COLOR_08) -/* Events */ +/* Events. */ DEF_ICON_COLOR(EVENT_A) DEF_ICON_COLOR(EVENT_B) DEF_ICON_COLOR(EVENT_C) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 338b12f7985..802c175492f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -58,6 +58,7 @@ struct bNodeTree; struct bScreen; struct rctf; struct rcti; +struct uiBlockInteraction_Handle; struct uiButSearch; struct uiFontStyle; struct uiList; @@ -129,12 +130,6 @@ enum { UI_DIR_ALL = UI_DIR_UP | UI_DIR_DOWN | UI_DIR_LEFT | UI_DIR_RIGHT, }; -#if 0 -/* uiBlock->autofill (not yet used) */ -# define UI_BLOCK_COLLUMNS 1 -# define UI_BLOCK_ROWS 2 -#endif - /** #uiBlock.flag (controls) */ enum { UI_BLOCK_LOOP = 1 << 0, @@ -251,7 +246,7 @@ enum { #define UI_PANEL_BOX_STYLE_MARGIN (U.widget_unit * 0.2f) /* but->drawflag - these flags should only affect how the button is drawn. */ -/* Note: currently, these flags _are not passed_ to the widget's state() or draw() functions +/* NOTE: currently, these flags *are not passed* to the widget's state() or draw() functions * (except for the 'align' ones)! */ enum { @@ -290,18 +285,14 @@ enum { /** Active right part of number button */ UI_BUT_ACTIVE_RIGHT = 1 << 22, - /* (also used by search buttons to enforce shortcut display for their items). */ - /** Button has shortcut text. */ - UI_BUT_HAS_SHORTCUT = 1 << 23, - /** Reverse order of consecutive off/on icons */ - UI_BUT_ICON_REVERSE = 1 << 24, + UI_BUT_ICON_REVERSE = 1 << 23, /** Value is animated, but the current value differs from the animated one. */ - UI_BUT_ANIMATED_CHANGED = 1 << 25, + UI_BUT_ANIMATED_CHANGED = 1 << 24, /* Draw the checkbox buttons inverted. */ - UI_BUT_CHECKBOX_INVERT = 1 << 26, + UI_BUT_CHECKBOX_INVERT = 1 << 25, }; /* scale fixed button widths by this to account for DPI */ @@ -322,8 +313,8 @@ typedef enum { UI_BUT_POIN_SHORT = 64, UI_BUT_POIN_INT = 96, UI_BUT_POIN_FLOAT = 128, - /* UI_BUT_POIN_FUNCTION = 192, */ /*UNUSED*/ - UI_BUT_POIN_BIT = 256, /* OR'd with a bit index*/ + // UI_BUT_POIN_FUNCTION = 192, /* UNUSED */ + UI_BUT_POIN_BIT = 256, /* OR'd with a bit index. */ } eButPointerType; /* requires (but->poin != NULL) */ @@ -390,6 +381,7 @@ typedef enum { /** Resize handle (resize uilist). */ UI_BTYPE_GRIP = 57 << 9, UI_BTYPE_DECORATOR = 58 << 9, + UI_BTYPE_DATASETROW = 59 << 9, } eButType; #define BUTTYPE (63 << 9) @@ -507,7 +499,6 @@ typedef void (*uiButSearchUpdateFn)(const struct bContext *C, const char *str, uiSearchItems *items, const bool is_first); -typedef void (*uiButSearchArgFreeFn)(void *arg); typedef bool (*uiButSearchContextMenuFn)(struct bContext *C, void *arg, void *active, @@ -520,10 +511,58 @@ typedef struct ARegion *(*uiButSearchTooltipFn)(struct bContext *C, /* Must return allocated string. */ typedef char *(*uiButToolTipFunc)(struct bContext *C, void *argN, const char *tip); -typedef int (*uiButPushedStateFunc)(struct bContext *C, void *arg); +typedef int (*uiButPushedStateFunc)(struct uiBut *but, const void *arg); typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event); +/* -------------------------------------------------------------------- */ +/** \name Custom Interaction + * + * Sometimes it's useful to create data that remains available + * while the user interacts with a button. + * + * A common case is dragging a number button or slider + * however this could be used in other cases too. + * \{ */ + +struct uiBlockInteraction_Params { + /** + * When true, this interaction is not modal + * (user clicking on a number button arrows or pasting a value for example). + */ + bool is_click; + /** + * Array of unique event ID's (values from #uiBut.retval). + * There may be more than one for multi-button editing (see #UI_BUT_DRAG_MULTI). + */ + int *unique_retval_ids; + uint unique_retval_ids_len; +}; + +/** Returns 'user_data', freed by #uiBlockInteractionEndFn. */ +typedef void *(*uiBlockInteractionBeginFn)(struct bContext *C, + const struct uiBlockInteraction_Params *params, + void *arg1); +typedef void (*uiBlockInteractionEndFn)(struct bContext *C, + const struct uiBlockInteraction_Params *params, + void *arg1, + void *user_data); +typedef void (*uiBlockInteractionUpdateFn)(struct bContext *C, + const struct uiBlockInteraction_Params *params, + void *arg1, + void *user_data); + +typedef struct uiBlockInteraction_CallbackData { + uiBlockInteractionBeginFn begin_fn; + uiBlockInteractionEndFn end_fn; + uiBlockInteractionUpdateFn update_fn; + void *arg1; +} uiBlockInteraction_CallbackData; + +void UI_block_interaction_set(uiBlock *block, uiBlockInteraction_CallbackData *callbacks); + +/** \} */ + /* Menu Callbacks */ typedef void (*uiMenuCreateFunc)(struct bContext *C, struct uiLayout *layout, void *arg1); @@ -536,6 +575,8 @@ typedef void (*uiMenuHandleFunc)(struct bContext *C, void *arg, int event); */ typedef bool (*uiMenuStepFunc)(struct bContext *C, int direction, void *arg1); +typedef void (*uiFreeArgFunc)(void *arg); + /* interface_query.c */ bool UI_but_has_tooltip_label(const uiBut *but); bool UI_but_is_tool(const uiBut *but); @@ -622,11 +663,11 @@ typedef void (*uiBlockCancelFunc)(struct bContext *C, void *arg1); void UI_popup_block_invoke(struct bContext *C, uiBlockCreateFunc func, void *arg, - void (*arg_free)(void *arg)); + uiFreeArgFunc arg_free); void UI_popup_block_invoke_ex(struct bContext *C, uiBlockCreateFunc func, void *arg, - void (*arg_free)(void *arg), + uiFreeArgFunc arg_free, bool can_refresh); void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, @@ -671,7 +712,7 @@ enum { UI_BLOCK_THEME_STYLE_POPUP = 1, }; void UI_block_theme_style_set(uiBlock *block, char theme_style); -char UI_block_emboss_get(uiBlock *block); +eUIEmbossType UI_block_emboss_get(uiBlock *block); void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss); bool UI_block_is_search_only(const uiBlock *block); void UI_block_set_search_only(uiBlock *block, bool search_only); @@ -686,7 +727,7 @@ void UI_block_region_set(uiBlock *block, struct ARegion *region); void UI_block_lock_set(uiBlock *block, bool val, const char *lockstr); void UI_block_lock_clear(uiBlock *block); -/* automatic aligning, horiz or verical */ +/* Automatic aligning, horizontal or vertical. */ void UI_block_align_begin(uiBlock *block); void UI_block_align_end(uiBlock *block); @@ -723,6 +764,7 @@ void UI_but_drag_set_asset(uiBut *but, const char *name, const char *path, int id_type, + int import_type, /* eFileAssetImportType */ int icon, struct ImBuf *imb, float scale); @@ -1371,7 +1413,7 @@ typedef struct uiStringInfo { char *strinfo; } uiStringInfo; -/* Note: Expects pointers to uiStringInfo structs as parameters. +/* NOTE: Expects pointers to uiStringInfo structs as parameters. * Will fill them with translated strings, when possible. * Strings in uiStringInfo must be MEM_freeN'ed by caller. */ void UI_but_string_info_get(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0); @@ -1601,7 +1643,7 @@ void UI_but_func_search_set(uiBut *but, uiButSearchUpdateFn search_update_fn, void *arg, const bool free_arg, - uiButSearchArgFreeFn search_arg_free_fn, + uiFreeArgFunc search_arg_free_fn, uiButHandleFunc search_exec_fn, void *active); void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn context_menu_fn); @@ -1615,6 +1657,13 @@ int UI_searchbox_size_x(void); /* check if a string is in an existing search box */ int UI_search_items_find_index(uiSearchItems *items, const char *name); +void UI_but_hint_drawstr_set(uiBut *but, const char *string); +void UI_but_datasetrow_indentation_set(uiBut *but, int indentation); +void UI_but_datasetrow_component_set(uiBut *but, uint8_t geometry_component_type); +void UI_but_datasetrow_domain_set(uiBut *but, uint8_t attribute_domain); +uint8_t UI_but_datasetrow_component_get(uiBut *but); +uint8_t UI_but_datasetrow_domain_get(uiBut *but); + void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]); void UI_but_number_step_size_set(uiBut *but, float step_size); @@ -1639,7 +1688,7 @@ void UI_but_func_drawextra_set( void UI_but_func_menu_step_set(uiBut *but, uiMenuStepFunc func); -void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN); +void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *arg, uiFreeArgFunc free_arg); void UI_but_tooltip_refresh(struct bContext *C, uiBut *but); void UI_but_tooltip_timer_remove(struct bContext *C, uiBut *but); @@ -1653,7 +1702,7 @@ void UI_but_focus_on_enter_event(struct wmWindow *win, uiBut *but); void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN); -void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, void *arg); +void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, const void *arg); struct PointerRNA *UI_but_extra_operator_icon_add(uiBut *but, const char *opname, @@ -2420,12 +2469,20 @@ void uiItemPopoverPanelFromGroup(uiLayout *layout, void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg); void uiItemMenuFN(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *argN); -void uiItemMenuEnumO_ptr(uiLayout *layout, +void uiItemMenuEnumFullO_ptr(uiLayout *layout, + struct bContext *C, + struct wmOperatorType *ot, + const char *propname, + const char *name, + int icon, + struct PointerRNA *r_opptr); +void uiItemMenuEnumFullO(uiLayout *layout, struct bContext *C, - struct wmOperatorType *ot, + const char *opname, const char *propname, const char *name, - int icon); + int icon, + struct PointerRNA *r_opptr); void uiItemMenuEnumO(uiLayout *layout, struct bContext *C, const char *opname, diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 64f881052a1..8191a9a9062 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -51,7 +51,7 @@ enum eView2D_CommonViewTypes { V2D_COMMONVIEW_STANDARD, /* listview (i.e. Outliner) */ V2D_COMMONVIEW_LIST, - /* stackview (this is basically a list where new items are added at the top) */ + /* Stack-view (this is basically a list where new items are added at the top). */ V2D_COMMONVIEW_STACK, /* headers (this is basically the same as listview, but no y-panning) */ V2D_COMMONVIEW_HEADER, @@ -105,8 +105,12 @@ struct ScrArea; struct bContext; struct bScreen; struct rctf; +struct rcti; +struct wmEvent; struct wmGizmoGroupType; struct wmKeyConfig; +struct wmOperator; +struct wmOperatorType; typedef struct View2DScrollers View2DScrollers; @@ -284,9 +288,80 @@ void UI_view2d_smooth_view(struct bContext *C, /* Gizmo Types */ /* view2d_gizmo_navigate.c */ -/* Caller passes in own idname. */ +/* Caller passes in own idname. */ void VIEW2D_GGT_navigate_impl(struct wmGizmoGroupType *gzgt, const char *idname); +/* Edge pan */ + +/** + * Custom-data for view panning operators. + */ +typedef struct View2DEdgePanData { + /** Screen where view pan was initiated. */ + struct bScreen *screen; + /** Area where view pan was initiated. */ + struct ScrArea *area; + /** Region where view pan was initiated. */ + struct ARegion *region; + /** View2d we're operating in. */ + struct View2D *v2d; + + /** Inside distance in UI units from the edge of the region within which to start panning. */ + float inside_pad; + /** Outside distance in UI units from the edge of the region at which to stop panning. */ + float outside_pad; + /** + * Width of the zone in UI units where speed increases with distance from the edge. + * At the end of this zone max speed is reached. + */ + float speed_ramp; + /** Maximum speed in UI units per second. */ + float max_speed; + /** Delay in seconds before maximum speed is reached. */ + float delay; + + /** Amount to move view relative to zoom. */ + float facx, facy; + + /* Timers. */ + double edge_pan_last_time; + double edge_pan_start_time_x, edge_pan_start_time_y; +} View2DEdgePanData; + +bool UI_view2d_edge_pan_poll(struct bContext *C); + +void UI_view2d_edge_pan_init(struct bContext *C, + struct View2DEdgePanData *vpd, + float inside_pad, + float outside_pad, + float speed_ramp, + float max_speed, + float delay); + +void UI_view2d_edge_pan_reset(struct View2DEdgePanData *vpd); + +/* Apply transform to view (i.e. adjust 'cur' rect). */ +void UI_view2d_edge_pan_apply(struct bContext *C, struct View2DEdgePanData *vpd, int x, int y); + +/* Apply transform to view using mouse events. */ +void UI_view2d_edge_pan_apply_event(struct bContext *C, + struct View2DEdgePanData *vpd, + const struct wmEvent *event); + +void UI_view2d_edge_pan_operator_properties(struct wmOperatorType *ot); + +void UI_view2d_edge_pan_operator_properties_ex(struct wmOperatorType *ot, + float inside_pad, + float outside_pad, + float speed_ramp, + float max_speed, + float delay); + +/* Initialize panning data with operator settings. */ +void UI_view2d_edge_pan_operator_init(struct bContext *C, + struct View2DEdgePanData *vpd, + struct wmOperator *op); + #ifdef __cplusplus } #endif diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index 421019bebb8..2cc3830042c 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -75,6 +75,7 @@ set(SRC resources.c view2d.c view2d_draw.c + view2d_edge_pan.c view2d_gizmo_navigate.c view2d_ops.c @@ -101,7 +102,7 @@ if(WITH_PYTHON) add_definitions(-DWITH_PYTHON) endif() -if(WIN32) +if(WIN32 OR APPLE) if(WITH_INPUT_IME) add_definitions(-DWITH_INPUT_IME) endif() diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index a31efefd99c..32b86119753 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -476,7 +476,7 @@ void ui_block_bounds_calc(uiBlock *block) static void ui_block_bounds_calc_centered(wmWindow *window, uiBlock *block) { - /* note: this is used for the splash where window bounds event has not been + /* NOTE: this is used for the splash where window bounds event has not been * updated by ghost, get the window bounds from ghost directly */ const int xmax = WM_window_pixels_x(window); @@ -587,7 +587,7 @@ void UI_block_bounds_set_normal(uiBlock *block, int addval) block->bounds_type = UI_BLOCK_BOUNDS; } -/* used for pulldowns */ +/* Used for pull-downs. */ void UI_block_bounds_set_text(uiBlock *block, int addval) { block->bounds = addval; @@ -811,7 +811,8 @@ static void ui_but_update_old_active_from_new(uiBut *oldbut, uiBut *but) /* Move tooltip from new to old. */ SWAP(uiButToolTipFunc, oldbut->tip_func, but->tip_func); - SWAP(void *, oldbut->tip_argN, but->tip_argN); + SWAP(void *, oldbut->tip_arg, but->tip_arg); + SWAP(uiFreeArgFunc, oldbut->tip_arg_free, but->tip_arg_free); oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy); oldbut->drawflag = (oldbut->drawflag & ~drawflag_copy) | (but->drawflag & drawflag_copy); @@ -822,7 +823,7 @@ static void ui_but_update_old_active_from_new(uiBut *oldbut, uiBut *but) if (oldbut->type == UI_BTYPE_SEARCH_MENU) { uiButSearch *search_oldbut = (uiButSearch *)oldbut, *search_but = (uiButSearch *)but; - SWAP(uiButSearchArgFreeFn, search_oldbut->arg_free_fn, search_but->arg_free_fn); + SWAP(uiFreeArgFunc, search_oldbut->arg_free_fn, search_but->arg_free_fn); SWAP(void *, search_oldbut->arg, search_but->arg); } @@ -861,7 +862,7 @@ static void ui_but_update_old_active_from_new(uiBut *oldbut, uiBut *but) SWAP(void *, but->dragpoin, oldbut->dragpoin); } - /* note: if layout hasn't been applied yet, it uses old button pointers... */ + /* NOTE: if layout hasn't been applied yet, it uses old button pointers... */ } /** @@ -985,12 +986,12 @@ bool UI_but_active_only(const bContext *C, ARegion *region, uiBlock *block, uiBu /** * \warning This must run after other handlers have been added, - * otherwise the handler wont be removed, see: T71112. + * otherwise the handler won't be removed, see: T71112. */ bool UI_block_active_only_flagged_buttons(const bContext *C, ARegion *region, uiBlock *block) { /* Running this command before end-block has run, means buttons that open menus - * wont have those menus correctly positioned, see T83539. */ + * won't have those menus correctly positioned, see T83539. */ BLI_assert(block->endblock); bool done = false; @@ -1160,7 +1161,6 @@ void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_str MEM_freeN(butstr_orig); but->str = but->strdata; but->flag |= UI_BUT_HAS_SEP_CHAR; - but->drawflag |= UI_BUT_HAS_SHORTCUT; ui_but_update(but); } @@ -1199,7 +1199,7 @@ static bool ui_but_event_operator_string_from_menu(const bContext *C, /* annoying, create a property */ const IDPropertyTemplate val = {0}; - IDProperty *prop_menu = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */ + IDProperty *prop_menu = IDP_New(IDP_GROUP, &val, __func__); /* Dummy, name is unimportant. */ IDP_AddToGroup(prop_menu, IDP_NewString(mt->idname, "name", sizeof(mt->idname))); if (WM_key_event_operator_string( @@ -1224,7 +1224,7 @@ static bool ui_but_event_operator_string_from_panel(const bContext *C, /* annoying, create a property */ const IDPropertyTemplate val = {0}; - IDProperty *prop_panel = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */ + IDProperty *prop_panel = IDP_New(IDP_GROUP, &val, __func__); /* Dummy, name is unimportant. */ IDP_AddToGroup(prop_panel, IDP_NewString(pt->idname, "name", sizeof(pt->idname))); IDP_AddToGroup(prop_panel, IDP_New(IDP_INT, @@ -1382,11 +1382,11 @@ static bool ui_but_event_property_operator_string(const bContext *C, else { /* special exceptions for common nested data in editors... */ if (RNA_struct_is_a(ptr->type, &RNA_DopeSheet)) { - /* dopesheet filtering options... */ + /* Dope-sheet filtering options. */ data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(prop)); } else if (RNA_struct_is_a(ptr->type, &RNA_FileSelectParams)) { - /* Filebrowser options... */ + /* File-browser options. */ data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(prop)); } } @@ -1805,7 +1805,7 @@ void UI_block_update_from_old(const bContext *C, uiBlock *block) static void ui_but_validate(const uiBut *but) { /* Number buttons must have a click-step, - * assert instead of correcting the value to ensure the caller knows what they're doing. */ + * assert instead of correcting the value to ensure the caller knows what they're doing. */ if (but->type == UI_BTYPE_NUM) { uiButNumber *number_but = (uiButNumber *)but; @@ -1945,8 +1945,8 @@ void ui_fontscale(short *points, float aspect) if (aspect < 0.9f || aspect > 1.1f) { float pointsf = *points; - /* for some reason scaling fonts goes too fast compared to widget size */ - /* XXX not true anymore? (ton) */ + /* For some reason scaling fonts goes too fast compared to widget size. */ + /* XXX(ton): not true anymore? */ // aspect = sqrt(aspect); pointsf /= aspect; @@ -2106,6 +2106,9 @@ void UI_region_message_subscribe(ARegion *region, struct wmMsgBus *mbus) int ui_but_is_pushed_ex(uiBut *but, double *value) { int is_push = 0; + if (but->pushed_state_func) { + return but->pushed_state_func(but, but->pushed_state_arg); + } if (but->bit) { const bool state = !ELEM( @@ -2254,7 +2257,6 @@ void ui_but_v3_get(uiBut *but, float vec[3]) } else if (but->pointype == UI_BUT_POIN_CHAR) { const char *cp = (char *)but->poin; - vec[0] = ((float)cp[0]) / 255.0f; vec[1] = ((float)cp[1]) / 255.0f; vec[2] = ((float)cp[2]) / 255.0f; @@ -3138,7 +3140,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) return true; } else if (str[0] == '#') { - /* shortcut to create new driver expression (versus immediate Py-execution) */ + /* Shortcut to create new driver expression (versus immediate Python-execution). */ return ui_but_anim_expression_create(but, str + 1); } else { @@ -3207,27 +3209,25 @@ void ui_but_range_set_hard(uiBut *but) const PropertyType type = RNA_property_type(but->rnaprop); - /* clamp button range to something reasonable in case - * we get -inf/inf from RNA properties */ if (type == PROP_INT) { int imin, imax; RNA_property_int_range(&but->rnapoin, but->rnaprop, &imin, &imax); - but->hardmin = (imin == INT_MIN) ? -1e4 : imin; - but->hardmax = (imin == INT_MAX) ? 1e4 : imax; + but->hardmin = imin; + but->hardmax = imax; } else if (type == PROP_FLOAT) { float fmin, fmax; RNA_property_float_range(&but->rnapoin, but->rnaprop, &fmin, &fmax); - but->hardmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin; - but->hardmax = (fmax == FLT_MAX) ? (float)1e4 : fmax; + but->hardmin = fmin; + but->hardmax = fmax; } } -/* note: this could be split up into functions which handle arrays and not */ +/* NOTE: this could be split up into functions which handle arrays and not. */ void ui_but_range_set_soft(uiBut *but) { - /* ideally we would not limit this but practically, its more than - * enough worst case is very long vectors wont use a smart soft-range + /* Ideally we would not limit this, but practically it's more than + * enough. Worst case is very long vectors won't use a smart soft-range, * which isn't so bad. */ if (but->rnaprop) { @@ -3246,8 +3246,8 @@ void ui_but_range_set_soft(uiBut *but) RNA_property_int_ui_range(&but->rnapoin, but->rnaprop, &imin, &imax, &istep); softmin = (imin == INT_MIN) ? -1e4 : imin; softmax = (imin == INT_MAX) ? 1e4 : imax; - /*step = istep;*/ /*UNUSED*/ - /*precision = 1;*/ /*UNUSED*/ + // step = istep; /* UNUSED */ + // precision = 1; /* UNUSED */ if (is_array) { int value_range[2]; @@ -3266,8 +3266,8 @@ void ui_but_range_set_soft(uiBut *but) RNA_property_float_ui_range(&but->rnapoin, but->rnaprop, &fmin, &fmax, &fstep, &fprecision); softmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin; softmax = (fmax == FLT_MAX) ? (float)1e4 : fmax; - /*step = fstep;*/ /*UNUSED*/ - /*precision = fprecision;*/ /*UNUSED*/ + // step = fstep; /* UNUSED */ + // precision = fprecision; /* UNUSED */ /* Use shared min/max for array values, except for color alpha. */ if (is_array && !(subtype == PROP_COLOR && but->rnaindex == 3)) { @@ -3359,8 +3359,8 @@ static void ui_but_free(const bContext *C, uiBut *but) MEM_freeN(but->func_argN); } - if (but->tip_argN) { - MEM_freeN(but->tip_argN); + if (but->tip_arg_free) { + but->tip_arg_free(but->tip_arg); } if (but->hold_argN) { @@ -3542,7 +3542,7 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, eU return block; } -char UI_block_emboss_get(uiBlock *block) +eUIEmbossType UI_block_emboss_get(uiBlock *block) { return block->emboss; } @@ -3581,7 +3581,7 @@ static void ui_but_build_drawstr_float(uiBut *but, double value) subtype = RNA_property_subtype(but->rnaprop); } - /* Change negative zero to regular zero, without altering anything else. */ + /* Change negative zero to regular zero, without altering anything else. */ value += +0.0f; if (value == (double)FLT_MAX) { @@ -3906,6 +3906,10 @@ static void ui_but_alloc_info(const eButType type, alloc_size = sizeof(uiButCurveProfile); alloc_str = "uiButCurveProfile"; break; + case UI_BTYPE_DATASETROW: + alloc_size = sizeof(uiButDatasetRow); + alloc_str = "uiButDatasetRow"; + break; default: alloc_size = sizeof(uiBut); alloc_str = "uiBut"; @@ -4102,7 +4106,7 @@ static uiBut *ui_def_but(uiBlock *block, UI_BTYPE_BLOCK, UI_BTYPE_BUT_MENU, UI_BTYPE_SEARCH_MENU, - UI_BTYPE_PROGRESS_BAR, + UI_BTYPE_DATASETROW, UI_BTYPE_POPOVER)) { but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT); } @@ -4149,7 +4153,7 @@ static uiBut *ui_def_but(uiBlock *block, } #ifdef WITH_PYTHON - /* if the 'UI_OT_editsource' is running, extract the source info from the button */ + /* If the 'UI_OT_editsource' is running, extract the source info from the button. */ if (UI_editsource_enable_check()) { UI_editsource_active_but_test(but); } @@ -4187,7 +4191,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu uiPopupBlockHandle *handle = block->handle; uiBut *but = (uiBut *)but_p; - /* see comment in ui_item_enum_expand, re: uiname */ + /* see comment in ui_item_enum_expand, re: `uiname`. */ const EnumPropertyItem *item_array; UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT); @@ -4242,7 +4246,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu uiItemS(layout); } - /* note, item_array[...] is reversed on access */ + /* NOTE: `item_array[...]` is reversed on access. */ /* create items */ uiLayout *split = uiLayoutSplit(layout, 0.0f, false); @@ -4545,7 +4549,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, else if (proptype == PROP_STRING) { min = 0; max = RNA_property_string_maxlength(prop); - /* note, 'max' may be zero (code for dynamically resized array) */ + /* NOTE: 'max' may be zero (code for dynamically resized array). */ } } @@ -4592,7 +4596,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, if (proptype == PROP_POINTER) { /* If the button shows an ID, automatically set it as focused in context so operators can - * access it.*/ + * access it. */ const PointerRNA pptr = RNA_property_pointer_get(ptr, prop); if (pptr.data && RNA_struct_is_ID(pptr.type)) { but->context = CTX_store_add(&block->contexts, "id", &pptr); @@ -6146,6 +6150,7 @@ void UI_but_drag_set_asset(uiBut *but, const char *name, const char *path, int id_type, + int import_type, int icon, struct ImBuf *imb, float scale) @@ -6155,6 +6160,7 @@ void UI_but_drag_set_asset(uiBut *but, BLI_strncpy(asset_drag->name, name, sizeof(asset_drag->name)); asset_drag->path = path; asset_drag->id_type = id_type; + asset_drag->import_type = import_type; but->dragtype = WM_DRAG_ASSET; ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */ @@ -6328,19 +6334,21 @@ void UI_but_func_menu_step_set(uiBut *but, uiMenuStepFunc func) but->menu_step_func = func; } -void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN) +void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *arg, uiFreeArgFunc free_arg) { but->tip_func = func; - if (but->tip_argN) { - MEM_freeN(but->tip_argN); + if (but->tip_arg_free) { + but->tip_arg_free(but->tip_arg); } - but->tip_argN = argN; + but->tip_arg = arg; + but->tip_arg_free = free_arg; } -void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, void *arg) +void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, const void *arg) { but->pushed_state_func = func; but->pushed_state_arg = arg; + ui_but_update(but); } uiBut *uiDefBlockBut(uiBlock *block, @@ -6623,7 +6631,7 @@ void UI_but_func_search_set(uiBut *but, uiButSearchUpdateFn search_update_fn, void *arg, const bool free_arg, - uiButSearchArgFreeFn search_arg_free_fn, + uiFreeArgFunc search_arg_free_fn, uiButHandleFunc search_exec_fn, void *active) { @@ -6748,7 +6756,7 @@ static void operator_enum_search_update_fn(const struct bContext *C, for (int i = 0; i < filtered_amount; i++) { const EnumPropertyItem *item = filtered_items[i]; - /* note: need to give the index rather than the + /* NOTE: need to give the index rather than the * identifier because the enum can be freed */ if (!UI_search_item_add( items, item->name, POINTER_FROM_INT(item->value), item->icon, 0, 0)) { @@ -6825,6 +6833,55 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block, return but; } +void UI_but_datasetrow_indentation_set(uiBut *but, int indentation) +{ + uiButDatasetRow *but_dataset = (uiButDatasetRow *)but; + BLI_assert(but->type == UI_BTYPE_DATASETROW); + + but_dataset->indentation = indentation; + BLI_assert(indentation >= 0); +} + +/** + * Adds a hint to the button which draws right aligned, grayed out and never clipped. + */ +void UI_but_hint_drawstr_set(uiBut *but, const char *string) +{ + ui_but_add_shortcut(but, string, false); +} + +void UI_but_datasetrow_component_set(uiBut *but, uint8_t geometry_component_type) +{ + uiButDatasetRow *but_dataset_row = (uiButDatasetRow *)but; + BLI_assert(but->type == UI_BTYPE_DATASETROW); + + but_dataset_row->geometry_component_type = geometry_component_type; +} + +void UI_but_datasetrow_domain_set(uiBut *but, uint8_t attribute_domain) +{ + uiButDatasetRow *but_dataset_row = (uiButDatasetRow *)but; + BLI_assert(but->type == UI_BTYPE_DATASETROW); + + but_dataset_row->attribute_domain = attribute_domain; +} + +uint8_t UI_but_datasetrow_component_get(uiBut *but) +{ + uiButDatasetRow *but_dataset_row = (uiButDatasetRow *)but; + BLI_assert(but->type == UI_BTYPE_DATASETROW); + + return but_dataset_row->geometry_component_type; +} + +uint8_t UI_but_datasetrow_domain_get(uiBut *but) +{ + uiButDatasetRow *but_dataset_row = (uiButDatasetRow *)but; + BLI_assert(but->type == UI_BTYPE_DATASETROW); + + return but_dataset_row->attribute_domain; +} + void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4]) { but->flag |= UI_BUT_NODE_LINK; @@ -6909,7 +6966,7 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) } else if (type == BUT_GET_TIP) { if (but->tip_func) { - tmp = but->tip_func(C, but->tip_argN, but->tip); + tmp = but->tip_func(C, but->tip_arg, but->tip); } else if (but->tip && but->tip[0]) { tmp = BLI_strdup(but->tip); diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c index 1f9c736a5f3..dbfdfbf7950 100644 --- a/source/blender/editors/interface/interface_align.c +++ b/source/blender/editors/interface/interface_align.c @@ -590,7 +590,8 @@ static void ui_block_align_calc_but(uiBut *first, short nr) /* rows == 0: 1 row, cols == 0: 1 column */ - /* note; how it uses 'flag' in loop below (either set it, or OR it) is confusing */ + /* NOTE: manipulation of 'flag' in the loop below is confusing. + * In some cases it's assigned, other times OR is used. */ for (but = first, prev = NULL; but && but->alignnr == nr; prev = but, but = but->next) { next = but->next; if (next && next->alignnr != nr) { diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index b142e383df0..2a7611eabb1 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -417,7 +417,7 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um) &um->items, drawstr, but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext); } else if (but->rnaprop) { - /* Note: 'member_id' may be a path. */ + /* NOTE: 'member_id' may be a path. */ const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin); const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin); const char *member_id_data_path = member_id; @@ -425,7 +425,7 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um) member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path); } const char *prop_id = RNA_property_identifier(but->rnaprop); - /* Note, ignore 'drawstr', use property idname always. */ + /* NOTE: ignore 'drawstr', use property idname always. */ ED_screen_user_menu_item_add_prop(&um->items, "", member_id_data_path, prop_id, but->rnaindex); if (data_path) { MEM_freeN((void *)data_path); @@ -560,7 +560,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) const bool is_overridable = (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0; /* Set the (button_pointer, button_prop) - * and pointer data for Python access to the hovered ui element. */ + * and pointer data for Python access to the hovered UI element. */ uiLayoutSetContextFromBut(layout, but); /* Keyframes */ @@ -1280,7 +1280,6 @@ void ui_popup_context_menu_for_panel(bContext *C, ARegion *region, Panel *panel) uiBlock *block = uiLayoutGetBlock(layout); uiBut *but = block->buttons.last; but->flag |= UI_BUT_HAS_SEP_CHAR; - but->drawflag |= UI_BUT_HAS_SHORTCUT; } } UI_popup_menu_end(C, pup); diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 40cfcaea883..655fdda3069 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -69,8 +69,7 @@ static int roundboxtype = UI_CNR_ALL; void UI_draw_roundbox_corner_set(int type) { /* Not sure the roundbox function is the best place to change this - * if this is undone, it's not that big a deal, only makes curves edges - * square for the */ + * if this is undone, it's not that big a deal, only makes curves edges square. */ roundboxtype = type; } @@ -230,7 +229,7 @@ void ui_draw_but_TAB_outline(const rcti *rect, {0.98, 0.805}, }; - /* mult */ + /* Multiply. */ for (a = 0; a < 4; a++) { mul_v2_fl(vec[a], rad); } @@ -593,7 +592,7 @@ static void waveform_draw_one(float *waveform, int nbr, const float col[3]) GPU_vertbuf_attr_fill(vbo, pos_id, waveform); - /* TODO store the GPUBatch inside the scope */ + /* TODO: store the #GPUBatch inside the scope. */ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); GPU_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f); @@ -2224,9 +2223,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), /* ****************************************************** */ -/* TODO: high quality UI drop shadows using GLSL shader and single draw call - * would replace / modify the following 3 functions - merwin - */ +/* TODO(merwin): high quality UI drop shadows using GLSL shader and single draw call + * would replace / modify the following 3 functions. */ static void ui_shadowbox(const rctf *rect, uint pos, uint color, float shadsize, uchar alpha) { @@ -2351,7 +2349,7 @@ void ui_draw_dropshadow( true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color); #endif /* Compute final visibility to match old method result. */ - /* TODO we could just find a better fit function inside the shader instead of this. */ + /* TODO: we could just find a better fit function inside the shader instead of this. */ visibility = visibility * (1.0f - calpha); calpha += dalpha; } diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index 178f663ff58..b52bfc81b7a 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -130,14 +130,19 @@ void eyedropper_draw_cursor_text_region(const struct bContext *C, const char *name) { wmWindow *win = CTX_wm_window(C); - const int x = win->eventstate->x - region->winrct.xmin; - const int y = win->eventstate->y - region->winrct.ymin; + const int x = win->eventstate->x; + const int y = win->eventstate->y; if ((name[0] == '\0') || (BLI_rcti_isect_pt(®ion->winrct, x, y) == false)) { return; } - eyedropper_draw_cursor_text_ex(x, y, name); + const int mval[2] = { + x - region->winrct.xmin, + y - region->winrct.ymin, + }; + + eyedropper_draw_cursor_text_ex(mval[0], mval[1], name); } /** diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c index d5fb0e4e744..ba72cecc514 100644 --- a/source/blender/editors/interface/interface_eyedropper_color.c +++ b/source/blender/editors/interface/interface_eyedropper_color.c @@ -118,7 +118,8 @@ static bool eyedropper_init(bContext *C, wmOperator *op) RNA_property_float_get_array(&eye->ptr, eye->prop, col); if (eye->ptr.type == &RNA_CompositorNodeCryptomatteV2) { eye->crypto_node = (bNode *)eye->ptr.data; - eye->cryptomatte_session = ntreeCompositCryptomatteSession(eye->crypto_node); + eye->cryptomatte_session = ntreeCompositCryptomatteSession(CTX_data_scene(C), + eye->crypto_node); eye->draw_handle_sample_text = WM_draw_cb_activate(CTX_wm_window(C), eyedropper_draw_cb, eye); } @@ -199,6 +200,57 @@ static bool eyedropper_cryptomatte_sample_renderlayer_fl(RenderLayer *render_lay return false; } +static bool eyedropper_cryptomatte_sample_render_fl(const bNode *node, + const char *prefix, + const float fpos[2], + float r_col[3]) +{ + bool success = false; + Scene *scene = (Scene *)node->id; + BLI_assert(GS(scene->id.name) == ID_SCE); + Render *re = RE_GetSceneRender(scene); + + if (re) { + RenderResult *rr = RE_AcquireResultRead(re); + if (rr) { + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + RenderLayer *render_layer = RE_GetRenderLayer(rr, view_layer->name); + success = eyedropper_cryptomatte_sample_renderlayer_fl(render_layer, prefix, fpos, r_col); + if (success) { + break; + } + } + } + RE_ReleaseResult(re); + } + return success; +} + +static bool eyedropper_cryptomatte_sample_image_fl(const bNode *node, + NodeCryptomatte *crypto, + const char *prefix, + const float fpos[2], + float r_col[3]) +{ + bool success = false; + Image *image = (Image *)node->id; + BLI_assert((image == NULL) || (GS(image->id.name) == ID_IM)); + ImageUser *iuser = &crypto->iuser; + + if (image && image->type == IMA_TYPE_MULTILAYER) { + ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, NULL); + if (image->rr) { + LISTBASE_FOREACH (RenderLayer *, render_layer, &image->rr->layers) { + success = eyedropper_cryptomatte_sample_renderlayer_fl(render_layer, prefix, fpos, r_col); + if (success) { + break; + } + } + } + BKE_image_release_ibuf(image, ibuf, NULL); + } + return success; +} static bool eyedropper_cryptomatte_sample_fl( bContext *C, Eyedropper *eye, int mx, int my, float r_col[3]) @@ -255,53 +307,19 @@ static bool eyedropper_cryptomatte_sample_fl( return false; } - bool success = false; /* TODO(jbakker): Migrate this file to cc and use std::string as return param. */ char prefix[MAX_NAME + 1]; - ntreeCompositCryptomatteLayerPrefix(node, prefix, sizeof(prefix) - 1); + const Scene *scene = CTX_data_scene(C); + ntreeCompositCryptomatteLayerPrefix(scene, node, prefix, sizeof(prefix) - 1); prefix[MAX_NAME] = '\0'; if (node->custom1 == CMP_CRYPTOMATTE_SRC_RENDER) { - Scene *scene = (Scene *)node->id; - BLI_assert(GS(scene->id.name) == ID_SCE); - Render *re = RE_GetSceneRender(scene); - - if (re) { - RenderResult *rr = RE_AcquireResultRead(re); - if (rr) { - LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { - RenderLayer *render_layer = RE_GetRenderLayer(rr, view_layer->name); - success = eyedropper_cryptomatte_sample_renderlayer_fl( - render_layer, prefix, fpos, r_col); - if (success) { - break; - } - } - } - RE_ReleaseResult(re); - } + return eyedropper_cryptomatte_sample_render_fl(node, prefix, fpos, r_col); } - else if (node->custom1 == CMP_CRYPTOMATTE_SRC_IMAGE) { - Image *image = (Image *)node->id; - BLI_assert(GS(image->id.name) == ID_IM); - ImageUser *iuser = &crypto->iuser; - - if (image && image->type == IMA_TYPE_MULTILAYER) { - ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, NULL); - if (image->rr) { - LISTBASE_FOREACH (RenderLayer *, render_layer, &image->rr->layers) { - success = eyedropper_cryptomatte_sample_renderlayer_fl( - render_layer, prefix, fpos, r_col); - if (success) { - break; - } - } - } - BKE_image_release_ibuf(image, ibuf, NULL); - } + if (node->custom1 == CMP_CRYPTOMATTE_SRC_IMAGE) { + return eyedropper_cryptomatte_sample_image_fl(node, crypto, prefix, fpos, r_col); } - - return success; + return false; } /** diff --git a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c index f2899fc0098..417807afff1 100644 --- a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c +++ b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c @@ -255,7 +255,7 @@ static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, Eyed copy_v3_v3(col_conv, eye->color); } - /* Add material or Palette color*/ + /* Add material or Palette color. */ if (eye->mode == 0) { eyedropper_add_material(C, col_conv, only_stroke, only_fill, both); } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 282d470c7ea..3136ca64e0f 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -35,10 +35,12 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "BLI_array_utils.h" #include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_rect.h" +#include "BLI_sort_utils.h" #include "BLI_string.h" #include "BLI_string_cursor_utf8.h" #include "BLI_string_utf8.h" @@ -170,6 +172,20 @@ static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but static void ui_textedit_string_set(uiBut *but, struct uiHandleButtonData *data, const char *str); static void button_tooltip_timer_reset(bContext *C, uiBut *but); +static void ui_block_interaction_begin_ensure(bContext *C, + uiBlock *block, + struct uiHandleButtonData *data, + const bool is_click); +static struct uiBlockInteraction_Handle *ui_block_interaction_begin(struct bContext *C, + uiBlock *block, + const bool is_click); +static void ui_block_interaction_end(struct bContext *C, + uiBlockInteraction_CallbackData *callbacks, + struct uiBlockInteraction_Handle *interaction); +static void ui_block_interaction_update(struct bContext *C, + uiBlockInteraction_CallbackData *callbacks, + struct uiBlockInteraction_Handle *interaction); + #ifdef USE_KEYNAV_LIMIT static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEvent *event); static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEvent *event); @@ -225,6 +241,19 @@ typedef enum uiMenuScrollType { MENU_SCROLL_BOTTOM, } uiMenuScrollType; +typedef struct uiBlockInteraction_Handle { + struct uiBlockInteraction_Params params; + void *user_data; + /** + * This is shared between #uiHandleButtonData and #uiAfterFunc, + * the last user runs the end callback and frees the data. + * + * This is needed as the order of freeing changes depending on + * accepting/canceling the operation. + */ + int user_count; +} uiBlockInteraction_Handle; + #ifdef USE_ALLSELECT /* Unfortunately there's no good way handle more generally: @@ -273,7 +302,7 @@ static void ui_selectcontext_apply(bContext *C, /** * how far to drag before we check for gesture direction (in pixels), - * note: half the height of a button is about right... */ + * NOTE: half the height of a button is about right... */ # define DRAG_MULTINUM_THRESHOLD_DRAG_X (UI_UNIT_Y / 4) /** @@ -430,6 +459,8 @@ typedef struct uiHandleButtonData { uiSelectContextStore select_others; #endif + struct uiBlockInteraction_Handle *custom_interaction_handle; + /* Text field undo. */ struct uiUndoStack_Text *undo_stack_text; @@ -469,7 +500,10 @@ typedef struct uiAfterFunc { PropertyRNA *rnaprop; void *search_arg; - uiButSearchArgFreeFn search_arg_free_fn; + uiFreeArgFunc search_arg_free_fn; + + uiBlockInteraction_CallbackData custom_interaction_callbacks; + uiBlockInteraction_Handle *custom_interaction_handle; bContextStore *context; @@ -769,72 +803,95 @@ static bool ui_afterfunc_check(const uiBlock *block, const uiBut *but) (block->handle && block->handle->popup_op)); } +/** + * These functions are postponed and only executed after all other + * handling is done, i.e. menus are closed, in order to avoid conflicts + * with these functions removing the buttons we are working with. + */ static void ui_apply_but_func(bContext *C, uiBut *but) { uiBlock *block = but->block; + if (!ui_afterfunc_check(block, but)) { + return; + } - /* these functions are postponed and only executed after all other - * handling is done, i.e. menus are closed, in order to avoid conflicts - * with these functions removing the buttons we are working with */ - - if (ui_afterfunc_check(block, but)) { - uiAfterFunc *after = ui_afterfunc_new(); + uiAfterFunc *after = ui_afterfunc_new(); - if (but->func && ELEM(but, but->func_arg1, but->func_arg2)) { - /* exception, this will crash due to removed button otherwise */ - but->func(C, but->func_arg1, but->func_arg2); - } - else { - after->func = but->func; - } + if (but->func && ELEM(but, but->func_arg1, but->func_arg2)) { + /* exception, this will crash due to removed button otherwise */ + but->func(C, but->func_arg1, but->func_arg2); + } + else { + after->func = but->func; + } - after->func_arg1 = but->func_arg1; - after->func_arg2 = but->func_arg2; + after->func_arg1 = but->func_arg1; + after->func_arg2 = but->func_arg2; - after->funcN = but->funcN; - after->func_argN = (but->func_argN) ? MEM_dupallocN(but->func_argN) : NULL; + after->funcN = but->funcN; + after->func_argN = (but->func_argN) ? MEM_dupallocN(but->func_argN) : NULL; - after->rename_func = but->rename_func; - after->rename_arg1 = but->rename_arg1; - after->rename_orig = but->rename_orig; /* needs free! */ + after->rename_func = but->rename_func; + after->rename_arg1 = but->rename_arg1; + after->rename_orig = but->rename_orig; /* needs free! */ - after->handle_func = block->handle_func; - after->handle_func_arg = block->handle_func_arg; - after->retval = but->retval; + after->handle_func = block->handle_func; + after->handle_func_arg = block->handle_func_arg; + after->retval = but->retval; - if (but->type == UI_BTYPE_BUT_MENU) { - after->butm_func = block->butm_func; - after->butm_func_arg = block->butm_func_arg; - after->a2 = but->a2; - } + if (but->type == UI_BTYPE_BUT_MENU) { + after->butm_func = block->butm_func; + after->butm_func_arg = block->butm_func_arg; + after->a2 = but->a2; + } - if (block->handle) { - after->popup_op = block->handle->popup_op; - } + if (block->handle) { + after->popup_op = block->handle->popup_op; + } - after->optype = but->optype; - after->opcontext = but->opcontext; - after->opptr = but->opptr; + after->optype = but->optype; + after->opcontext = but->opcontext; + after->opptr = but->opptr; - after->rnapoin = but->rnapoin; - after->rnaprop = but->rnaprop; + after->rnapoin = but->rnapoin; + after->rnaprop = but->rnaprop; - if (but->type == UI_BTYPE_SEARCH_MENU) { - uiButSearch *search_but = (uiButSearch *)but; - after->search_arg_free_fn = search_but->arg_free_fn; - after->search_arg = search_but->arg; - search_but->arg_free_fn = NULL; - search_but->arg = NULL; - } + if (but->type == UI_BTYPE_SEARCH_MENU) { + uiButSearch *search_but = (uiButSearch *)but; + after->search_arg_free_fn = search_but->arg_free_fn; + after->search_arg = search_but->arg; + search_but->arg_free_fn = NULL; + search_but->arg = NULL; + } - if (but->context) { - after->context = CTX_store_copy(but->context); + if (but->active != NULL) { + uiHandleButtonData *data = but->active; + if (data->custom_interaction_handle != NULL) { + after->custom_interaction_callbacks = block->custom_interaction_callbacks; + after->custom_interaction_handle = data->custom_interaction_handle; + + /* Ensure this callback runs once and last. */ + uiAfterFunc *after_prev = after->prev; + if (after_prev && + (after_prev->custom_interaction_handle == data->custom_interaction_handle)) { + after_prev->custom_interaction_handle = NULL; + memset(&after_prev->custom_interaction_callbacks, + 0x0, + sizeof(after_prev->custom_interaction_callbacks)); + } + else { + after->custom_interaction_handle->user_count++; + } } + } - but->optype = NULL; - but->opcontext = 0; - but->opptr = NULL; + if (but->context) { + after->context = CTX_store_copy(but->context); } + + but->optype = NULL; + but->opcontext = 0; + but->opptr = NULL; } /* typically call ui_apply_but_undo(), ui_apply_but_autokey() */ @@ -997,6 +1054,18 @@ static void ui_apply_but_funcs_after(bContext *C) after.search_arg_free_fn(after.search_arg); } + if (after.custom_interaction_handle != NULL) { + after.custom_interaction_handle->user_count--; + BLI_assert(after.custom_interaction_handle->user_count >= 0); + if (after.custom_interaction_handle->user_count == 0) { + ui_block_interaction_update( + C, &after.custom_interaction_callbacks, after.custom_interaction_handle); + ui_block_interaction_end( + C, &after.custom_interaction_callbacks, after.custom_interaction_handle); + } + after.custom_interaction_handle = NULL; + } + ui_afterfunc_update_preferences_dirty(&after); if (after.undostr[0]) { @@ -1350,7 +1419,7 @@ static void ui_multibut_states_create(uiBut *but_active, uiHandleButtonData *dat } /* edit buttons proportionally to eachother - * note: if we mix buttons which are proportional and others which are not, + * NOTE: if we mix buttons which are proportional and others which are not, * this may work a bit strangely */ if ((but_active->rnaprop && (RNA_property_flag(but_active->rnaprop) & PROP_PROPORTIONAL)) || ELEM(but_active->unit_type, RNA_SUBTYPE_UNIT_VALUE(PROP_UNIT_LENGTH))) { @@ -1461,12 +1530,9 @@ static bool ui_drag_toggle_but_is_supported(const uiBut *but) /* Button pushed state to compare if other buttons match. Can be more * then just true or false for toggle buttons with more than 2 states. */ -static int ui_drag_toggle_but_pushed_state(bContext *C, uiBut *but) +static int ui_drag_toggle_but_pushed_state(uiBut *but) { if (but->rnapoin.data == NULL && but->poin == NULL && but->icon) { - if (but->pushed_state_func) { - return but->pushed_state_func(C, but->pushed_state_arg); - } /* Assume icon identifies a unique state, for buttons that * work through functions callbacks and don't have an boolean * value that indicates the state. */ @@ -1505,7 +1571,7 @@ static bool ui_drag_toggle_set_xy_xy( ui_window_to_block_fl(region, block, &xy_b_block[0], &xy_b_block[1]); LISTBASE_FOREACH (uiBut *, but, &block->buttons) { - /* Note: ctrl is always true here because (at least for now) + /* NOTE: ctrl is always true here because (at least for now) * we always want to consider text control in this case, even when not embossed. */ if (ui_but_is_interactive(but, true)) { if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) { @@ -1513,7 +1579,7 @@ static bool ui_drag_toggle_set_xy_xy( /* execute the button */ if (ui_drag_toggle_but_is_supported(but)) { /* is it pressed? */ - const int pushed_state_but = ui_drag_toggle_but_pushed_state(C, but); + const int pushed_state_but = ui_drag_toggle_but_pushed_state(but); if (pushed_state_but != pushed_state) { UI_but_execute(C, region, but); if (do_check) { @@ -1561,7 +1627,7 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const }; /* check if this is a different button, - * chances are high the button wont move about :) */ + * chances are high the button won't move about :) */ if (len_manhattan_v2v2(drag_info->but_cent_start, but_cent_new) > 1.0f) { if (fabsf(drag_info->but_cent_start[0] - but_cent_new[0]) < fabsf(drag_info->but_cent_start[1] - but_cent_new[1])) { @@ -1689,7 +1755,7 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore break; } uiSelectContextElem *other = &selctx_data->elems[i]; - /* TODO,. de-duplicate copy_to_selected_button */ + /* TODO: de-duplicate copy_to_selected_button. */ if (link->ptr.data != ptr.data) { if (use_path_from_id) { /* Path relative to ID. */ @@ -1939,11 +2005,11 @@ static bool ui_but_drag_init(bContext *C, uiDragToggleHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__); ARegion *region_prev; - /* call here because regular mouse-up event wont run, + /* call here because regular mouse-up event won't run, * typically 'button_activate_exit()' handles this */ ui_apply_but_autokey(C, but); - drag_info->pushed_state = ui_drag_toggle_but_pushed_state(C, but); + drag_info->pushed_state = ui_drag_toggle_but_pushed_state(but); drag_info->but_cent_start[0] = BLI_rctf_cent_x(&but->rect); drag_info->but_cent_start[1] = BLI_rctf_cent_y(&but->rect); copy_v2_v2_int(drag_info->xy_init, &event->x); @@ -1990,7 +2056,7 @@ static bool ui_but_drag_init(bContext *C, bool valid = false; uiDragColorHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__); - /* TODO support more button pointer types */ + /* TODO: support more button pointer types. */ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) { ui_but_v3_get(but, drag_info->color); drag_info->gamma_corrected = true; @@ -2187,6 +2253,9 @@ static void ui_apply_but( case UI_BTYPE_LISTROW: ui_apply_but_ROW(C, block, but, data); break; + case UI_BTYPE_DATASETROW: + ui_apply_but_ROW(C, block, but, data); + break; case UI_BTYPE_TAB: ui_apply_but_TAB(C, but, data); break; @@ -2283,6 +2352,11 @@ static void ui_apply_but( uiButCurveProfile *but_profile = (uiButCurveProfile *)but; but_profile->edit_profile = editprofile; } + + if (data->custom_interaction_handle != NULL) { + ui_block_interaction_update( + C, &block->custom_interaction_callbacks, data->custom_interaction_handle); + } } /** \} */ @@ -2297,7 +2371,7 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB ListBase *drags = event->customdata; /* drop event type has listbase customdata by default */ LISTBASE_FOREACH (wmDrag *, wmd, drags) { - /* TODO asset dropping. */ + /* TODO: asset dropping. */ if (wmd->type == WM_DRAG_ID) { /* align these types with UI_but_active_drop_name */ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { @@ -2346,16 +2420,16 @@ static int get_but_property_array_length(uiBut *but) } static void ui_but_set_float_array( - bContext *C, uiBut *but, uiHandleButtonData *data, float *values, int array_length) + bContext *C, uiBut *but, uiHandleButtonData *data, const float *values, const int values_len) { button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - for (int i = 0; i < array_length; i++) { + for (int i = 0; i < values_len; i++) { RNA_property_float_set_index(&but->rnapoin, but->rnaprop, i, values[i]); } if (data) { if (but->type == UI_BTYPE_UNITVEC) { - BLI_assert(array_length == 3); + BLI_assert(values_len == 3); copy_v3_v3(data->vec, values); } else { @@ -2366,56 +2440,39 @@ static void ui_but_set_float_array( button_activate_state(C, but, BUTTON_STATE_EXIT); } -static void float_array_to_string(float *values, - int array_length, +static void float_array_to_string(const float *values, + const int values_len, char *output, int output_len_max) { - /* to avoid buffer overflow attacks; numbers are quite arbitrary */ - BLI_assert(output_len_max > 15); - output_len_max -= 10; - - int current_index = 0; - output[current_index] = '['; - current_index++; - - for (int i = 0; i < array_length; i++) { - int length = BLI_snprintf( - output + current_index, output_len_max - current_index, "%f", values[i]); - current_index += length; - - if (i < array_length - 1) { - if (current_index < output_len_max) { - output[current_index + 0] = ','; - output[current_index + 1] = ' '; - current_index += 2; - } - } + const int values_end = values_len - 1; + int ofs = 0; + output[ofs++] = '['; + for (int i = 0; i < values_len; i++) { + ofs += BLI_snprintf_rlen( + output + ofs, output_len_max - ofs, (i != values_end) ? "%f, " : "%f]", values[i]); } - - output[current_index + 0] = ']'; - output[current_index + 1] = '\0'; } static void ui_but_copy_numeric_array(uiBut *but, char *output, int output_len_max) { - const int array_length = get_but_property_array_length(but); - float *values = alloca(array_length * sizeof(float)); + const int values_len = get_but_property_array_length(but); + float *values = alloca(values_len * sizeof(float)); RNA_property_float_get_array(&but->rnapoin, but->rnaprop, values); - float_array_to_string(values, array_length, output, output_len_max); + float_array_to_string(values, values_len, output, output_len_max); } -static bool parse_float_array(char *text, float *values, int expected_length) +static bool parse_float_array(char *text, float *values, int values_len_expected) { /* can parse max 4 floats for now */ - BLI_assert(0 <= expected_length && expected_length <= 4); + BLI_assert(0 <= values_len_expected && values_len_expected <= 4); float v[5]; - const int actual_length = sscanf( + const int values_len_actual = sscanf( text, "[%f, %f, %f, %f, %f]", &v[0], &v[1], &v[2], &v[3], &v[4]); - if (actual_length == expected_length) { - memcpy(values, v, sizeof(float) * expected_length); + if (values_len_actual == values_len_expected) { + memcpy(values, v, sizeof(float) * values_len_expected); return true; } return false; @@ -2426,16 +2483,16 @@ static void ui_but_paste_numeric_array(bContext *C, uiHandleButtonData *data, char *buf_paste) { - const int array_length = get_but_property_array_length(but); - if (array_length > 4) { + const int values_len = get_but_property_array_length(but); + if (values_len > 4) { /* not supported for now */ return; } - float *values = alloca(sizeof(float) * array_length); + float *values = alloca(sizeof(float) * values_len); - if (parse_float_array(buf_paste, values, array_length)) { - ui_but_set_float_array(C, but, data, values, array_length); + if (parse_float_array(buf_paste, values, values_len)) { + ui_but_set_float_array(C, but, data, values, values_len); } else { WM_report(RPT_ERROR, "Expected an array of numbers: [n, n, ...]"); @@ -2445,7 +2502,7 @@ static void ui_but_paste_numeric_array(bContext *C, static void ui_but_copy_numeric_value(uiBut *but, char *output, int output_len_max) { /* Get many decimal places, then strip trailing zeros. - * note: too high values start to give strange results */ + * NOTE: too high values start to give strange results. */ ui_but_string_get_ex(but, output, output_len_max, UI_PRECISION_FLOAT_MAX, false, NULL); BLI_str_rstrip_float_zero(output, '\0'); } @@ -3085,7 +3142,7 @@ static bool ui_textedit_insert_buf(uiBut *but, if ((len + step >= data->maxlen) && (data->maxlen - (len + 1) > 0)) { if (UI_but_is_utf8(but)) { - /* shorten 'step' to a utf8 aligned size that fits */ + /* Shorten 'step' to a utf8 aligned size that fits. */ BLI_strnlen_utf8_ex(buf, data->maxlen - (len + 1), &step); } else { @@ -3285,7 +3342,7 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in } #ifdef WITH_INPUT_IME -/* enable ime, and set up uibut ime data */ +/* Enable IME, and setup #uiBut IME data. */ static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but)) { /* XXX Is this really needed? */ @@ -3301,7 +3358,7 @@ static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but)) wm_window_IME_begin(win, x, y, 0, 0, true); } -/* disable ime, and clear uibut ime data */ +/* Disable IME, and clear #uiBut IME data. */ static void ui_textedit_ime_end(wmWindow *win, uiBut *UNUSED(but)) { wm_window_IME_end(win); @@ -3431,7 +3488,7 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data) const int strip = BLI_utf8_invalid_strip(but->editstr, strlen(but->editstr)); /* not a file?, strip non utf-8 chars */ if (strip) { - /* wont happen often so isn't that annoying to keep it here for a while */ + /* won't happen often so isn't that annoying to keep it here for a while */ printf("%s: invalid utf8 - stripped chars %d\n", __func__, strip); } } @@ -3923,7 +3980,6 @@ static void ui_numedit_begin_set_values(uiBut *but, uiHandleButtonData *data) data->startvalue = ui_but_value_get(but); data->origvalue = data->startvalue; data->value = data->origvalue; - but->editval = &data->value; } static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data) @@ -3952,6 +4008,7 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data) } else { ui_numedit_begin_set_values(but, data); + but->editval = &data->value; float softmin = but->softmin; float softmax = but->softmax; @@ -4301,7 +4358,7 @@ static bool ui_do_but_extra_operator_icon(bContext *C, button_tooltip_timer_reset(C, but); ui_but_extra_operator_icon_apply(C, but, op_icon); - /* Note: 'but', 'data' may now be freed, don't access. */ + /* NOTE: 'but', 'data' may now be freed, don't access. */ return true; } @@ -4351,7 +4408,7 @@ static bool ui_do_but_ANY_drag_toggle( } } else if (data->state == BUTTON_STATE_WAIT_DRAG) { - /* note: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into + /* NOTE: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into * its own function */ data->applied = false; *r_retval = ui_do_but_EXIT(C, but, data, event); @@ -4569,7 +4626,7 @@ static int ui_do_but_TEX( if (ELEM(event->type, EVT_PADENTER, EVT_RETKEY) && (!UI_but_is_utf8(but))) { /* pass - allow filesel, enter to execute */ } - else if (but->emboss == UI_EMBOSS_NONE && !event->ctrl) { + else if (ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS) && !event->ctrl) { /* pass */ } else { @@ -4694,7 +4751,7 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con { if (data->state == BUTTON_STATE_HIGHLIGHT) { - /* first handle click on icondrag type button */ + /* First handle click on icon-drag type button. */ if ((event->type == LEFTMOUSE) && (event->val == KM_PRESS) && but->dragpoin) { if (ui_but_contains_point_px_icon(but, data->region, event)) { @@ -4717,7 +4774,7 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) { int ret = WM_UI_HANDLER_BREAK; - /* XXX (a bit ugly) Special case handling for filebrowser drag button */ + /* XXX: (a bit ugly) Special case handling for file-browser drag button. */ if (but->dragpoin && but->imb && ui_but_contains_point_px_icon(but, data->region, event)) { ret = WM_UI_HANDLER_CONTINUE; } @@ -4787,7 +4844,7 @@ static float ui_numedit_apply_snapf( UnitSettings *unit = but->block->unit; const int unit_type = UI_but_unit_type_get(but); if ((unit_type == PROP_UNIT_ROTATION) && (unit->system_rotation != USER_UNIT_ROT_RADIANS)) { - /* pass (degrees)*/ + /* Pass (degrees). */ } else { softrange = 20.0f; @@ -4869,6 +4926,8 @@ static bool ui_numedit_but_NUM(uiButNumber *number_but, return changed; } + ui_block_interaction_begin_ensure(but->block->evil_C, but->block, data, false); + if (ui_but_is_cursor_warp(but)) { const float softmin = but->softmin; const float softmax = but->softmax; @@ -5379,6 +5438,8 @@ static bool ui_numedit_but_SLI(uiBut *but, return changed; } + ui_block_interaction_begin_ensure(but->block->evil_C, but->block, data, false); + const PropertyScaleType scale_type = ui_but_scale_type(but); softmin = but->softmin; @@ -5780,7 +5841,7 @@ static int ui_do_but_GRIP( int retval = WM_UI_HANDLER_CONTINUE; const bool horizontal = (BLI_rctf_size_x(&but->rect) < BLI_rctf_size_y(&but->rect)); - /* Note: Having to store org point in window space and recompute it to block "space" each time + /* NOTE: Having to store org point in window space and recompute it to block "space" each time * is not ideal, but this is a way to hack around behavior of ui_window_to_block(), which * returns different results when the block is inside a panel or not... * See T37739. @@ -5853,7 +5914,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co { if (data->state == BUTTON_STATE_HIGHLIGHT) { - /* first handle click on icondrag type button */ + /* First handle click on icon-drag type button. */ if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) { if (ui_but_contains_point_px_icon(but, data->region, event)) { button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG); @@ -5900,7 +5961,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co * wouldn't lead to cancel changes made to this button, but changing state to EXIT also * makes no button active for a while which leads to triggering operator when doing fast * scrolling mouse wheel. using post activate stuff from button allows to make button be - * active again after checking for all all that mouse leave and cancel stuff, so quick + * active again after checking for all that mouse leave and cancel stuff, so quick * scroll wouldn't be an issue anymore. Same goes for scrolling wheel in another * direction below (sergey). */ @@ -6038,7 +6099,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co uiButColor *color_but = (uiButColor *)but; if (data->state == BUTTON_STATE_HIGHLIGHT) { - /* first handle click on icondrag type button */ + /* First handle click on icon-drag type button. */ if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) { ui_palette_set_active(color_but); if (ui_but_contains_point_px_icon(but, data->region, event)) { @@ -6452,7 +6513,7 @@ static void ui_ndofedit_but_HSVCUBE(uiButHSVCube *hsv_but, CLAMP(hsv[2], hsv_but->but.softmin, hsv_but->but.softmax); break; default: - BLI_assert(!"invalid hsv type"); + BLI_assert_msg(0, "invalid hsv type"); break; } @@ -6968,8 +7029,8 @@ static bool ui_numedit_but_CURVE(uiBlock *block, CurveMapPoint *cmp = cuma->curve; bool changed = false; - /* evtx evty and drag coords are absolute mousecoords, - * prevents errors when editing when layout changes */ + /* evtx evty and drag coords are absolute mouse-coords, + * prevents errors when editing when layout changes. */ int mx = evtx; int my = evty; ui_window_to_block(data->region, block, &mx, &my); @@ -7027,7 +7088,7 @@ static bool ui_numedit_but_CURVE(uiBlock *block, changed = true; #ifdef USE_CONT_MOUSE_CORRECT - /* note: using 'cmp_last' is weak since there may be multiple points selected, + /* NOTE: using 'cmp_last' is weak since there may be multiple points selected, * but in practice this isn't really an issue */ if (ui_but_is_cursor_warp(but)) { /* OK but can go outside bounds */ @@ -7236,8 +7297,8 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, CurveProfilePoint *pts = profile->path; bool changed = false; - /* evtx evty and drag coords are absolute mousecoords, - * prevents errors when editing when layout changes */ + /* evtx evty and drag coords are absolute mouse-coords, + * prevents errors when editing when layout changes. */ int mx = evtx; int my = evty; ui_window_to_block(data->region, block, &mx, &my); @@ -7298,7 +7359,7 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, data->draglasty = evty; changed = true; #ifdef USE_CONT_MOUSE_CORRECT - /* note: using 'cmp_last' is weak since there may be multiple points selected, + /* NOTE: using 'cmp_last' is weak since there may be multiple points selected, * but in practice this isn't really an issue */ if (ui_but_is_cursor_warp(but)) { /* OK but can go outside bounds */ @@ -7844,6 +7905,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * case UI_BTYPE_CHECKBOX: case UI_BTYPE_CHECKBOX_N: case UI_BTYPE_ROW: + case UI_BTYPE_DATASETROW: retval = ui_do_but_TOG(C, but, data, event); break; case UI_BTYPE_SCROLL: @@ -8006,8 +8068,7 @@ static void ui_blocks_set_tooltips(ARegion *region, const bool enable) return; } - /* we disabled buttons when when they were already shown, and - * re-enable them on mouse move */ + /* We disabled buttons when they were already shown, and re-enable them on mouse move. */ LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { block->tooltipdisabled = !enable; } @@ -8233,8 +8294,8 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s data->hold_action_timer = NULL; } - /* add a blocking ui handler at the window handler for blocking, modal states - * but not for popups, because we already have a window level handler*/ + /* Add a blocking ui handler at the window handler for blocking, modal states + * but not for popups, because we already have a window level handler. */ if (!(but->block->handle && but->block->handle->popup)) { if (button_modal_state(state)) { if (!button_modal_state(data->state)) { @@ -8256,6 +8317,16 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s but->flag &= ~UI_SELECT; } + if (state == BUTTON_STATE_TEXT_EDITING) { + ui_block_interaction_begin_ensure(C, but->block, data, true); + } + else if (state == BUTTON_STATE_EXIT) { + if (data->state == BUTTON_STATE_NUM_EDITING) { + /* This happens on pasting values for example. */ + ui_block_interaction_begin_ensure(C, but->block, data, true); + } + } + data->state = state; if (state != BUTTON_STATE_EXIT) { @@ -8484,6 +8555,21 @@ static void button_activate_exit( ED_region_tag_redraw_no_rebuild(data->region); ED_region_tag_refresh_ui(data->region); + if ((but->flag & UI_BUT_DRAG_MULTI) == 0) { + if (data->custom_interaction_handle != NULL) { + /* Should only set when the button is modal. */ + BLI_assert(but->active != NULL); + data->custom_interaction_handle->user_count--; + + BLI_assert(data->custom_interaction_handle->user_count >= 0); + if (data->custom_interaction_handle->user_count == 0) { + ui_block_interaction_end( + C, &but->block->custom_interaction_callbacks, data->custom_interaction_handle); + } + data->custom_interaction_handle = NULL; + } + } + /* clean up button */ if (but->active) { MEM_freeN(but->active); @@ -8631,9 +8717,9 @@ void UI_context_active_but_prop_handle(bContext *C) { uiBut *activebut = ui_context_rna_button_active(C); if (activebut) { - /* TODO, look into a better way to handle the button change + /* TODO(campbell): look into a better way to handle the button change * currently this is mainly so reset defaults works for the - * operator redo panel - campbell */ + * operator redo panel. */ uiBlock *block = activebut->block; if (block->handle_func) { block->handle_func(C, block->handle_func_arg, activebut->retval); @@ -8822,7 +8908,7 @@ void ui_but_execute_begin(struct bContext *UNUSED(C), { BLI_assert(region != NULL); BLI_assert(BLI_findindex(®ion->uiblocks, but->block) != -1); - /* note: ideally we would not have to change 'but->active' however + /* NOTE: ideally we would not have to change 'but->active' however * some functions we call don't use data (as they should be doing) */ uiHandleButtonData *data; *active_back = but->active; @@ -9191,7 +9277,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) * * This is needed to make sure if a button was active, * it stays active while the mouse is over it. - * This avoids adding mousemoves, see: T33466. */ + * This avoids adding mouse-moves, see: T33466. */ if (ELEM(state_orig, BUTTON_STATE_INIT, BUTTON_STATE_HIGHLIGHT, BUTTON_STATE_WAIT_DRAG)) { if (ui_but_find_mouse_over(region, event) == but) { button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER); @@ -9679,7 +9765,7 @@ static void ui_region_auto_open_clear(ARegion *region) * This allows a menu to be open, * but send key events to the parent if there's no active buttons. * - * Without this keyboard navigation from menu's wont work. + * Without this keyboard navigation from menus won't work. */ static bool ui_menu_pass_event_to_parent_if_nonactive(uiPopupBlockHandle *menu, const uiBut *but, @@ -10032,7 +10118,7 @@ static int ui_handle_menu_event(bContext *C, } if (!but) { - /* wrap button or no active button*/ + /* Wrap button or no active button. */ uiBut *but_wrap = NULL; if (ELEM(scrolltype, MENU_SCROLL_UP, MENU_SCROLL_BOTTOM)) { but_wrap = ui_but_last(block); @@ -10272,7 +10358,7 @@ static int ui_handle_menu_event(bContext *C, /* For buttons that use a hold function, * exit when mouse-up outside the menu. */ if (block->flag & UI_BLOCK_POPUP_HOLD) { - /* Note, we could check the cursor is over the parent button. */ + /* NOTE: we could check the cursor is over the parent button. */ menu->menuretval = UI_RETURN_CANCEL; retval = WM_UI_HANDLER_CONTINUE; } @@ -10376,7 +10462,7 @@ static int ui_handle_menu_event(bContext *C, * anymore why it was there? but it meant enter didn't work * for example when mouse was not over submenu */ if ((event->type == TIMER) || - (/*inside &&*/ (!menu->menuretval || (menu->menuretval & UI_RETURN_UPDATE)) && + (/* inside && */ (!menu->menuretval || (menu->menuretval & UI_RETURN_UPDATE)) && retval == WM_UI_HANDLER_CONTINUE)) { retval = ui_handle_menu_button(C, event, menu); } @@ -11331,3 +11417,100 @@ bool UI_but_active_drop_color(bContext *C) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name UI Block Interaction API + * \{ */ + +void UI_block_interaction_set(uiBlock *block, uiBlockInteraction_CallbackData *callbacks) +{ + block->custom_interaction_callbacks = *callbacks; +} + +static uiBlockInteraction_Handle *ui_block_interaction_begin(bContext *C, + uiBlock *block, + const bool is_click) +{ + BLI_assert(block->custom_interaction_callbacks.begin_fn != NULL); + uiBlockInteraction_Handle *interaction = MEM_callocN(sizeof(*interaction), __func__); + + int unique_retval_ids_len = 0; + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + if (but->active || (but->flag & UI_BUT_DRAG_MULTI)) { + unique_retval_ids_len++; + } + } + + int *unique_retval_ids = MEM_mallocN(sizeof(*unique_retval_ids) * unique_retval_ids_len, + __func__); + unique_retval_ids_len = 0; + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + if (but->active || (but->flag & UI_BUT_DRAG_MULTI)) { + unique_retval_ids[unique_retval_ids_len++] = but->retval; + } + } + + if (unique_retval_ids_len > 1) { + qsort(unique_retval_ids, unique_retval_ids_len, sizeof(int), BLI_sortutil_cmp_int); + unique_retval_ids_len = BLI_array_deduplicate_ordered(unique_retval_ids, + unique_retval_ids_len); + unique_retval_ids = MEM_reallocN(unique_retval_ids, + sizeof(*unique_retval_ids) * unique_retval_ids_len); + } + + interaction->params.is_click = is_click; + interaction->params.unique_retval_ids = unique_retval_ids; + interaction->params.unique_retval_ids_len = unique_retval_ids_len; + + interaction->user_data = block->custom_interaction_callbacks.begin_fn( + C, &interaction->params, block->custom_interaction_callbacks.arg1); + return interaction; +} + +static void ui_block_interaction_end(bContext *C, + uiBlockInteraction_CallbackData *callbacks, + uiBlockInteraction_Handle *interaction) +{ + BLI_assert(callbacks->end_fn != NULL); + callbacks->end_fn(C, &interaction->params, callbacks->arg1, interaction->user_data); + MEM_freeN(interaction->params.unique_retval_ids); + MEM_freeN(interaction); +} + +static void ui_block_interaction_update(bContext *C, + uiBlockInteraction_CallbackData *callbacks, + uiBlockInteraction_Handle *interaction) +{ + BLI_assert(callbacks->update_fn != NULL); + callbacks->update_fn(C, &interaction->params, callbacks->arg1, interaction->user_data); +} + +/** + * \note #ui_block_interaction_begin cannot be called when setting the button state + * (e.g. #BUTTON_STATE_NUM_EDITING) for the following reasons. + * + * - Other buttons may still be activated using #UI_BUT_DRAG_MULTI + * which is necessary before gathering all the #uiBut.retval values to initialize + * #uiBlockInteraction_Params.unique_retval_ids. + * - When clicking on a number button it's not known if the event is a click or a drag. + * + * Instead, it must be called immediately before the drag action begins. + */ +static void ui_block_interaction_begin_ensure(bContext *C, + uiBlock *block, + uiHandleButtonData *data, + const bool is_click) +{ + if (data->custom_interaction_handle) { + return; + } + if (block->custom_interaction_callbacks.begin_fn == NULL) { + return; + } + + uiBlockInteraction_Handle *interaction = ui_block_interaction_begin(C, block, is_click); + interaction->user_count = 1; + data->custom_interaction_handle = interaction; +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 4defbed940e..2a505abe257 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1180,7 +1180,7 @@ static DrawInfo *icon_ensure_drawinfo(Icon *icon) return di; } -/* note!, returns unscaled by DPI */ +/* NOTE:, returns unscaled by DPI. */ int UI_icon_get_width(int icon_id) { Icon *icon = BKE_icon_get(icon_id); @@ -1500,7 +1500,7 @@ static void icon_draw_rect(float x, /* sanity check */ if (w <= 0 || h <= 0 || w > 2000 || h > 2000) { printf("%s: icons are %i x %i pixels?\n", __func__, w, h); - BLI_assert(!"invalid icon size"); + BLI_assert_msg(0, "invalid icon size"); return; } /* modulate color */ @@ -1519,7 +1519,7 @@ static void icon_draw_rect(float x, draw_h = h; draw_x += (w - draw_w) / 2; } - /* if the image is squared, the draw_ initialization values are good */ + /* If the image is squared, the `draw_*` initialization values are good. */ /* first allocate imbuf for scaling and copy preview into it */ ima = IMB_allocImBuf(rw, rh, 32, IB_rect); @@ -2294,7 +2294,7 @@ int UI_icon_from_idcode(const int idcode) case ID_ME: return ICON_MESH_DATA; case ID_MSK: - return ICON_MOD_MASK; /* TODO! this would need its own icon! */ + return ICON_MOD_MASK; /* TODO: this would need its own icon! */ case ID_NT: return ICON_NODETREE; case ID_OB: @@ -2302,9 +2302,9 @@ int UI_icon_from_idcode(const int idcode) case ID_PA: return ICON_PARTICLE_DATA; case ID_PAL: - return ICON_COLOR; /* TODO! this would need its own icon! */ + return ICON_COLOR; /* TODO: this would need its own icon! */ case ID_PC: - return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */ + return ICON_CURVE_BEZCURVE; /* TODO: this would need its own icon! */ case ID_LP: return ICON_OUTLINER_DATA_LIGHTPROBE; case ID_SCE: diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 40a3f0d330f..40a9c67c630 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -137,19 +137,19 @@ extern const short ui_radial_dir_to_angle[8]; /** #PieMenuData.flags */ enum { - /** pie menu item collision is detected at 90 degrees */ + /** Pie menu item collision is detected at 90 degrees. */ UI_PIE_DEGREES_RANGE_LARGE = (1 << 0), - /** use initial center of pie menu to calculate direction */ + /** Use initial center of pie menu to calculate direction. */ UI_PIE_INITIAL_DIRECTION = (1 << 1), - /** pie menu is drag style */ + /** Pie menu is drag style. */ UI_PIE_DRAG_STYLE = (1 << 2), - /** mouse not far enough from center position */ + /** Mouse not far enough from center position. */ UI_PIE_INVALID_DIR = (1 << 3), - /** pie menu changed to click style, click to confirm */ + /** Pie menu changed to click style, click to confirm. */ UI_PIE_CLICK_STYLE = (1 << 4), - /** pie animation finished, do not calculate any more motion */ + /** Pie animation finished, do not calculate any more motion. */ UI_PIE_ANIMATION_FINISHED = (1 << 5), - /** pie gesture selection has been done, now wait for mouse motion to end */ + /** Pie gesture selection has been done, now wait for mouse motion to end. */ UI_PIE_GESTURE_END_WAIT = (1 << 6), }; @@ -221,7 +221,8 @@ struct uiBut { const char *tip; uiButToolTipFunc tip_func; - void *tip_argN; + void *tip_arg; + uiFreeArgFunc tip_arg_free; /** info on why button is disabled, displayed in tooltip */ const char *disabled_info; @@ -261,7 +262,7 @@ struct uiBut { ListBase extra_op_icons; /** #uiButExtraOpIcon */ - /* Draggable data, type is WM_DRAG_... */ + /* Drag-able data, type is WM_DRAG_... */ char dragtype; short dragflag; void *dragpoin; @@ -279,7 +280,7 @@ struct uiBut { float *editvec; uiButPushedStateFunc pushed_state_func; - void *pushed_state_arg; + const void *pushed_state_arg; /* pointer back */ uiBlock *block; @@ -316,7 +317,7 @@ typedef struct uiButSearch { void *item_active; void *arg; - uiButSearchArgFreeFn arg_free_fn; + uiFreeArgFunc arg_free_fn; uiButSearchContextMenuFn item_context_menu_fn; uiButSearchTooltipFn item_tooltip_fn; @@ -350,6 +351,15 @@ typedef struct uiButProgressbar { float progress; } uiButProgressbar; +/** Derived struct for #UI_BTYPE_DATASETROW. */ +typedef struct uiButDatasetRow { + uiBut but; + + uint8_t geometry_component_type; + uint8_t attribute_domain; + int indentation; +} uiButDatasetRow; + /** Derived struct for #UI_BTYPE_HSVCUBE. */ typedef struct uiButHSVCube { uiBut but; @@ -501,6 +511,9 @@ struct uiBlock { uiBlockHandleFunc handle_func; void *handle_func_arg; + /** Custom interaction data. */ + uiBlockInteraction_CallbackData custom_interaction_callbacks; + /** Custom extra event handling. */ int (*block_event_func)(const struct bContext *C, struct uiBlock *, const struct wmEvent *); @@ -695,7 +708,7 @@ struct uiPopupBlockCreate { uiBlockCreateFunc create_func; uiBlockHandleCreateFunc handle_create_func; void *arg; - void (*arg_free)(void *arg); + uiFreeArgFunc arg_free; int event_xy[2]; @@ -819,7 +832,7 @@ uiPopupBlockHandle *ui_popup_block_create(struct bContext *C, uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, void *arg, - void (*arg_free)(void *arg)); + uiFreeArgFunc arg_free); uiPopupBlockHandle *ui_popup_menu_create(struct bContext *C, struct ARegion *butregion, uiBut *but, @@ -934,9 +947,7 @@ extern void ui_but_execute_end(struct bContext *C, void *active_back); extern void ui_but_active_free(const struct bContext *C, uiBut *but); extern int ui_but_menu_direction(uiBut *but); -extern void ui_but_text_password_hide(char password_str[UI_MAX_DRAW_STR], - uiBut *but, - const bool restore); +extern void ui_but_text_password_hide(char password_str[128], uiBut *but, const bool restore); extern uiBut *ui_but_find_select_in_enum(uiBut *but, int direction); bool ui_but_is_editing(const uiBut *but); float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 8f2871ce18b..8b9539f1d33 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -169,7 +169,7 @@ struct uiLayout { bool enabled; bool redalert; bool keepaspect; - /** For layouts inside gridflow, they and their items shall never have a fixed maximal size. */ + /** For layouts inside grid-flow, they and their items shall never have a fixed maximal size. */ bool variable_size; char alignment; eUIEmbossType emboss; @@ -643,7 +643,7 @@ static void ui_item_array(uiLayout *layout, NULL); } else { - /* note, this block of code is a bit arbitrary and has just been made + /* NOTE: this block of code is a bit arbitrary and has just been made * to work with common cases, but may need to be re-worked */ /* special case, boolean array in a menu, this could be used in a more generic way too */ @@ -662,7 +662,7 @@ static void ui_item_array(uiLayout *layout, } } - /* show checkboxes for rna on a non-emboss block (menu for eg) */ + /* Show check-boxes for rna on a non-emboss block (menu for eg). */ bool *boolarr = NULL; if (type == PROP_BOOLEAN && ELEM(layout->root->block->emboss, UI_EMBOSS_NONE, UI_EMBOSS_PULLDOWN)) { @@ -1191,7 +1191,7 @@ static uiBut *uiItemFullO_ptr_ex(uiLayout *layout, const eUIEmbossType prev_emboss = layout->emboss; if (flag & UI_ITEM_R_NO_BG) { - layout->emboss = UI_EMBOSS_NONE; + layout->emboss = UI_EMBOSS_NONE_OR_STATUS; } /* create the button */ @@ -1411,7 +1411,7 @@ BLI_INLINE bool ui_layout_is_radial(const uiLayout *layout) } /** - * Create ui items for enum items in \a item_array. + * Create UI items for enum items in \a item_array. * * A version of #uiItemsFullEnumO that takes pre-calculated item array. */ @@ -1818,7 +1818,7 @@ static void ui_item_rna_size(uiLayout *layout, } else if (type == PROP_BOOLEAN) { if (icon == ICON_NONE) { - /* Exception for checkboxes, they need a little less space to align nicely. */ + /* Exception for check-boxes, they need a little less space to align nicely. */ is_checkbox_only = true; } icon = ICON_DOT; @@ -1984,7 +1984,7 @@ void uiItemFullR(uiLayout *layout, * a label to display in the first column, the heading is inserted there. Otherwise it's inserted * as a new row before the first item. */ uiLayout *heading_layout = ui_layout_heading_find(layout); - /* Although checkboxes use the split layout, they are an exception and should only place their + /* Although check-boxes use the split layout, they are an exception and should only place their * label in the second column, to not make that almost empty. * * Keep using 'use_prop_sep' instead of disabling it entirely because @@ -2062,7 +2062,7 @@ void uiItemFullR(uiLayout *layout, /* Menus and pie-menus don't show checkbox without this. */ if ((layout->root->type == UI_LAYOUT_MENU) || - /* Use checkboxes only as a fallback in pie-menu's, when no icon is defined. */ + /* Use check-boxes only as a fallback in pie-menu's, when no icon is defined. */ ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) { const int prop_flag = RNA_property_flag(prop); if (type == PROP_BOOLEAN) { @@ -2122,7 +2122,7 @@ void uiItemFullR(uiLayout *layout, const eUIEmbossType prev_emboss = layout->emboss; if (no_bg) { - layout->emboss = UI_EMBOSS_NONE; + layout->emboss = UI_EMBOSS_NONE_OR_STATUS; } uiBut *but = NULL; @@ -2346,16 +2346,16 @@ void uiItemFullR(uiLayout *layout, * In this case we want the ability not to have an icon. * * We could pass an argument not to set the icon to begin with however this is the one case - * the functionality is needed. */ + * the functionality is needed. */ if (but && no_icon) { if ((icon == ICON_NONE) && (but->icon != ICON_NONE)) { ui_def_but_icon_clear(but); } } - /* Mark non-embossed textfields inside a listbox. */ + /* Mark non-embossed text-fields inside a list-box. */ if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) && - (but->emboss & UI_EMBOSS_NONE)) { + ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS)) { UI_but_flag_enable(but, UI_BUT_LIST_ITEM); } @@ -2831,7 +2831,7 @@ void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt) PanelType *pt = (PanelType *)arg_pt; UI_paneltype_draw(C, pt, layout); - /* panels are created flipped (from event handling pov) */ + /* Panels are created flipped (from event handling POV). */ layout->root->block->flag ^= UI_BLOCK_IS_FLIP; } @@ -2860,7 +2860,7 @@ static uiBut *ui_item_menu(uiLayout *layout, int w = ui_text_icon_width(layout, name, icon, 1); const int h = UI_UNIT_Y; - if (layout->root->type == UI_LAYOUT_HEADER) { /* ugly .. */ + if (layout->root->type == UI_LAYOUT_HEADER) { /* Ugly! */ if (icon == ICON_NONE && force_menu) { /* pass */ } @@ -2893,7 +2893,7 @@ static uiBut *ui_item_menu(uiLayout *layout, } if (argN) { - /* ugly .. */ + /* ugly! */ if (arg != argN) { but->poin = (char *)but; } @@ -3147,7 +3147,7 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon) but->drawflag |= UI_BUT_TEXT_RIGHT; } - /* Mark as a label inside a listbox. */ + /* Mark as a label inside a list-box. */ if (block->flag & UI_BLOCK_LIST_ITEM) { but->flag |= UI_BUT_LIST_ITEM; } @@ -3381,10 +3381,13 @@ typedef struct MenuItemLevel { static void menu_item_enum_opname_menu(bContext *UNUSED(C), uiLayout *layout, void *arg) { - MenuItemLevel *lvl = (MenuItemLevel *)(((uiBut *)arg)->func_argN); + uiBut *but = arg; + MenuItemLevel *lvl = but->func_argN; + /* Use the operator properties from the button owning the menu. */ + IDProperty *op_props = but->opptr ? but->opptr->data : NULL; uiLayoutSetOperatorContext(layout, lvl->opcontext); - uiItemsEnumO(layout, lvl->opname, lvl->propname); + uiItemsFullEnumO(layout, lvl->opname, lvl->propname, op_props, lvl->opcontext, 0); layout->root->block->flag |= UI_BLOCK_IS_FLIP; @@ -3392,12 +3395,13 @@ static void menu_item_enum_opname_menu(bContext *UNUSED(C), uiLayout *layout, vo UI_block_direction_set(layout->root->block, UI_DIR_DOWN); } -void uiItemMenuEnumO_ptr(uiLayout *layout, - bContext *C, - wmOperatorType *ot, - const char *propname, - const char *name, - int icon) +void uiItemMenuEnumFullO_ptr(uiLayout *layout, + bContext *C, + wmOperatorType *ot, + const char *propname, + const char *name, + int icon, + PointerRNA *r_opptr) { /* Caller must check */ BLI_assert(ot->srna != NULL); @@ -3416,6 +3420,15 @@ void uiItemMenuEnumO_ptr(uiLayout *layout, lvl->opcontext = layout->root->opcontext; uiBut *but = ui_item_menu(layout, name, icon, menu_item_enum_opname_menu, NULL, lvl, NULL, true); + /* Use the menu button as owner for the operator properties, which will then be passed to the + * individual menu items. */ + if (r_opptr) { + but->opptr = MEM_callocN(sizeof(PointerRNA), "uiButOpPtr"); + WM_operator_properties_create_ptr(but->opptr, ot); + BLI_assert(but->opptr->data == NULL); + WM_operator_properties_alloc(&but->opptr, (IDProperty **)&but->opptr->data, ot->idname); + *r_opptr = *but->opptr; + } /* add hotkey here, lower UI code can't detect it */ if ((layout->root->block->flag & UI_BLOCK_LOOP) && (ot->prop && ot->invoke)) { @@ -3427,12 +3440,13 @@ void uiItemMenuEnumO_ptr(uiLayout *layout, } } -void uiItemMenuEnumO(uiLayout *layout, - bContext *C, - const char *opname, - const char *propname, - const char *name, - int icon) +void uiItemMenuEnumFullO(uiLayout *layout, + bContext *C, + const char *opname, + const char *propname, + const char *name, + int icon, + PointerRNA *r_opptr) { wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */ @@ -3444,7 +3458,17 @@ void uiItemMenuEnumO(uiLayout *layout, return; } - uiItemMenuEnumO_ptr(layout, C, ot, propname, name, icon); + uiItemMenuEnumFullO_ptr(layout, C, ot, propname, name, icon, r_opptr); +} + +void uiItemMenuEnumO(uiLayout *layout, + bContext *C, + const char *opname, + const char *propname, + const char *name, + int icon) +{ + uiItemMenuEnumFullO(layout, C, opname, propname, name, icon, NULL); } static void menu_item_enum_rna_menu(bContext *UNUSED(C), uiLayout *layout, void *arg) @@ -4042,12 +4066,11 @@ static void ui_litem_layout_column_flow(uiLayout *litem) int emy = 0; int miny = 0; - int w = litem->w - (flow->totcol - 1) * style->columnspace; emh = toth / flow->totcol; /* create column per column */ col = 0; - w = (litem->w - (flow->totcol - 1) * style->columnspace) / flow->totcol; + int w = (litem->w - (flow->totcol - 1) * style->columnspace) / flow->totcol; LISTBASE_FOREACH (uiItem *, item, &litem->items) { ui_item_size(item, &itemw, &itemh); @@ -4616,7 +4639,7 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali { litem->root = layout->root; litem->align = align; - /* Children of gridflow layout shall never have "ideal big size" returned as estimated size. */ + /* Children of grid-flow layout shall never have "ideal big size" returned as estimated size. */ litem->variable_size = layout->variable_size || layout->item.type == ITEM_LAYOUT_GRID_FLOW; litem->active = true; litem->enabled = true; diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 0cf3ad59903..4afe232e33e 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -803,7 +803,7 @@ bool UI_context_copy_to_selected_list(bContext *C, } else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) { /* Special case when we do this for 'Sequence.lock'. - * (if the sequence is locked, it wont be in "selected_editable_sequences"). */ + * (if the sequence is locked, it won't be in "selected_editable_sequences"). */ const char *prop_id = RNA_property_identifier(prop); if (STREQ(prop_id, "lock")) { *r_lb = CTX_data_collection_get(C, "selected_sequences"); @@ -921,7 +921,7 @@ bool UI_context_copy_to_selected_list(bContext *C, * to handle situations like T41062... */ if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence)) != NULL) { /* Special case when we do this for 'Sequence.lock'. - * (if the sequence is locked, it wont be in "selected_editable_sequences"). */ + * (if the sequence is locked, it won't be in "selected_editable_sequences"). */ const char *prop_id = RNA_property_identifier(prop); if (STREQ(prop_id, "lock")) { *r_lb = CTX_data_collection_get(C, "selected_sequences"); @@ -1215,7 +1215,7 @@ static void UI_OT_jump_to_target_button(wmOperatorType *ot) /* ------------------------------------------------------------------------- */ /* EditSource Utility funcs and operator, - * note, this includes utility functions and button matching checks */ + * NOTE: this includes utility functions and button matching checks. */ typedef struct uiEditSourceStore { uiBut but_orig; @@ -1340,7 +1340,7 @@ static int editsource_text_edit(bContext *C, txt_move_toline(text, line - 1, false); /* naughty!, find text area to set, not good behavior - * but since this is a dev tool lets allow it - campbell */ + * but since this is a developer tool lets allow it - campbell */ ScrArea *area = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TEXT, 0); if (area) { SpaceText *st = area->spacedata.first; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 6505a7cd76a..38dc91fb57f 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -258,7 +258,7 @@ static Panel *panel_add_instanced(ARegion *region, /* Make sure the panel is added to the end of the display-order as well. This is needed for * loading existing files. * - * Note: We could use special behavior to place it after the panel that starts the list of + * NOTE: We could use special behavior to place it after the panel that starts the list of * instanced panels, but that would add complexity that isn't needed for now. */ int max_sortorder = 0; LISTBASE_FOREACH (Panel *, existing_panel, panels) { @@ -674,7 +674,7 @@ static bool panel_type_context_poll(ARegion *region, const PanelType *panel_type, const char *context) { - if (UI_panel_category_is_visible(region)) { + if (!BLI_listbase_is_empty(®ion->panels_category)) { return STREQ(panel_type->category, UI_panel_category_active_get(region, false)); } @@ -1188,7 +1188,6 @@ static void panel_draw_aligned_widgets(const uiStyle *style, /* Draw text label. */ if (panel->drawname[0] != '\0') { - /* + 0.001f to avoid flirting with float inaccuracy .*/ const rcti title_rect = { .xmin = widget_rect.xmin + (panel->labelofs / aspect) + scaled_unit * 1.1f, .xmax = widget_rect.xmax, @@ -1893,7 +1892,7 @@ static void ui_do_animate(bContext *C, Panel *panel) } else { if (UI_panel_is_dragging(panel)) { - /* Note: doing this in #panel_activate_state would require + /* NOTE: doing this in #panel_activate_state would require * removing `const` for context in many other places. */ reorder_instanced_panel_list(C, region, panel); } @@ -2564,7 +2563,7 @@ PointerRNA *UI_region_panel_custom_data_under_cursor(const bContext *C, const wm /** \name Window Level Modal Panel Interaction * \{ */ -/* Note, this is modal handler and should not swallow events for animation. */ +/* NOTE: this is modal handler and should not swallow events for animation. */ static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata) { Panel *panel = userdata; diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c index aa10d092f5e..025c242d0fc 100644 --- a/source/blender/editors/interface/interface_query.c +++ b/source/blender/editors/interface/interface_query.c @@ -67,7 +67,8 @@ bool ui_but_is_toggle(const uiBut *but) UI_BTYPE_TOGGLE_N, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, - UI_BTYPE_ROW); + UI_BTYPE_ROW, + UI_BTYPE_DATASETROW); } /** @@ -77,7 +78,7 @@ bool ui_but_is_toggle(const uiBut *but) */ bool ui_but_is_interactive(const uiBut *but, const bool labeledit) { - /* note, UI_BTYPE_LABEL is included for highlights, this allows drags */ + /* NOTE: #UI_BTYPE_LABEL is included for highlights, this allows drags. */ if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == NULL) { return false; } @@ -90,7 +91,8 @@ bool ui_but_is_interactive(const uiBut *but, const bool labeledit) if (but->flag & UI_SCROLLED) { return false; } - if ((but->type == UI_BTYPE_TEXT) && (but->emboss == UI_EMBOSS_NONE) && !labeledit) { + if ((but->type == UI_BTYPE_TEXT) && + (ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS)) && !labeledit) { return false; } if ((but->type == UI_BTYPE_LISTROW) && labeledit) { diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c index e68705e4321..48952c4f121 100644 --- a/source/blender/editors/interface/interface_region_color_picker.c +++ b/source/blender/editors/interface/interface_region_color_picker.c @@ -624,7 +624,7 @@ static void ui_block_colorpicker(uiBlock *block, bt->custom_data = cpicker; } - /* Note: don't disable UI_BUT_UNDO for RGBA values, since these don't add undo steps. */ + /* NOTE: don't disable UI_BUT_UNDO for RGBA values, since these don't add undo steps. */ /* RGB values */ UI_block_align_begin(block); diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c index 58a74a3473e..d3c1a97e957 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.c +++ b/source/blender/editors/interface/interface_region_menu_popup.c @@ -403,7 +403,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C, pup->layout = UI_block_layout( pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); - /* note, this intentionally differs from the menu & sub-menu default because many operators + /* NOTE: this intentionally differs from the menu & sub-menu default because many operators * use popups like this to select one of their options - * where having invoke doesn't make sense */ uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN); @@ -591,7 +591,7 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports) * \{ */ void UI_popup_block_invoke_ex( - bContext *C, uiBlockCreateFunc func, void *arg, void (*arg_free)(void *arg), bool can_refresh) + bContext *C, uiBlockCreateFunc func, void *arg, uiFreeArgFunc arg_free, bool can_refresh) { wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *handle; @@ -608,10 +608,7 @@ void UI_popup_block_invoke_ex( WM_event_add_mousemove(window); } -void UI_popup_block_invoke(bContext *C, - uiBlockCreateFunc func, - void *arg, - void (*arg_free)(void *arg)) +void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg, uiFreeArgFunc arg_free) { UI_popup_block_invoke_ex(C, func, arg, arg_free, true); } diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c index a9f72233cb1..b8c4d8ddb09 100644 --- a/source/blender/editors/interface/interface_region_popover.c +++ b/source/blender/editors/interface/interface_region_popover.c @@ -420,7 +420,7 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap) * For now close this style of popovers when accessed. */ UI_block_flag_disable(pup->block, UI_BLOCK_KEEP_OPEN); - /* panels are created flipped (from event handling pov) */ + /* Panels are created flipped (from event handling POV). */ pup->block->flag ^= UI_BLOCK_IS_FLIP; } diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index 8135f5a203e..55a162c883a 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -341,7 +341,7 @@ static void ui_popup_block_position(wmWindow *window, block->safety.ymax = block->rect.ymax + s1; } - /* exception for switched pulldowns... */ + /* Exception for switched pull-downs. */ if (dir1 && (dir1 & block->direction) == 0) { if (dir2 == UI_DIR_RIGHT) { block->safety.xmax = block->rect.xmax + s2; @@ -773,7 +773,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, void *arg, - void (*arg_free)(void *arg)) + uiFreeArgFunc arg_free) { wmWindow *window = CTX_wm_window(C); uiBut *activebut = UI_context_active_but_get(C); diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index 987cde61f97..c35dbc5d7a6 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -95,7 +95,7 @@ typedef struct uiSearchboxData { /** draw thumbnail previews, rather than list */ bool preview; /** Use the #UI_SEP_CHAR char for splitting shortcuts (good for operators, bad for data). */ - bool use_sep; + bool use_shortcut_sep; int prv_rows, prv_cols; /** * Show the active icon and text after the last instance of this string. @@ -314,7 +314,7 @@ bool ui_searchbox_apply(uiBut *but, ARegion *region) data->items.name_prefix_offsets[data->active] : 0); - const char *name_sep = data->use_sep ? strrchr(name, UI_SEP_CHAR) : NULL; + const char *name_sep = data->use_shortcut_sep ? strrchr(name, UI_SEP_CHAR) : NULL; BLI_strncpy(but->editstr, name, name_sep ? (name_sep - name) + 1 : data->items.maxstrlen); @@ -535,7 +535,7 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re /* Never include the prefix in the button. */ (data->items.name_prefix_offsets ? data->items.name_prefix_offsets[a] : 0); - const char *name_sep = data->use_sep ? strrchr(name, UI_SEP_CHAR) : NULL; + const char *name_sep = data->use_shortcut_sep ? strrchr(name, UI_SEP_CHAR) : NULL; if (STREQLEN(but->editstr, name, name_sep ? (name_sep - name) : data->items.maxstrlen)) { data->active = a; break; @@ -627,7 +627,7 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region) char *name_sep_test = NULL; uiMenuItemSeparatorType separator_type = UI_MENU_ITEM_SEPARATOR_NONE; - if (data->use_sep) { + if (data->use_shortcut_sep) { separator_type = UI_MENU_ITEM_SEPARATOR_SHORTCUT; } /* Only set for displaying additional hint (e.g. library name of a linked data-block). */ @@ -719,7 +719,10 @@ static void ui_searchbox_region_free_cb(ARegion *region) region->regiondata = NULL; } -ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiButSearch *search_but) +static ARegion *ui_searchbox_create_generic_ex(bContext *C, + ARegion *butregion, + uiButSearch *search_but, + const bool use_shortcut_sep) { wmWindow *win = CTX_wm_window(C); const uiStyle *style = UI_style_get(); @@ -759,12 +762,8 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiButSearc data->prv_cols = but->a2; } - /* Only show key shortcuts when needed (checking RNA prop pointer is useless here, a lot of - * buttons are about data without having that pointer defined, let's rather try with optype!). - * One can also enforce that behavior by setting - * UI_BUT_HAS_SHORTCUT drawflag of search button. */ - if (but->optype != NULL || (but->drawflag & UI_BUT_HAS_SHORTCUT) != 0) { - data->use_sep = true; + if (but->optype != NULL || use_shortcut_sep) { + data->use_shortcut_sep = true; } data->sep_string = search_but->item_sep_string; @@ -888,6 +887,11 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiButSearc return region; } +ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiButSearch *search_but) +{ + return ui_searchbox_create_generic_ex(C, butregion, search_but, false); +} + /** * Similar to Python's `str.title` except... * @@ -973,8 +977,8 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe data->items.names[a], 0, state, - data->use_sep ? UI_MENU_ITEM_SEPARATOR_SHORTCUT : - UI_MENU_ITEM_SEPARATOR_NONE, + data->use_shortcut_sep ? UI_MENU_ITEM_SEPARATOR_SHORTCUT : + UI_MENU_ITEM_SEPARATOR_NONE, NULL); } } @@ -996,8 +1000,7 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe ARegion *ui_searchbox_create_operator(bContext *C, ARegion *butregion, uiButSearch *search_but) { - UI_but_drawflag_enable(&search_but->but, UI_BUT_HAS_SHORTCUT); - ARegion *region = ui_searchbox_create_generic(C, butregion, search_but); + ARegion *region = ui_searchbox_create_generic_ex(C, butregion, search_but, true); region->type->draw = ui_searchbox_region_draw_cb__operator; @@ -1016,8 +1019,7 @@ static void ui_searchbox_region_draw_cb__menu(const bContext *UNUSED(C), ARegion ARegion *ui_searchbox_create_menu(bContext *C, ARegion *butregion, uiButSearch *search_but) { - UI_but_drawflag_enable(&search_but->but, UI_BUT_HAS_SHORTCUT); - ARegion *region = ui_searchbox_create_generic(C, butregion, search_but); + ARegion *region = ui_searchbox_create_generic_ex(C, butregion, search_but, true); if (false) { region->type->draw = ui_searchbox_region_draw_cb__menu; diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index accfb78ab94..10bc3760b42 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -188,11 +188,11 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *region /* tone_fg = rgb_to_grayscale(main_color); */ /* mix the colors */ - rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* light gray */ - rgb_tint(active_color, 0.6f, 0.2f, tone_bg, 0.2f); /* light blue */ - rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.4f); /* gray */ - rgb_tint(python_color, 0.0f, 0.0f, tone_bg, 0.5f); /* dark gray */ - rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* red */ + rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* Light gray. */ + rgb_tint(active_color, 0.6f, 0.2f, tone_bg, 0.2f); /* Light blue. */ + rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.4f); /* Gray. */ + rgb_tint(python_color, 0.0f, 0.0f, tone_bg, 0.5f); /* Dark gray. */ + rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* Red. */ /* draw text */ BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width); @@ -435,7 +435,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is } } else { - /* Note, this is an exceptional case, we could even remove it + /* NOTE: this is an exceptional case, we could even remove it * however there have been reports of tooltips failing, so keep it for now. */ expr_result = BLI_strdup(IFACE_("Internal error!")); is_error = true; @@ -492,7 +492,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is } } else { - /* Note, this is an exceptional case, we could even remove it + /* NOTE: this is an exceptional case, we could even remove it * however there have been reports of tooltips failing, so keep it for now. */ expr_result = BLI_strdup(TIP_("Internal error!")); is_error = true; @@ -574,7 +574,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is shortcut_toolbar, ARRAY_SIZE(shortcut_toolbar))) { /* Generate keymap in order to inspect it. - * Note, we could make a utility to avoid the keymap generation part of this. */ + * NOTE: we could make a utility to avoid the keymap generation part of this. */ const char *expr_imports[] = { "bpy", "bl_keymap_utils", "bl_keymap_utils.keymap_from_toolbar", NULL}; const char *expr = diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index ad0c523a594..88ab6a377d0 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -245,7 +245,7 @@ void UI_fontstyle_draw_rotated(const uiFontStyle *fs, /* ignore UI_STYLE, always aligned to top */ - /* rotate counter-clockwise for now (assumes left-to-right language)*/ + /* Rotate counter-clockwise for now (assumes left-to-right language). */ xofs += height; yofs = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX) + 5; angle = M_PI_2; diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c index 91ad6619889..f01dca7712c 100644 --- a/source/blender/editors/interface/interface_template_search_menu.c +++ b/source/blender/editors/interface/interface_template_search_menu.c @@ -873,7 +873,7 @@ static struct MenuSearch_Data *menu_items_from_ui_create( /* Finally sort menu items. * - * Note: we might want to keep the in-menu order, for now sort all. */ + * NOTE: we might want to keep the in-menu order, for now sort all. */ BLI_listbase_sort(&data->items, menu_item_sort_by_drawstr_full); BLI_ghash_free(menu_parent_map, NULL, NULL); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index e3df9704826..9c17486aea4 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -344,7 +344,7 @@ typedef struct TemplateID { float scale; } TemplateID; -/* Search browse menu, assign */ +/* Search browse menu, assign. */ static void template_ID_set_property_exec_fn(bContext *C, void *arg_template, void *item) { TemplateID *template_ui = (TemplateID *)arg_template; @@ -653,7 +653,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) /* Only remap that specific ID usage to overriding local data-block. */ ID *override_id = BKE_lib_override_library_create_from_id(bmain, id, false); if (override_id != NULL) { - BKE_main_id_clear_newpoins(bmain); + BKE_main_id_newptr_and_tag_clear(bmain); if (GS(override_id->name) == ID_OB) { Scene *scene = CTX_data_scene(C); @@ -672,9 +672,9 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) } else { if (BKE_lib_id_make_local(bmain, id, false, 0)) { - BKE_main_id_clear_newpoins(bmain); + BKE_main_id_newptr_and_tag_clear(bmain); - /* reassign to get get proper updates/notifiers */ + /* Reassign to get proper updates/notifiers. */ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); undo_push_label = "Make Local"; } @@ -687,8 +687,8 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) break; case UI_ID_OVERRIDE: if (id && ID_IS_OVERRIDE_LIBRARY(id)) { - BKE_lib_override_library_free(&id->override_library, true); - /* reassign to get get proper updates/notifiers */ + BKE_lib_override_library_make_local(id); + /* Reassign to get proper updates/notifiers. */ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); @@ -877,7 +877,7 @@ static uiBut *template_id_def_new_but(uiBlock *block, BLT_I18NCONTEXT_ID_POINTCLOUD, BLT_I18NCONTEXT_ID_VOLUME, BLT_I18NCONTEXT_ID_SIMULATION, ); - /* Note: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters, + /* NOTE: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters, * check the definition to see if a new call must be added when the limit * is exceeded. */ @@ -1078,7 +1078,7 @@ static void template_ID(const bContext *C, char numstr[32]; short numstr_len; - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", ID_REAL_USERS(id)); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", ID_REAL_USERS(id)); but = uiDefBut( block, @@ -2399,8 +2399,8 @@ static eAutoPropButsReturn template_operator_property_buts_draw_single( op->type->ui((bContext *)C, op); op->layout = NULL; - /* UI_LAYOUT_OP_SHOW_EMPTY ignored. retun_info is ignored too. We could - * allow ot.ui callback to return this, but not needed right now. */ + /* #UI_LAYOUT_OP_SHOW_EMPTY ignored. retun_info is ignored too. + * We could allow #wmOperatorType.ui callback to return this, but not needed right now. */ } else { wmWindowManager *wm = CTX_wm_manager(C); @@ -2556,7 +2556,7 @@ void uiTemplateOperatorPropertyButs( wmWindowManager *wm = CTX_wm_manager(C); /* If there are only checkbox items, don't use split layout by default. It looks weird if the - * checkboxes only use half the width. */ + * check-boxes only use half the width. */ if (ui_layout_operator_properties_only_booleans(C, wm, op, flag)) { flag |= UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT; } @@ -3050,7 +3050,7 @@ static void colorband_flip_cb(bContext *C, ColorBand *coba) coba->data[a] = data_tmp[a]; } - /* may as well flip the cur*/ + /* May as well flip the `cur`. */ coba->cur = coba->tot - (coba->cur + 1); ED_undo_push(C, "Flip Color Ramp"); @@ -4015,23 +4015,23 @@ static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event) case UICURVE_FUNC_RESET_VIEW: BKE_curvemapping_reset_view(cumap); break; - case UICURVE_FUNC_HANDLE_VECTOR: /* set vector */ + case UICURVE_FUNC_HANDLE_VECTOR: /* Set vector. */ BKE_curvemap_handle_set(cuma, HD_VECT); BKE_curvemapping_changed(cumap, false); break; - case UICURVE_FUNC_HANDLE_AUTO: /* set auto */ + case UICURVE_FUNC_HANDLE_AUTO: /* Set auto. */ BKE_curvemap_handle_set(cuma, HD_AUTO); BKE_curvemapping_changed(cumap, false); break; - case UICURVE_FUNC_HANDLE_AUTO_ANIM: /* set auto-clamped */ + case UICURVE_FUNC_HANDLE_AUTO_ANIM: /* Set auto-clamped. */ BKE_curvemap_handle_set(cuma, HD_AUTO_ANIM); BKE_curvemapping_changed(cumap, false); break; - case UICURVE_FUNC_EXTEND_HOZ: /* extend horiz */ + case UICURVE_FUNC_EXTEND_HOZ: /* Extend horizontal. */ cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; BKE_curvemapping_changed(cumap, false); break; - case UICURVE_FUNC_EXTEND_EXP: /* extend extrapolate */ + case UICURVE_FUNC_EXTEND_EXP: /* Extend extrapolate. */ cumap->flag |= CUMA_EXTEND_EXTRAPOLATE; BKE_curvemapping_changed(cumap, false); break; @@ -5805,7 +5805,7 @@ static void uilist_filter_items_default(struct uiList *ui_list, if (order_by_name) { int new_idx; - /* note: order_idx equals either to ui_list->items_len if no filtering done, + /* NOTE: order_idx equals either to ui_list->items_len if no filtering done, * or to ui_list->items_shown if filter is enabled, * or to (ui_list->items_len - ui_list->items_shown) if filtered items are excluded. * This way, we only sort items we actually intend to draw! @@ -5883,7 +5883,7 @@ static void uilist_prepare(uiList *ui_list, } /* If list length changes or list is tagged to check this, - * and active is out of view, scroll to it .*/ + * and active is out of view, scroll to it. */ if (ui_list->list_last_len != len || ui_list->flag & UILST_SCROLL_TO_ACTIVE_ITEM) { if (activei_row < ui_list->list_scroll) { ui_list->list_scroll = activei_row; @@ -6205,7 +6205,7 @@ void uiTemplateList(uiLayout *layout, 0, TIP_("Double click to rename")); if ((dyntip_data = uilist_item_use_dynamic_tooltip(itemptr, item_dyntip_propname))) { - UI_but_func_tooltip_set(but, uilist_item_tooltip_func, dyntip_data); + UI_but_func_tooltip_set(but, uilist_item_tooltip_func, dyntip_data, MEM_freeN); } sub = uiLayoutRow(overlap, false); @@ -6762,7 +6762,7 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C) NULL); but_progress->progress = progress; - UI_but_func_tooltip_set(&but_progress->but, progress_tooltip_func, tip_arg); + UI_but_func_tooltip_set(&but_progress->but, progress_tooltip_func, tip_arg, MEM_freeN); } if (!wm->is_interface_locked) { diff --git a/source/blender/editors/interface/interface_undo.c b/source/blender/editors/interface/interface_undo.c index 304d2254a81..40f196d9b45 100644 --- a/source/blender/editors/interface/interface_undo.c +++ b/source/blender/editors/interface/interface_undo.c @@ -107,7 +107,7 @@ void ui_textedit_undo_push(uiUndoStack_Text *stack, const char *text, int cursor } } - /* Create the new state */ + /* Create the new state. */ const int text_size = strlen(text) + 1; stack->current = MEM_mallocN(sizeof(uiUndoStack_Text_State) + text_size, __func__); stack->current->cursor_index = cursor_index; diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 6ad1de68a1f..7ea02226f02 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -701,7 +701,7 @@ int UI_calc_float_precision(int prec, double value) /* Check on the number of decimal places need to display the number, * this is so 0.00001 is not displayed as 0.00, - * _but_, this is only for small values si 10.0001 will not get the same treatment. + * _but_, this is only for small values as 10.0001 will not get the same treatment. */ value = fabs(value); if ((value < pow10_neg[prec]) && (value > (1.0 / max_pow))) { @@ -932,7 +932,7 @@ void UI_butstore_update(uiBlock *block) uiBut *but_new = ui_but_find_new(block, *bs_elem->but_p); /* can be NULL if the buttons removed, - * note: we could allow passing in a callback when buttons are removed + * NOTE: we could allow passing in a callback when buttons are removed * so the caller can cleanup */ *bs_elem->but_p = but_new; } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index d2e6165a20f..8abff4ad0d8 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -113,6 +113,7 @@ typedef enum { UI_WTYPE_LISTITEM, UI_WTYPE_PROGRESSBAR, UI_WTYPE_NODESOCKET, + UI_WTYPE_DATASETROW, } uiWidgetTypeEnum; /* Button state argument shares bits with 'uiBut.flag'. @@ -236,7 +237,7 @@ typedef struct uiWidgetTrias { #define WIDGET_SIZE_MAX (WIDGET_CURVE_RESOLU * 4) typedef struct uiWidgetBase { - /* TODO remove these completely */ + /* TODO: remove these completely. */ int totvert, halfwayvert; float outer_v[WIDGET_SIZE_MAX][2]; float inner_v[WIDGET_SIZE_MAX][2]; @@ -398,7 +399,7 @@ static struct { GPUBatch *roundbox_widget; GPUBatch *roundbox_shadow; - /* TODO remove */ + /* TODO: remove. */ GPUVertFormat format; uint vflag_id; } g_ui_batch_cache = {0}; @@ -522,7 +523,7 @@ void UI_draw_anti_tria( float draw_color[4]; copy_v4_v4(draw_color, color); - /* Note: This won't give back the original color. */ + /* NOTE: This won't give back the original color. */ draw_color[3] *= 1.0f / WIDGET_AA_JITTER; GPU_blend(GPU_BLEND_ALPHA); @@ -767,7 +768,7 @@ static void round_box__edges( BLI_rctf_rcti_copy(&wt->uniform_params.rect, rect); BLI_rctf_init(&wt->uniform_params.recti, minxi, maxxi, minyi, maxyi); - /* mult */ + /* Multiply by radius. */ for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) { veci[a][0] = radi * cornervec[a][0]; veci[a][1] = radi * cornervec[a][1]; @@ -1376,8 +1377,6 @@ static int ui_but_draw_menu_icon(const uiBut *but) static void widget_draw_icon( const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, const uchar mono_color[4]) { - float xs = 0.0f, ys = 0.0f; - if (but->flag & UI_BUT_ICON_PREVIEW) { GPU_blend(GPU_BLEND_ALPHA); widget_draw_preview(icon, alpha, rect); @@ -1419,6 +1418,7 @@ static void widget_draw_icon( if (icon && icon != ICON_BLANK1) { const float ofs = 1.0f / aspect; + float xs, ys; if (but->drawflag & UI_BUT_ICON_LEFT) { /* special case - icon_only pie buttons */ @@ -1531,14 +1531,14 @@ static void ui_text_clip_right_ex(const uiFontStyle *fstyle, 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. */ + /* 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) + sep_len; } } else { - /* Otherwise fit as much as we can without adding an ellipsis. */ + /* 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) { @@ -1640,7 +1640,7 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle, /* Corner case, the str already takes all available mem, * and the ellipsis chars would actually add more chars. * Better to just trim one or two letters to the right in this case... - * Note: with a single-char ellipsis, this should never happen! But better be safe + * NOTE: with a single-char ellipsis, this should never happen! But better be safe * here... */ ui_text_clip_right_ex( @@ -1930,19 +1930,27 @@ static void widget_draw_text_ime_underline(const uiFontStyle *fstyle, } #endif /* WITH_INPUT_IME */ -static bool widget_draw_text_underline_calc_center_x(const char *UNUSED(str), +struct UnderlineData { + size_t str_offset; /* The string offset of the underlined character. */ + int width_px; /* The underline width in pixels. */ + int r_offset_px[2]; /* Write the X,Y offset here. */ +}; + +static bool widget_draw_text_underline_calc_position(const char *UNUSED(str), const size_t str_step_ofs, const rcti *glyph_step_bounds, const int UNUSED(glyph_advance_x), const rctf *glyph_bounds, - const int glyph_bearing[2], + const int UNUSED(glyph_bearing[2]), void *user_data) { - /* The index of the character to get, set to the x-position. */ - int *ul_data = user_data; - if (ul_data[0] == (int)str_step_ofs) { - ul_data[1] = glyph_step_bounds->xmin + glyph_bearing[0] + - (BLI_rctf_size_x(glyph_bounds) / 2.0f); + struct UnderlineData *ul_data = user_data; + if (ul_data->str_offset == str_step_ofs) { + /* Full width of this glyph including both bearings. */ + const float width = glyph_bounds->xmin + BLI_rctf_size_x(glyph_bounds) + glyph_bounds->xmin; + ul_data->r_offset_px[0] = glyph_step_bounds->xmin + ((width - ul_data->width_px) * 0.5f); + /* One line-width below the lower glyph bounds. */ + ul_data->r_offset_px[1] = glyph_bounds->ymin - U.pixelsize; /* Early exit. */ return false; } @@ -1997,14 +2005,15 @@ static void widget_draw_text(const uiFontStyle *fstyle, drawstr_left_len = INT_MAX; #ifdef WITH_INPUT_IME - /* FIXME, IME is modifying 'const char *drawstr! */ + /* FIXME: IME is modifying `const char *drawstr`! */ ime_data = ui_but_ime_data_get(but); if (ime_data && ime_data->composite_len) { /* insert composite string into cursor pos */ BLI_snprintf((char *)drawstr, UI_MAX_DRAW_STR, - "%s%s%s", + "%.*s%s%s", + but->pos, but->editstr, ime_data->str_composite, but->editstr + but->pos); @@ -2020,8 +2029,11 @@ static void widget_draw_text(const uiFontStyle *fstyle, /* text button selection, cursor, composite underline */ if (but->editstr && but->pos != -1) { int but_pos_ofs; - /* Shape of the cursor for drawing. */ - rcti but_cursor_shape; + +#ifdef WITH_INPUT_IME + bool ime_reposition_window = false; + int ime_win_x, ime_win_y; +#endif /* text button selection */ if ((but->selend - but->selsta) > 0) { @@ -2046,14 +2058,28 @@ static void widget_draw_text(const uiFontStyle *fstyle, immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + rcti selection_shape; + selection_shape.xmin = rect->xmin + selsta_draw; + selection_shape.xmax = min_ii(rect->xmin + selwidth_draw, rect->xmax - 2); + selection_shape.ymin = rect->ymin + U.pixelsize; + selection_shape.ymax = rect->ymax - U.pixelsize; immUniformColor4ubv(wcol->item); immRecti(pos, - rect->xmin + selsta_draw, - rect->ymin + U.pixelsize, - min_ii(rect->xmin + selwidth_draw, rect->xmax - 2), - rect->ymax - U.pixelsize); + selection_shape.xmin, + selection_shape.ymin, + selection_shape.xmax, + selection_shape.ymax); immUnbindProgram(); + +#ifdef WITH_INPUT_IME + /* IME candidate window uses selection position. */ + if (!ime_reposition_window) { + ime_reposition_window = true; + ime_win_x = selection_shape.xmin; + ime_win_y = selection_shape.ymin; + } +#endif } } @@ -2061,7 +2087,7 @@ static void widget_draw_text(const uiFontStyle *fstyle, but_pos_ofs = but->pos; #ifdef WITH_INPUT_IME - /* if is ime compositing, move the cursor */ + /* If is IME compositing, move the cursor. */ if (ime_data && ime_data->composite_len && ime_data->cursor_pos != -1) { but_pos_ofs += ime_data->cursor_pos; } @@ -2086,6 +2112,8 @@ static void widget_draw_text(const uiFontStyle *fstyle, immUniformThemeColor(TH_WIDGET_TEXT_CURSOR); + /* Shape of the cursor for drawing. */ + rcti but_cursor_shape; but_cursor_shape.xmin = (rect->xmin + t) - U.pixelsize; but_cursor_shape.ymin = rect->ymin + U.pixelsize; but_cursor_shape.xmax = (rect->xmin + t) + U.pixelsize; @@ -2099,16 +2127,24 @@ static void widget_draw_text(const uiFontStyle *fstyle, but_cursor_shape.ymax); immUnbindProgram(); - } #ifdef WITH_INPUT_IME - if (ime_data && ime_data->composite_len) { - /* ime cursor following */ - if (but->pos >= but->ofs) { - ui_but_ime_reposition(but, but_cursor_shape.xmax + 5, but_cursor_shape.ymin + 3, false); + /* IME candidate window uses cursor position. */ + if (!ime_reposition_window) { + ime_reposition_window = true; + ime_win_x = but_cursor_shape.xmax + 5; + ime_win_y = but_cursor_shape.ymin + 3; } +#endif + } - /* composite underline */ +#ifdef WITH_INPUT_IME + /* IME cursor following. */ + if (ime_reposition_window) { + ui_but_ime_reposition(but, ime_win_x, ime_win_y, false); + } + if (ime_data && ime_data->composite_len) { + /* Composite underline. */ widget_draw_text_ime_underline(fstyle, wcol, but, rect, ime_data, drawstr); } #endif @@ -2123,14 +2159,15 @@ static void widget_draw_text(const uiFontStyle *fstyle, transopts = ui_translate_buttons(); #endif + bool use_drawstr_right_as_hint = false; + /* cut string in 2 parts - only for menu entries */ - if ((but->drawflag & UI_BUT_HAS_SHORTCUT) && (but->editstr == NULL)) { - if (but->flag & UI_BUT_HAS_SEP_CHAR) { - drawstr_right = strrchr(drawstr, UI_SEP_CHAR); - if (drawstr_right) { - drawstr_left_len = (drawstr_right - drawstr); - drawstr_right++; - } + if (but->flag & UI_BUT_HAS_SEP_CHAR && (but->editstr == NULL)) { + drawstr_right = strrchr(drawstr, UI_SEP_CHAR); + if (drawstr_right) { + use_drawstr_right_as_hint = true; + drawstr_left_len = (drawstr_right - drawstr); + drawstr_right++; } } @@ -2198,21 +2235,24 @@ static void widget_draw_text(const uiFontStyle *fstyle, BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); } - int ul_data[2] = { - ul_index, /* Character index to test. */ - 0, /* Write the x-offset here. */ + int ul_width = round_fl_to_int(BLF_width(fstyle->uifont_id, "_", 2)); + + struct UnderlineData ul_data = { + .str_offset = ul_index, + .width_px = ul_width, }; + BLF_boundbox_foreach_glyph(fstyle->uifont_id, drawstr_ofs, ul_index + 1, - widget_draw_text_underline_calc_center_x, - ul_data); - ul_data[1] -= BLF_width(fstyle->uifont_id, "_", 2) / 2.0f; - - BLF_position(fstyle->uifont_id, - rect->xmin + font_xofs + ul_data[1], - rect->ymin + font_yofs, - 0.0f); + widget_draw_text_underline_calc_position, + &ul_data); + + const int pos_x = rect->xmin + font_xofs + ul_data.r_offset_px[0]; + const int pos_y = rect->ymin + font_yofs + ul_data.r_offset_px[1]; + + /* Use text output because direct drawing doesn't always work. See T89246. */ + BLF_position(fstyle->uifont_id, pos_x, pos_y, 0.0f); BLF_color4ubv(fstyle->uifont_id, wcol->text); BLF_draw(fstyle->uifont_id, "_", 2); @@ -2228,7 +2268,7 @@ static void widget_draw_text(const uiFontStyle *fstyle, if (drawstr_right) { uchar col[4]; copy_v4_v4_uchar(col, wcol->text); - if (but->drawflag & UI_BUT_HAS_SHORTCUT) { + if (use_drawstr_right_as_hint) { col[3] *= 0.5f; } @@ -2480,7 +2520,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, ui_text_clip_middle(fstyle, but, rect); } - /* always draw text for textbutton cursor */ + /* Always draw text for text-button cursor. */ widget_draw_text(fstyle, wcol, but, rect); ui_but_text_password_hide(password_str, but, true); @@ -3075,7 +3115,7 @@ void ui_draw_gradient(const rcti *rect, copy_v3_v3(col1[3], col1[2]); break; default: - BLI_assert(!"invalid 'type' argument"); + BLI_assert_msg(0, "invalid 'type' argument"); hsv_to_rgb(1.0, 1.0, 1.0, &col1[2][0], &col1[2][1], &col1[2][2]); copy_v3_v3(col1[0], col1[2]); copy_v3_v3(col1[1], col1[2]); @@ -3476,7 +3516,7 @@ static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), /** * Draw menu buttons still with triangles when field is not embossed */ -static void widget_menubut_embossn(uiBut *UNUSED(but), +static void widget_menubut_embossn(const uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int UNUSED(state), @@ -3499,7 +3539,7 @@ static void widget_menubut_embossn(uiBut *UNUSED(but), * Draw number buttons still with triangles when field is not embossed */ static void widget_numbut_embossn( - uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign) + const uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign) { widget_numbut_draw(wcol, rect, state, roundboxalign, true); } @@ -3679,10 +3719,28 @@ static void widget_progressbar( /* "slider" bar color */ copy_v3_v3_uchar(wcol->inner, wcol->item); widgetbase_draw(&wtb_bar, wcol); +} + +static void widget_datasetrow( + uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign)) +{ + uiButDatasetRow *but_componentrow = (uiButDatasetRow *)but; + uiWidgetBase wtb; + widget_init(&wtb); + + /* no outline */ + wtb.draw_outline = false; + const float rad = wcol->roundness * U.widget_unit; + round_box_edges(&wtb, UI_CNR_ALL, rect, rad); + + if ((state & UI_ACTIVE) || (state & UI_SELECT)) { + widgetbase_draw(&wtb, wcol); + } - /* raise text a bit */ - rect->xmin += (BLI_rcti_size_x(&rect_prog) / 2); - rect->xmax += (BLI_rcti_size_x(&rect_prog) / 2); + BLI_rcti_resize(rect, + BLI_rcti_size_x(rect) - UI_UNIT_X * but_componentrow->indentation, + BLI_rcti_size_y(rect)); + BLI_rcti_translate(rect, 0.5f * UI_UNIT_X * but_componentrow->indentation, 0); } static void widget_nodesocket( @@ -4271,7 +4329,7 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType * widget_init(&wtb); if (but->block->drawextra) { - /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */ + /* NOTE: drawextra can change rect +1 or -1, to match round errors of existing previews. */ but->block->drawextra( C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect); @@ -4457,6 +4515,10 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) wt.custom = widget_progressbar; break; + case UI_WTYPE_DATASETROW: + wt.custom = widget_datasetrow; + break; + case UI_WTYPE_NODESOCKET: wt.custom = widget_nodesocket; break; @@ -4780,6 +4842,11 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu fstyle = &style->widgetlabel; break; + case UI_BTYPE_DATASETROW: + wt = widget_type(UI_WTYPE_DATASETROW); + fstyle = &style->widgetlabel; + break; + case UI_BTYPE_SCROLL: wt = widget_type(UI_WTYPE_SCROLL); break; @@ -4912,7 +4979,7 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) } /** - * Uses the widget base drawing and colors from from the box widget, but ensures an opaque + * Uses the widget base drawing and colors from the box widget, but ensures an opaque * inner color. */ void ui_draw_box_opaque(rcti *rect, int roundboxalign) @@ -5307,7 +5374,7 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, } } else { - BLI_assert(!"Unknwon menu item separator type"); + BLI_assert_msg(0, "Unknwon menu item separator type"); } if (fstyle->kerning == 1) { diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index e4dad0f1a53..e9804840801 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -347,7 +347,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y); v2d->keeptot = V2D_KEEPTOT_BOUNDS; - /* note, scroll is being flipped in ED_region_panels() drawing */ + /* NOTE: scroll is being flipped in #ED_region_panels() drawing. */ v2d->scroll |= (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE); if (do_init) { @@ -535,7 +535,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize) curRatio = height / width; winRatio = winy / winx; - /* both sizes change (area/region maximized) */ + /* Both sizes change (area/region maximized). */ if (do_x == do_y) { if (do_x && do_y) { /* here is 1,1 case, so all others must be 0,0 */ @@ -717,7 +717,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize) * * So, resolution is to just shift view by the gap between the extremities. * We favor moving the 'minimum' across, as that's origin for most things. - * (XXX - in the past, max was favored... if there are bugs, swap!) + * (XXX: in the past, max was favored... if there are bugs, swap!) */ if ((cur->xmin < tot->xmin) && (cur->xmax > tot->xmax)) { /* outside boundaries on both sides, @@ -991,10 +991,11 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resiz if (ELEM(0, width, height)) { if (G.debug & G_DEBUG) { + /* XXX: temp debug info. */ printf("Error: View2D totRect set exiting: v2d=%p width=%d height=%d\n", (void *)v2d, width, - height); /* XXX temp debug info */ + height); } return; } @@ -1058,7 +1059,7 @@ void UI_view2d_zoom_cache_reset(void) /* While scaling we can accumulate fonts at many sizes (~20 or so). * Not an issue with embedded font, but can use over 500Mb with i18n ones! See T38244. */ - /* Note: only some views draw text, we could check for this case to avoid cleaning cache. */ + /* NOTE: only some views draw text, we could check for this case to avoid cleaning cache. */ BLF_cache_clear(); } @@ -1157,7 +1158,7 @@ void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, const bool xaxis) * correspondence with pixels for smooth UI drawing, * but only applied where requested. */ - /* XXX temp (ton) */ + /* XXX(ton): temp. */ xofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_X) ? GLA_PIXEL_OFS : 0.0f; yofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_Y) ? GLA_PIXEL_OFS : 0.0f; @@ -1737,15 +1738,15 @@ bool UI_view2d_view_to_region_clip( void UI_view2d_view_to_region( const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) { - /* step 1: express given coordinates as proportional values */ + /* Step 1: express given coordinates as proportional values. */ x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur); - /* step 2: convert proportional distances to screen coordinates */ + /* Step 2: convert proportional distances to screen coordinates. */ x = v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask)); y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask)); - /* although we don't clamp to lie within region bounds, we must avoid exceeding size of ints */ + /* Although we don't clamp to lie within region bounds, we must avoid exceeding size of ints. */ *r_region_x = clamp_float_to_int(x); *r_region_y = clamp_float_to_int(y); } @@ -1768,13 +1769,13 @@ void UI_view2d_view_to_region_rcti(const View2D *v2d, const rctf *rect_src, rcti const float mask_size[2] = {BLI_rcti_size_x(&v2d->mask), BLI_rcti_size_y(&v2d->mask)}; rctf rect_tmp; - /* step 1: express given coordinates as proportional values */ + /* Step 1: express given coordinates as proportional values. */ rect_tmp.xmin = (rect_src->xmin - v2d->cur.xmin) / cur_size[0]; rect_tmp.xmax = (rect_src->xmax - v2d->cur.xmin) / cur_size[0]; rect_tmp.ymin = (rect_src->ymin - v2d->cur.ymin) / cur_size[1]; rect_tmp.ymax = (rect_src->ymax - v2d->cur.ymin) / cur_size[1]; - /* step 2: convert proportional distances to screen coordinates */ + /* Step 2: convert proportional distances to screen coordinates. */ rect_tmp.xmin = v2d->mask.xmin + (rect_tmp.xmin * mask_size[0]); rect_tmp.xmax = v2d->mask.xmin + (rect_tmp.xmax * mask_size[0]); rect_tmp.ymin = v2d->mask.ymin + (rect_tmp.ymin * mask_size[1]); @@ -1799,7 +1800,7 @@ bool UI_view2d_view_to_region_rcti_clip(const View2D *v2d, const rctf *rect_src, BLI_assert(rect_src->xmin <= rect_src->xmax && rect_src->ymin <= rect_src->ymax); - /* step 1: express given coordinates as proportional values */ + /* Step 1: express given coordinates as proportional values. */ rect_tmp.xmin = (rect_src->xmin - v2d->cur.xmin) / cur_size[0]; rect_tmp.xmax = (rect_src->xmax - v2d->cur.xmin) / cur_size[0]; rect_tmp.ymin = (rect_src->ymin - v2d->cur.ymin) / cur_size[1]; @@ -1807,7 +1808,7 @@ bool UI_view2d_view_to_region_rcti_clip(const View2D *v2d, const rctf *rect_src, if (((rect_tmp.xmax < 0.0f) || (rect_tmp.xmin > 1.0f) || (rect_tmp.ymax < 0.0f) || (rect_tmp.ymin > 1.0f)) == 0) { - /* step 2: convert proportional distances to screen coordinates */ + /* Step 2: convert proportional distances to screen coordinates. */ rect_tmp.xmin = v2d->mask.xmin + (rect_tmp.xmin * mask_size[0]); rect_tmp.xmax = v2d->mask.ymin + (rect_tmp.xmax * mask_size[0]); rect_tmp.ymin = v2d->mask.ymin + (rect_tmp.ymin * mask_size[1]); @@ -1843,7 +1844,7 @@ View2D *UI_view2d_fromcontext(const bContext *C) return &(region->v2d); } -/* same as above, but it returns regionwindow. Utility for pulldowns or buttons */ +/* Same as above, but it returns region-window. Utility for pull-downs or buttons. */ View2D *UI_view2d_fromcontext_rwin(const bContext *C) { ScrArea *area = CTX_wm_area(C); diff --git a/source/blender/editors/interface/view2d_draw.c b/source/blender/editors/interface/view2d_draw.c index 5801b7cdbdb..f7ef8c06389 100644 --- a/source/blender/editors/interface/view2d_draw.c +++ b/source/blender/editors/interface/view2d_draw.c @@ -216,7 +216,7 @@ static void draw_parallel_lines(const ParallelLinesSet *lines, immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); immUniform2fv("viewportSize", &viewport[2]); /* -1.0f offset here is because the line is too fat due to the builtin anti-aliasing. - * TODO make a variant or a uniform to toggle it off. */ + * TODO: make a variant or a uniform to toggle it off. */ immUniform1f("lineWidth", U.pixelsize - 1.0f); } else { diff --git a/source/blender/editors/interface/view2d_edge_pan.c b/source/blender/editors/interface/view2d_edge_pan.c new file mode 100644 index 00000000000..1d300c7b275 --- /dev/null +++ b/source/blender/editors/interface/view2d_edge_pan.c @@ -0,0 +1,345 @@ +/* + * 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) 2021 Blender Foundation + * All rights reserved. + */ + +/** \file + * \ingroup spnode + */ + +#include "BKE_context.h" + +#include "BLI_math.h" +#include "BLI_rect.h" + +#include "ED_screen.h" + +#include "MEM_guardedalloc.h" + +#include "PIL_time.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "UI_interface.h" +#include "UI_view2d.h" + +#include "WM_api.h" +#include "WM_types.h" + +/* -------------------------------------------------------------------- */ +/** \name Edge Pan Operator Utilities + * \{ */ + +bool UI_view2d_edge_pan_poll(bContext *C) +{ + ARegion *region = CTX_wm_region(C); + + /* Check if there's a region in context to work with. */ + if (region == NULL) { + return false; + } + + View2D *v2d = ®ion->v2d; + + /* Check that 2d-view can pan. */ + if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y)) { + return false; + } + + /* View can pan. */ + return true; +} + +void UI_view2d_edge_pan_init(bContext *C, + View2DEdgePanData *vpd, + float inside_pad, + float outside_pad, + float speed_ramp, + float max_speed, + float delay) +{ + if (!UI_view2d_edge_pan_poll(C)) { + return; + } + + /* Set pointers to owners. */ + vpd->screen = CTX_wm_screen(C); + vpd->area = CTX_wm_area(C); + vpd->region = CTX_wm_region(C); + vpd->v2d = &vpd->region->v2d; + + BLI_assert(speed_ramp > 0.0f); + vpd->inside_pad = inside_pad; + vpd->outside_pad = outside_pad; + vpd->speed_ramp = speed_ramp; + vpd->max_speed = max_speed; + vpd->delay = delay; + + /* Calculate translation factor, based on size of view. */ + const float winx = (float)(BLI_rcti_size_x(&vpd->region->winrct) + 1); + const float winy = (float)(BLI_rcti_size_y(&vpd->region->winrct) + 1); + vpd->facx = (BLI_rctf_size_x(&vpd->v2d->cur)) / winx; + vpd->facy = (BLI_rctf_size_y(&vpd->v2d->cur)) / winy; + + UI_view2d_edge_pan_reset(vpd); +} + +void UI_view2d_edge_pan_reset(View2DEdgePanData *vpd) +{ + vpd->edge_pan_start_time_x = 0.0; + vpd->edge_pan_start_time_y = 0.0; + vpd->edge_pan_last_time = PIL_check_seconds_timer(); +} + +/** + * Reset the edge pan timers if the mouse isn't in the scroll zone and + * start the timers when the mouse enters a scroll zone. + */ +static void edge_pan_manage_delay_timers(View2DEdgePanData *vpd, + int pan_dir_x, + int pan_dir_y, + const double current_time) +{ + if (pan_dir_x == 0) { + vpd->edge_pan_start_time_x = 0.0; + } + else if (vpd->edge_pan_start_time_x == 0.0) { + vpd->edge_pan_start_time_x = current_time; + } + if (pan_dir_y == 0) { + vpd->edge_pan_start_time_y = 0.0; + } + else if (vpd->edge_pan_start_time_y == 0.0) { + vpd->edge_pan_start_time_y = current_time; + } +} + +/** + * Used to calculate a "fade in" factor for edge panning to make the interaction feel smooth + * and more purposeful. + * + * \note Assumes a domain_min of 0.0f. + */ +static float smootherstep(const float domain_max, float x) +{ + x = clamp_f(x / domain_max, 0.0, 1.0); + return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); +} + +static float edge_pan_speed(View2DEdgePanData *vpd, + int event_loc, + bool x_dir, + const double current_time) +{ + ARegion *region = vpd->region; + + /* Find the distance from the start of the drag zone. */ + const int pad = vpd->inside_pad * U.widget_unit; + const int min = (x_dir ? region->winrct.xmin : region->winrct.ymin) + pad; + const int max = (x_dir ? region->winrct.xmax : region->winrct.ymax) - pad; + int distance = 0.0; + if (event_loc > max) { + distance = event_loc - max; + } + else if (event_loc < min) { + distance = min - event_loc; + } + else { + BLI_assert_msg(0, "Calculating speed outside of pan zones"); + return 0.0f; + } + float distance_factor = distance / (vpd->speed_ramp * U.widget_unit); + CLAMP(distance_factor, 0.0f, 1.0f); + + /* Apply a fade in to the speed based on a start time delay. */ + const double start_time = x_dir ? vpd->edge_pan_start_time_x : vpd->edge_pan_start_time_y; + const float delay_factor = smootherstep(vpd->delay, (float)(current_time - start_time)); + + return distance_factor * delay_factor * vpd->max_speed * U.widget_unit * (float)U.dpi_fac; +} + +static void edge_pan_apply_delta(bContext *C, View2DEdgePanData *vpd, float dx, float dy) +{ + View2D *v2d = vpd->v2d; + if (!v2d) { + return; + } + + /* Calculate amount to move view by. */ + dx *= vpd->facx; + dy *= vpd->facy; + + /* Only move view on an axis if change is allowed. */ + if ((v2d->keepofs & V2D_LOCKOFS_X) == 0) { + v2d->cur.xmin += dx; + v2d->cur.xmax += dx; + } + if ((v2d->keepofs & V2D_LOCKOFS_Y) == 0) { + v2d->cur.ymin += dy; + v2d->cur.ymax += dy; + } + + /* Inform v2d about changes after this operation. */ + UI_view2d_curRect_changed(C, v2d); + + /* Don't rebuild full tree in outliner, since we're just changing our view. */ + ED_region_tag_redraw_no_rebuild(vpd->region); + + /* Request updates to be done. */ + WM_event_add_mousemove(CTX_wm_window(C)); + + UI_view2d_sync(vpd->screen, vpd->area, v2d, V2D_LOCK_COPY); +} + +void UI_view2d_edge_pan_apply(bContext *C, View2DEdgePanData *vpd, int x, int y) +{ + ARegion *region = vpd->region; + + rcti inside_rect, outside_rect; + inside_rect = region->winrct; + outside_rect = region->winrct; + BLI_rcti_pad(&inside_rect, -vpd->inside_pad * U.widget_unit, -vpd->inside_pad * U.widget_unit); + BLI_rcti_pad(&outside_rect, vpd->outside_pad * U.widget_unit, vpd->outside_pad * U.widget_unit); + + int pan_dir_x = 0; + int pan_dir_y = 0; + if ((vpd->outside_pad == 0) || BLI_rcti_isect_pt(&outside_rect, x, y)) { + /* Find whether the mouse is beyond X and Y edges. */ + if (x > inside_rect.xmax) { + pan_dir_x = 1; + } + else if (x < inside_rect.xmin) { + pan_dir_x = -1; + } + if (y > inside_rect.ymax) { + pan_dir_y = 1; + } + else if (y < inside_rect.ymin) { + pan_dir_y = -1; + } + } + + const double current_time = PIL_check_seconds_timer(); + edge_pan_manage_delay_timers(vpd, pan_dir_x, pan_dir_y, current_time); + + /* Calculate the delta since the last time the operator was called. */ + const float dtime = (float)(current_time - vpd->edge_pan_last_time); + float dx = 0.0f, dy = 0.0f; + if (pan_dir_x != 0) { + const float speed = edge_pan_speed(vpd, x, true, current_time); + dx = dtime * speed * (float)pan_dir_x; + } + if (pan_dir_y != 0) { + const float speed = edge_pan_speed(vpd, y, false, current_time); + dy = dtime * speed * (float)pan_dir_y; + } + vpd->edge_pan_last_time = current_time; + + /* Pan, clamping inside the regions total bounds. */ + edge_pan_apply_delta(C, vpd, dx, dy); +} + +void UI_view2d_edge_pan_apply_event(bContext *C, View2DEdgePanData *vpd, const wmEvent *event) +{ + /* Only mouse-move events matter here, ignore others. */ + if (event->type != MOUSEMOVE) { + return; + } + + UI_view2d_edge_pan_apply(C, vpd, event->x, event->y); +} + +void UI_view2d_edge_pan_operator_properties(wmOperatorType *ot) +{ + /* Default values for edge panning operators. */ + UI_view2d_edge_pan_operator_properties_ex(ot, + /*inside_pad*/ 1.0f, + /*outside_pad*/ 0.0f, + /*speed_ramp*/ 1.0f, + /*max_speed*/ 500.0f, + /*delay*/ 1.0f); +} + +void UI_view2d_edge_pan_operator_properties_ex(struct wmOperatorType *ot, + float inside_pad, + float outside_pad, + float speed_ramp, + float max_speed, + float delay) +{ + RNA_def_float( + ot->srna, + "inside_padding", + inside_pad, + 0.0f, + 100.0f, + "Inside Padding", + "Inside distance in UI units from the edge of the region within which to start panning", + 0.0f, + 100.0f); + RNA_def_float( + ot->srna, + "outside_padding", + outside_pad, + 0.0f, + 100.0f, + "Outside Padding", + "Outside distance in UI units from the edge of the region at which to stop panning", + 0.0f, + 100.0f); + RNA_def_float(ot->srna, + "speed_ramp", + speed_ramp, + 0.0f, + 100.0f, + "Speed Ramp", + "Width of the zone in UI units where speed increases with distance from the edge", + 0.0f, + 100.0f); + RNA_def_float(ot->srna, + "max_speed", + max_speed, + 0.0f, + 10000.0f, + "Max Speed", + "Maximum speed in UI units per second", + 0.0f, + 10000.0f); + RNA_def_float(ot->srna, + "delay", + delay, + 0.0f, + 10.0f, + "Delay", + "Delay in seconds before maximum speed is reached", + 0.0f, + 10.0f); +} + +void UI_view2d_edge_pan_operator_init(bContext *C, View2DEdgePanData *vpd, wmOperator *op) +{ + UI_view2d_edge_pan_init(C, + vpd, + RNA_float_get(op->ptr, "inside_padding"), + RNA_float_get(op->ptr, "outside_padding"), + RNA_float_get(op->ptr, "speed_ramp"), + RNA_float_get(op->ptr, "max_speed"), + RNA_float_get(op->ptr, "delay")); +} + +/** \} */ diff --git a/source/blender/editors/interface/view2d_gizmo_navigate.c b/source/blender/editors/interface/view2d_gizmo_navigate.c index 8d3f1beb947..30b4a7c097a 100644 --- a/source/blender/editors/interface/view2d_gizmo_navigate.c +++ b/source/blender/editors/interface/view2d_gizmo_navigate.c @@ -113,7 +113,7 @@ static struct NavigateGizmoInfo *navigate_params_from_space_type(short space_typ case SPACE_CLIP: return g_navigate_params_for_space_clip; default: - /* Used for sequencer. */ + /* Used for sequencer. */ return g_navigate_params_for_view2d; } } diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 7453cd17868..1fd1b6c984d 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -187,7 +187,7 @@ static void view_pan_apply(bContext *C, wmOperator *op) view_pan_apply_ex(C, vpd, RNA_int_get(op->ptr, "deltax"), RNA_int_get(op->ptr, "deltay")); } -/* cleanup temp customdata */ +/* Cleanup temp custom-data. */ static void view_pan_exit(wmOperator *op) { MEM_SAFE_FREE(op->customdata); @@ -271,7 +271,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event) view_pan_apply(C, op); break; } - /* XXX - Mode switching isn't implemented. See comments in 36818. + /* XXX: Mode switching isn't implemented. See comments in 36818. * switch to zoom */ #if 0 case LEFTMOUSE: @@ -341,162 +341,37 @@ static void VIEW2D_OT_pan(wmOperatorType *ot) * passes through. * \{ */ -/** Distance from the edge of the region within which to start panning. */ -#define EDGE_PAN_REGION_PAD (U.widget_unit) -/** Speed factor in pixels per second per pixel of distance from edge pan zone beginning. */ -#define EDGE_PAN_SPEED_PER_PIXEL (25.0f * (float)U.dpi_fac) -/** Delay before drag panning in seconds. */ -#define EDGE_PAN_DELAY 1.0f - /* set up modal operator and relevant settings */ static int view_edge_pan_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - /* Set up customdata. */ - view_pan_init(C, op); - - v2dViewPanData *vpd = op->customdata; - - vpd->edge_pan_start_time_x = 0.0; - vpd->edge_pan_start_time_y = 0.0; - vpd->edge_pan_last_time = PIL_check_seconds_timer(); + op->customdata = MEM_callocN(sizeof(View2DEdgePanData), "View2DEdgePanData"); + View2DEdgePanData *vpd = op->customdata; + UI_view2d_edge_pan_operator_init(C, vpd, op); WM_event_add_modal_handler(C, op); return (OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH); } -/** - * Reset the edge pan timers if the mouse isn't in the scroll zone and - * start the timers when the mouse enters a scroll zone. - */ -static void edge_pan_manage_delay_timers(v2dViewPanData *vpd, - int pan_dir_x, - int pan_dir_y, - const double current_time) -{ - if (pan_dir_x == 0) { - vpd->edge_pan_start_time_x = 0.0; - } - else if (vpd->edge_pan_start_time_x == 0.0) { - vpd->edge_pan_start_time_x = current_time; - } - if (pan_dir_y == 0) { - vpd->edge_pan_start_time_y = 0.0; - } - else if (vpd->edge_pan_start_time_y == 0.0) { - vpd->edge_pan_start_time_y = current_time; - } -} - -/** - * Used to calculate a "fade in" factor for edge panning to make the interaction feel smooth - * and more purposeful. - * - * \note Assumes a domain_min of 0.0f. - */ -static float smootherstep(const float domain_max, float x) -{ - x = clamp_f(x / domain_max, 0.0, 1.0); - return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); -} - -static float edge_pan_speed(v2dViewPanData *vpd, - int event_loc, - bool x_dir, - const double current_time) -{ - ARegion *region = vpd->region; - - /* Find the distance from the start of the drag zone. */ - const int min = (x_dir ? region->winrct.xmin : region->winrct.ymin) + EDGE_PAN_REGION_PAD; - const int max = (x_dir ? region->winrct.xmax : region->winrct.ymax) - EDGE_PAN_REGION_PAD; - int distance = 0.0; - if (event_loc > max) { - distance = event_loc - max; - } - else if (event_loc < min) { - distance = min - event_loc; - } - else { - BLI_assert(!"Calculating speed outside of pan zones"); - return 0.0f; - } - - /* Apply a fade in to the speed based on a start time delay. */ - const double start_time = x_dir ? vpd->edge_pan_start_time_x : vpd->edge_pan_start_time_y; - const float delay_factor = smootherstep(EDGE_PAN_DELAY, (float)(current_time - start_time)); - - return distance * EDGE_PAN_SPEED_PER_PIXEL * delay_factor; -} - static int view_edge_pan_modal(bContext *C, wmOperator *op, const wmEvent *event) { - v2dViewPanData *vpd = op->customdata; - ARegion *region = vpd->region; + View2DEdgePanData *vpd = op->customdata; if (event->val == KM_RELEASE || event->type == EVT_ESCKEY) { - view_pan_exit(op); + MEM_SAFE_FREE(op->customdata); return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); } - /* Only mousemove events matter here, ignore others. */ - if (event->type != MOUSEMOVE) { - return OPERATOR_PASS_THROUGH; - } + + UI_view2d_edge_pan_apply_event(C, vpd, event); /* This operator is supposed to run together with some drag action. * On successful handling, always pass events on to other handlers. */ - const int success_retval = OPERATOR_PASS_THROUGH; - - const int outside_padding = RNA_int_get(op->ptr, "outside_padding") * UI_UNIT_X; - rcti padding_rect; - if (outside_padding != 0) { - padding_rect = region->winrct; - BLI_rcti_pad(&padding_rect, outside_padding, outside_padding); - } - - int pan_dir_x = 0; - int pan_dir_y = 0; - if ((outside_padding == 0) || BLI_rcti_isect_pt(&padding_rect, event->x, event->y)) { - /* Find whether the mouse is beyond X and Y edges. */ - if (event->x > region->winrct.xmax - EDGE_PAN_REGION_PAD) { - pan_dir_x = 1; - } - else if (event->x < region->winrct.xmin + EDGE_PAN_REGION_PAD) { - pan_dir_x = -1; - } - if (event->y > region->winrct.ymax - EDGE_PAN_REGION_PAD) { - pan_dir_y = 1; - } - else if (event->y < region->winrct.ymin + EDGE_PAN_REGION_PAD) { - pan_dir_y = -1; - } - } - - const double current_time = PIL_check_seconds_timer(); - edge_pan_manage_delay_timers(vpd, pan_dir_x, pan_dir_y, current_time); - - /* Calculate the delta since the last time the operator was called. */ - const float dtime = (float)(current_time - vpd->edge_pan_last_time); - float dx = 0.0f, dy = 0.0f; - if (pan_dir_x != 0) { - const float speed = edge_pan_speed(vpd, event->x, true, current_time); - dx = dtime * speed * (float)pan_dir_x; - } - if (pan_dir_y != 0) { - const float speed = edge_pan_speed(vpd, event->y, false, current_time); - dy = dtime * speed * (float)pan_dir_y; - } - vpd->edge_pan_last_time = current_time; - - /* Pan, clamping inside the regions's total bounds. */ - view_pan_apply_ex(C, vpd, dx, dy); - - return success_retval; + return OPERATOR_PASS_THROUGH; } static void view_edge_pan_cancel(bContext *UNUSED(C), wmOperator *op) { - view_pan_exit(op); + MEM_SAFE_FREE(op->customdata); } static void VIEW2D_OT_edge_pan(wmOperatorType *ot) @@ -510,26 +385,13 @@ static void VIEW2D_OT_edge_pan(wmOperatorType *ot) ot->invoke = view_edge_pan_invoke; ot->modal = view_edge_pan_modal; ot->cancel = view_edge_pan_cancel; - ot->poll = view_pan_poll; + ot->poll = UI_view2d_edge_pan_poll; /* operator is modal */ ot->flag = OPTYPE_INTERNAL; - RNA_def_int(ot->srna, - "outside_padding", - 0, - 0, - 100, - "Outside Padding", - "Padding around the region in UI units within which panning is activated (0 to " - "disable boundary)", - 0, - 100); + UI_view2d_edge_pan_operator_properties(ot); } -#undef EDGE_PAN_REGION_PAD -#undef EDGE_PAN_SPEED_PER_PIXEL -#undef EDGE_PAN_DELAY - /** \} */ /* -------------------------------------------------------------------- */ @@ -757,7 +619,7 @@ typedef struct v2dViewZoomData { } v2dViewZoomData; /** - * Clamp by convention rather then locking flags, + * Clamp by convention rather than locking flags, * for ndof and +/- keys */ static void view_zoom_axis_lock_defaults(bContext *C, bool r_do_zoom_xy[2]) @@ -943,7 +805,7 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op) /** \name View Zoom Operator (single step) * \{ */ -/* cleanup temp customdata */ +/* Cleanup temp custom-data. */ static void view_zoomstep_exit(wmOperator *op) { UI_view2d_zoom_cache_reset(); @@ -1172,7 +1034,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op) UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); } -/* cleanup temp customdata */ +/* Cleanup temp custom-data. */ static void view_zoomdrag_exit(bContext *C, wmOperator *op) { UI_view2d_zoom_cache_reset(); @@ -1665,7 +1527,7 @@ struct SmoothView2DStore { /** * function to get a factor out of a rectangle * - * note: this doesn't always work as well as it might because the target size + * NOTE: this doesn't always work as well as it might because the target size * may not be reached because of clamping the desired rect, we _could_ * attempt to clamp the rect before working out the zoom factor but its * not really worthwhile for the few cases this happens. @@ -1883,7 +1745,7 @@ typedef struct v2dScrollerMove { * This is a CUT DOWN VERSION of the 'real' version, which is defined in view2d.c, * as we only need focus bubble info. * - * \warning: The start of this struct must not change, + * \warning The start of this struct must not change, * so that it stays in sync with the 'real' version. * For now, we don't need to have a separate (internal) header for structs like this... */ @@ -2052,7 +1914,7 @@ static void scroller_activate_init(bContext *C, ED_region_tag_redraw_no_rebuild(region); } -/* cleanup temp customdata */ +/* Cleanup temp custom-data. */ static void scroller_activate_exit(bContext *C, wmOperator *op) { if (op->customdata) { @@ -2194,7 +2056,7 @@ static int scroller_activate_modal(bContext *C, wmOperator *op, const wmEvent *e return OPERATOR_FINISHED; } - /* otherwise, end the drag action */ + /* Otherwise, end the drag action. */ if (vsm->lastx || vsm->lasty) { scroller_activate_exit(C, op); return OPERATOR_FINISHED; @@ -2270,7 +2132,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent * scroller_activate_exit(C, op); /* can't catch this event for ourselves, so let it go to someone else? */ - /* XXX note: if handlers use mask rect to clip input, input will fail for this case */ + /* XXX NOTE: if handlers use mask rect to clip input, input will fail for this case. */ return OPERATOR_PASS_THROUGH; } diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 28838d677f0..12890552b1d 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -63,10 +63,26 @@ # include "WM_api.h" # include "WM_types.h" +# include "DEG_depsgraph.h" + # include "io_alembic.h" # include "ABC_alembic.h" +const EnumPropertyItem rna_enum_abc_export_evaluation_mode_items[] = { + {DAG_EVAL_RENDER, + "RENDER", + 0, + "Render", + "Use Render settings for object visibility, modifier settings, etc"}, + {DAG_EVAL_VIEWPORT, + "VIEWPORT", + 0, + "Viewport", + "Use Viewport settings for object visibility, modifier settings, etc"}, + {0, NULL, 0, NULL, NULL}, +}; + static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (!RNA_struct_property_is_set(op->ptr, "as_background_job")) { @@ -126,7 +142,6 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) .curves_as_mesh = RNA_boolean_get(op->ptr, "curves_as_mesh"), .flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"), .visible_objects_only = RNA_boolean_get(op->ptr, "visible_objects_only"), - .renderable_only = RNA_boolean_get(op->ptr, "renderable_only"), .face_sets = RNA_boolean_get(op->ptr, "face_sets"), .use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"), .export_hair = RNA_boolean_get(op->ptr, "export_hair"), @@ -137,6 +152,7 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) .triangulate = RNA_boolean_get(op->ptr, "triangulate"), .quad_method = RNA_enum_get(op->ptr, "quad_method"), .ngon_method = RNA_enum_get(op->ptr, "ngon_method"), + .evaluation_mode = RNA_enum_get(op->ptr, "evaluation_mode"), .global_scale = RNA_float_get(op->ptr, "global_scale"), }; @@ -194,9 +210,11 @@ static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr) sub = uiLayoutColumnWithHeading(col, true, IFACE_("Only")); uiItemR(sub, imfptr, "selected", 0, IFACE_("Selected Objects"), ICON_NONE); - uiItemR(sub, imfptr, "renderable_only", 0, IFACE_("Renderable Objects"), ICON_NONE); uiItemR(sub, imfptr, "visible_objects_only", 0, IFACE_("Visible Objects"), ICON_NONE); + col = uiLayoutColumn(box, true); + uiItemR(col, imfptr, "evaluation_mode", 0, NULL, ICON_NONE); + /* Object Data */ box = uiLayoutBox(layout); row = uiLayoutRow(box, false); @@ -355,12 +373,6 @@ void WM_OT_alembic_export(wmOperatorType *ot) ot->srna, "selected", 0, "Selected Objects Only", "Export only selected objects"); RNA_def_boolean(ot->srna, - "renderable_only", - 1, - "Renderable Objects Only", - "Export only objects marked renderable in the outliner"); - - RNA_def_boolean(ot->srna, "visible_objects_only", 0, "Visible Objects Only", @@ -468,6 +480,14 @@ void WM_OT_alembic_export(wmOperatorType *ot) "This option is deprecated; EXECUTE this operator to run in the foreground, and INVOKE it " "to run as a background job"); + RNA_def_enum(ot->srna, + "evaluation_mode", + rna_enum_abc_export_evaluation_mode_items, + DAG_EVAL_RENDER, + "Use Settings for", + "Determines visibility of objects, modifier settings, and other areas where there " + "are different settings for viewport and rendering"); + /* This dummy prop is used to check whether we need to init the start and * end frame values to that of the scene's, otherwise they are reset at * every change, draw update. */ diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c index cb3f9a89e62..e6f190f335b 100644 --- a/source/blender/editors/lattice/editlattice_select.c +++ b/source/blender/editors/lattice/editlattice_select.c @@ -108,9 +108,9 @@ bool ED_lattice_deselect_all_multi(struct bContext *C) static int lattice_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, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); - const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; @@ -119,29 +119,36 @@ static int lattice_select_random_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt; + int seed_iter = seed; - RNG *rng = BLI_rng_new_srandom(seed); + /* This gives a consistent result regardless of object order. */ + if (ob_index) { + seed_iter += BLI_ghashutil_strhash_p(obedit->id.name); + } - int tot; - BPoint *bp; + int a = lt->pntsu * lt->pntsv * lt->pntsw; + int elem_map_len = 0; + BPoint **elem_map = MEM_mallocN(sizeof(*elem_map) * a, __func__); + BPoint *bp = lt->def; - tot = lt->pntsu * lt->pntsv * lt->pntsw; - bp = lt->def; - while (tot--) { + while (a--) { if (!bp->hide) { - if (BLI_rng_get_float(rng) < randfac) { - bpoint_select_set(bp, select); - } + elem_map[elem_map_len++] = bp; } bp++; } + BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed_iter); + const int count_select = elem_map_len * randfac; + for (int i = 0; i < count_select; i++) { + bpoint_select_set(elem_map[i], select); + } + MEM_freeN(elem_map); + if (select == false) { lt->actbp = LT_ACTBP_NONE; } - BLI_rng_free(rng); - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -229,7 +236,7 @@ static int lattice_select_mirror_exec(bContext *C, wmOperator *op) } } - /* TODO, only notify changes */ + /* TODO: only notify changes. */ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -507,7 +514,7 @@ static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op) BPoint *bp; int a, tot; - if (BLI_listbase_is_empty(&obedit->defbase) || lt->dvert == NULL) { + if (BLI_listbase_is_empty(<->vertex_group_names) || lt->dvert == NULL) { continue; } diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c index d92a81179cc..23eaf991fd3 100644 --- a/source/blender/editors/lattice/editlattice_undo.c +++ b/source/blender/editors/lattice/editlattice_undo.c @@ -240,7 +240,7 @@ static void lattice_undosys_step_decode(struct bContext *C, } undolatt_to_editlatt(&elem->data, lt->editlatt); lt->editlatt->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(<->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 36edbbe31d6..880d27e1615 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -145,7 +145,7 @@ static void setup_vertex_point(Mask *mask, /* parent */ reference_parent_point = close_point; - /* note, we may want to copy other attributes later, radius? pressure? color? */ + /* NOTE: we may want to copy other attributes later, radius? pressure? color? */ } } @@ -189,7 +189,7 @@ static void finSelectedSplinePoint(MaskLayer *mask_layer, *point = NULL; if (check_active) { - /* TODO, having an active point but no active spline is possible, why? */ + /* TODO: having an active point but no active spline is possible, why? */ if (mask_layer->act_spline && mask_layer->act_point && MASKPOINT_ISSEL_ANY(mask_layer->act_point)) { *spline = mask_layer->act_spline; @@ -277,7 +277,7 @@ static bool add_vertex_subdivide(const bContext *C, Mask *mask, const float co[2 setup_vertex_point(mask, spline, new_point, co, u, ctime, NULL, true); - /* TODO - we could pass the spline! */ + /* TODO: we could pass the spline! */ BKE_mask_layer_shape_changed_add(mask_layer, BKE_mask_layer_shape_spline_to_index(mask_layer, spline) + point_index + 1, @@ -479,7 +479,7 @@ static int add_vertex_handle_cyclic_at_point(bContext *C, spline->flag |= MASK_SPLINE_CYCLIC; - /* TODO, update keyframes in time. */ + /* TODO: update keyframes in time. */ BKE_mask_calc_handle_point_auto(spline, active_point, false); BKE_mask_calc_handle_point_auto(spline, other_point, false); @@ -526,7 +526,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) float co[2]; RNA_float_get_array(op->ptr, "location", co); - /* TODO, having an active point but no active spline is possible, why? */ + /* TODO: having an active point but no active spline is possible, why? */ if (mask_layer && mask_layer->act_spline && mask_layer->act_point && MASKPOINT_ISSEL_ANY(mask_layer->act_point)) { MaskSpline *spline = mask_layer->act_spline; diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index d3fa0e93597..de8ea8e21eb 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -211,7 +211,7 @@ static void draw_spline_points(const bContext *C, undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT); } - /* TODO, add this to sequence editor */ + /* TODO: add this to sequence editor. */ float handle_size = 2.0f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize; mask_spline_color_get(mask_layer, spline, is_spline_sel, rgb_spline); diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c index 1792f0e13bc..d9efbef4b42 100644 --- a/source/blender/editors/mask/mask_editaction.c +++ b/source/blender/editors/mask/mask_editaction.c @@ -109,7 +109,7 @@ void ED_masklayer_make_cfra_list(MaskLayer *mask_layer, ListBase *elems, bool on /* Selection Tools */ /* check if one of the frames in this layer is selected */ -bool ED_masklayer_frame_select_check(MaskLayer *mask_layer) +bool ED_masklayer_frame_select_check(const MaskLayer *mask_layer) { MaskLayerShape *mask_layer_shape; @@ -283,25 +283,25 @@ void ED_masklayer_frames_duplicate(MaskLayer *mask_layer) { MaskLayerShape *mask_layer_shape, *gpfn; - /* error checking */ + /* Error checking. */ if (mask_layer == NULL) { return; } - /* duplicate selected frames */ + /* Duplicate selected frames. */ for (mask_layer_shape = mask_layer->splines_shapes.first; mask_layer_shape; mask_layer_shape = gpfn) { gpfn = mask_layer_shape->next; - /* duplicate this frame */ + /* Duplicate this frame. */ if (mask_layer_shape->flag & MASK_SHAPE_SELECT) { MaskLayerShape *mask_shape_dupe; - /* duplicate frame, and deselect self */ + /* Duplicate frame, and deselect self. */ mask_shape_dupe = BKE_mask_layer_shape_duplicate(mask_layer_shape); mask_layer_shape->flag &= ~MASK_SHAPE_SELECT; - /* XXX - how to handle duplicate frames? */ + /* XXX: how to handle duplicate frames? */ BLI_insertlinkafter(&mask_layer->splines_shapes, mask_layer_shape, mask_shape_dupe); } } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 1a6ac8597ae..6fa7457ce14 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -83,7 +83,9 @@ Mask *ED_mask_new(bContext *C, const char *name) return mask; } -/* Get ative layer. Will create mask/layer to be sure there's an active layer. */ +/** + * Get active layer. Will create mask/layer to be sure there's an active layer. + */ MaskLayer *ED_mask_layer_ensure(bContext *C, bool *r_added_mask) { Mask *mask = CTX_data_edit_mask(C); @@ -388,7 +390,7 @@ static void select_sliding_point(Mask *mask, point->bezt.f3 |= SELECT; break; default: - BLI_assert(!"Unexpected situation in select_sliding_point()"); + BLI_assert_msg(0, "Unexpected situation in select_sliding_point()"); } mask_layer->act_spline = spline; diff --git a/source/blender/editors/mask/mask_query.c b/source/blender/editors/mask/mask_query.c index 401b6eac4f2..cd51026d20c 100644 --- a/source/blender/editors/mask/mask_query.c +++ b/source/blender/editors/mask/mask_query.c @@ -169,7 +169,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, } if (r_u) { - /* TODO(sergey): Projection fails in some weirdo cases.. */ + /* TODO(sergey): Projection fails in some weirdo cases. */ if (use_project) { u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY); } diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 5c369afc4cd..3bb05a27c54 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -92,7 +92,6 @@ bool ED_mask_select_check(const Mask *mask) return false; } -/* 'sel' select */ void ED_mask_spline_select_set(MaskSpline *spline, const bool do_select) { if (do_select) { diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index 81bf66da72c..a5a3489c143 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -173,7 +173,7 @@ static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op) MaskSplinePoint *point = &spline->points[i]; if (MASKPOINT_ISSEL_ANY(point)) { - /* TODO - nicer access here */ + /* TODO: nicer access here. */ shape_ele_dst->value[6] = shape_ele_src->value[6]; } @@ -291,7 +291,7 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op) BLI_addtail(&shapes_tmp, mask_layer_shape_tmp); } - /* re-key, note: cant modify the keys here since it messes uop */ + /* re-key, NOTE: can't modify the keys here since it messes up. */ for (mask_layer_shape_tmp = shapes_tmp.first; mask_layer_shape_tmp; mask_layer_shape_tmp = mask_layer_shape_tmp->next) { BKE_mask_layer_evaluate(mask_layer, mask_layer_shape_tmp->frame, true); diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index b7ee50a9461..648008a4779 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -65,7 +65,7 @@ void paintface_flush_flags(struct bContext *C, Object *ob, short flag) return; } - /* note, call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags */ + /* NOTE: call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags. */ /* we could call this directly in all areas that change selection, * since this could become slow for realtime updates (circle-select for eg) */ @@ -433,7 +433,7 @@ bool paintface_mouse_select( /* image window redraw */ paintface_flush_flags(C, ob, SELECT); - ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */ + ED_region_tag_redraw(CTX_wm_region(C)); /* XXX: should redraw all 3D views. */ return true; } diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 18e231893d4..a64b90e15a3 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -95,7 +95,12 @@ static void make_prim_finish(bContext *C, EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); /* only recalc editmode tessface if we are staying in editmode */ - EDBM_update_generic(obedit->data, !exit_editmode, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = !exit_editmode, + .calc_normals = false, + .is_destructive = true, + }); /* userdef */ if (exit_editmode) { diff --git a/source/blender/editors/mesh/editmesh_add_gizmo.c b/source/blender/editors/mesh/editmesh_add_gizmo.c index e7a99ca9e08..9efcf0963b4 100644 --- a/source/blender/editors/mesh/editmesh_add_gizmo.c +++ b/source/blender/editors/mesh/editmesh_add_gizmo.c @@ -357,7 +357,12 @@ static int add_primitive_cube_gizmo_exec(bContext *C, wmOperator *op) } EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mesh/editmesh_automerge.c b/source/blender/editors/mesh/editmesh_automerge.c index 2bd5b9b26ca..35fff1f8f3a 100644 --- a/source/blender/editors/mesh/editmesh_automerge.c +++ b/source/blender/editors/mesh/editmesh_automerge.c @@ -76,7 +76,12 @@ void EDBM_automerge(Object *obedit, bool update, const char hflag, const float d BMO_op_finish(bm, &weldop); if ((totvert_prev != bm->totvert) && update) { - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } } @@ -134,7 +139,12 @@ void EDBM_automerge_and_split(Object *obedit, #endif if (LIKELY(ok) && update) { - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } } diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 43492cd57af..01736f2919a 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -279,7 +279,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) for (int i = 0; i < NUM_VALUE_KINDS; i++) { opdata->shift_value[i] = -1.0f; opdata->initial_length[i] = -1.0f; - /* note: scale for OFFSET_VALUE will get overwritten in edbm_bevel_invoke */ + /* NOTE: scale for #OFFSET_VALUE will get overwritten in #edbm_bevel_invoke. */ opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch; initNumInput(&opdata->num_input[i]); @@ -347,7 +347,7 @@ static bool edbm_bevel_calc(wmOperator *op) /* revert to original mesh */ if (opdata->is_modal) { - EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false); + EDBM_redo_state_restore(&opdata->ob_store[ob_index].mesh_backup, em, false); } const int material = CLAMPIS(material_init, -1, obedit->totcol - 1); @@ -403,9 +403,12 @@ static bool edbm_bevel_calc(wmOperator *op) continue; } - EDBM_mesh_normals_update(em); - - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); changed = true; } return changed; @@ -433,7 +436,7 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { - EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, NULL, false); + EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup); } ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel); if (v3d) { @@ -453,8 +456,13 @@ static void edbm_bevel_cancel(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { Object *obedit = opdata->ob_store[ob_index].ob; BMEditMesh *em = BKE_editmesh_from_object(obedit); - EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, em, true); - EDBM_update_generic(obedit->data, false, true); + EDBM_redo_state_restore_and_free(&opdata->ob_store[ob_index].mesh_backup, em, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = true, + .is_destructive = true, + }); } } diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index ea35d5a9e26..3c8afe8e7db 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -67,7 +67,7 @@ typedef struct { /* Aligned with objects array. */ struct { - BMBackup mesh; + BMBackup mesh_backup; bool is_valid; bool is_dirty; } * backup; @@ -160,7 +160,7 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (em->bm->totedgesel != 0) { opdata->backup[ob_index].is_valid = true; - opdata->backup[ob_index].mesh = EDBM_redo_state_store(em); + opdata->backup[ob_index].mesh_backup = EDBM_redo_state_store(em); } } @@ -184,7 +184,7 @@ static void edbm_bisect_exit(bContext *C, BisectData *opdata) for (int ob_index = 0; ob_index < opdata->backup_len; ob_index++) { if (opdata->backup[ob_index].is_valid) { - EDBM_redo_state_free(&opdata->backup[ob_index].mesh, NULL, false); + EDBM_redo_state_free(&opdata->backup[ob_index].mesh_backup); } } MEM_freeN(opdata->backup); @@ -280,7 +280,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) /* -------------------------------------------------------------------- */ /* Modal support */ - /* Note: keep this isolated, exec can work without this */ + /* NOTE: keep this isolated, exec can work without this. */ if (opdata != NULL) { mesh_bisect_interactive_calc(C, op, plane_co, plane_no); /* Write back to the props. */ @@ -301,7 +301,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) if (opdata != NULL) { if (opdata->backup[ob_index].is_dirty) { - EDBM_redo_state_restore(opdata->backup[ob_index].mesh, em, false); + EDBM_redo_state_restore(&opdata->backup[ob_index].mesh_backup, em, false); opdata->backup[ob_index].is_dirty = false; } } @@ -347,7 +347,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) BMOperator bmop_attr; /* The fill normal sign is ignored as the face-winding is defined by surrounding faces. - * The normal is passed so triangle fill wont have to calculate it. */ + * The normal is passed so triangle fill won't have to calculate it. */ normalize_v3_v3(normal_fill, plane_no_local); /* Fill */ @@ -383,7 +383,12 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) bm, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true); if (EDBM_op_finish(em, &bmop, op, true)) { - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); EDBM_selectmode_flush(em); ret = OPERATOR_FINISHED; } diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index d5ddb7fc2c4..907881a44f3 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -319,9 +319,12 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", offset_local, BM_ELEM_SELECT); } - EDBM_mesh_normals_update(em); - - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -448,11 +451,13 @@ static int edbm_extrude_region_exec(bContext *C, wmOperator *op) continue; } /* This normally happens when pushing undo but modal operators - * like this one don't push undo data until after modal mode is - * done.*/ - EDBM_mesh_normals_update(em); - - EDBM_update_generic(obedit->data, true, true); + * like this one don't push undo data until after modal mode is done. */ + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); } MEM_freeN(objects); return OPERATOR_FINISHED; @@ -502,13 +507,15 @@ static int edbm_extrude_context_exec(bContext *C, wmOperator *op) } edbm_extrude_mesh(obedit, em, op); - /* This normally happens when pushing undo but modal operators - * like this one don't push undo data until after modal mode is - * done.*/ - EDBM_mesh_normals_update(em); - - EDBM_update_generic(obedit->data, true, true); + /* This normally happens when pushing undo but modal operators + * like this one don't push undo data until after modal mode is done. */ + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); } MEM_freeN(objects); return OPERATOR_FINISHED; @@ -555,7 +562,12 @@ static int edbm_extrude_verts_exec(bContext *C, wmOperator *op) edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -603,7 +615,12 @@ static int edbm_extrude_edges_exec(bContext *C, wmOperator *op) edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT, use_normal_flip); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -651,7 +668,12 @@ static int edbm_extrude_faces_exec(bContext *C, wmOperator *op) edbm_extrude_discrete_faces(em, op, BM_ELEM_SELECT); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -884,11 +906,13 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w } /* This normally happens when pushing undo but modal operators - * like this one don't push undo data until after modal mode is - * done. */ - EDBM_mesh_normals_update(vc.em); - - EDBM_update_generic(vc.obedit->data, true, true); + * like this one don't push undo data until after modal mode is done. */ + EDBM_update(vc.obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); diff --git a/source/blender/editors/mesh/editmesh_extrude_screw.c b/source/blender/editors/mesh/editmesh_extrude_screw.c index 4cffd12cb34..1ba6a0f42c6 100644 --- a/source/blender/editors/mesh/editmesh_extrude_screw.c +++ b/source/blender/editors/mesh/editmesh_extrude_screw.c @@ -155,7 +155,12 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); diff --git a/source/blender/editors/mesh/editmesh_extrude_spin.c b/source/blender/editors/mesh/editmesh_extrude_spin.c index 187652ae00f..2146207308c 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin.c @@ -108,7 +108,12 @@ static int edbm_spin_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c index 73d79805f60..18f51ae9df2 100644 --- a/source/blender/editors/mesh/editmesh_inset.c +++ b/source/blender/editors/mesh/editmesh_inset.c @@ -209,7 +209,7 @@ static void edbm_inset_exit(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { - EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, NULL, false); + EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup); } ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel); if (v3d) { @@ -235,8 +235,13 @@ static void edbm_inset_cancel(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { Object *obedit = opdata->ob_store[ob_index].ob; BMEditMesh *em = BKE_editmesh_from_object(obedit); - EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, em, true); - EDBM_update_generic(obedit->data, false, true); + EDBM_redo_state_restore_and_free(&opdata->ob_store[ob_index].mesh_backup, em, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = true, + }); } } @@ -271,7 +276,7 @@ static bool edbm_inset_calc(wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); if (opdata->is_modal) { - EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false); + EDBM_redo_state_restore(&opdata->ob_store[ob_index].mesh_backup, em, false); } if (use_individual) { @@ -326,7 +331,12 @@ static bool edbm_inset_calc(wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); changed = true; } return changed; diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index d1f228e951a..f2691580a9d 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -116,8 +116,12 @@ static void edbm_intersect_select(BMEditMesh *em, struct Mesh *me, bool do_selec } } - EDBM_mesh_normals_update(em); - EDBM_update_generic(me, true, true); + EDBM_update(me, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); } /* -------------------------------------------------------------------- */ @@ -963,8 +967,12 @@ static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op)) } #endif - EDBM_mesh_normals_update(em); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); #ifdef USE_NET_ISLAND_CONNECT /* we may have remaining isolated regions remaining, @@ -1068,8 +1076,12 @@ static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op)) BLI_ghash_free(face_edge_map, NULL, NULL); - EDBM_mesh_normals_update(em); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); } BLI_stack_free(edges_loose); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index b5cd9c7f60d..73f6a3f3238 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -157,7 +157,7 @@ typedef struct KnifePosData { typedef struct KnifeTool_OpData { ARegion *region; /* region that knifetool was activated in */ void *draw_handle; /* for drawing preview loop */ - ViewContext vc; /* note: _don't_ use 'mval', instead use the one we define below */ + ViewContext vc; /* NOTE: _don't_ use 'mval', instead use the one we define below. */ float mval[2]; /* mouse value with snapping applied */ // bContext *C; @@ -272,8 +272,7 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd) float v1[3], v2[3]; float planes[4][4]; - planes_from_projmat( - (const float(*)[4])kcd->projmat, planes[2], planes[0], planes[3], planes[1], NULL, NULL); + planes_from_projmat(kcd->projmat, planes[2], planes[0], planes[1], planes[3], NULL, NULL); /* ray-cast all planes */ { @@ -578,8 +577,8 @@ static void knife_input_ray_segment(KnifeTool_OpData *kcd, float r_origin_ofs[3]) { /* unproject to find view ray */ - ED_view3d_unproject(kcd->vc.region, mval[0], mval[1], 0.0f, r_origin); - ED_view3d_unproject(kcd->vc.region, mval[0], mval[1], ofs, r_origin_ofs); + ED_view3d_unproject_v3(kcd->vc.region, mval[0], mval[1], 0.0f, r_origin); + ED_view3d_unproject_v3(kcd->vc.region, mval[0], mval[1], ofs, r_origin_ofs); /* transform into object space */ mul_m4_v3(kcd->ob_imat, r_origin); @@ -938,7 +937,7 @@ static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd, static void knife_start_cut(KnifeTool_OpData *kcd) { kcd->prev = kcd->curr; - kcd->curr.is_space = 0; /*TODO: why do we do this? */ + kcd->curr.is_space = 0; /* TODO: why do we do this? */ if (kcd->prev.vert == NULL && kcd->prev.edge == NULL) { float origin[3], origin_ofs[3]; @@ -953,7 +952,7 @@ static void knife_start_cut(KnifeTool_OpData *kcd) zero_v3(kcd->prev.cage); } - copy_v3_v3(kcd->prev.co, kcd->prev.cage); /*TODO: do we need this? */ + copy_v3_v3(kcd->prev.co, kcd->prev.cage); /* TODO: do we need this? */ copy_v3_v3(kcd->curr.cage, kcd->prev.cage); copy_v3_v3(kcd->curr.co, kcd->prev.co); } @@ -1161,7 +1160,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, } else if (lh1->kfe) { kfe->v1 = knife_split_edge(kcd, lh1->kfe, lh1->hit, lh1->cagehit, &kfe2); - lh1->v = kfe->v1; /* record the KnifeVert for this hit */ + lh1->v = kfe->v1; /* Record the #KnifeVert for this hit. */ } else { BLI_assert(lh1->f); @@ -1169,7 +1168,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, kfe->v1->is_cut = true; kfe->v1->is_face = true; knife_append_list(kcd, &kfe->v1->faces, lh1->f); - lh1->v = kfe->v1; /* record the KnifeVert for this hit */ + lh1->v = kfe->v1; /* Record the #KnifeVert for this hit. */ } if (lh2->v) { @@ -1476,7 +1475,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd) } } - /* Note: as following loop progresses, the 'v' fields of + /* NOTE: as following loop progresses, the 'v' fields of * the linehits will be filled in (as edges are split or * in-face verts are made), so it may be true that both * the v and the kfe or f fields will be non-NULL. */ @@ -1745,7 +1744,7 @@ static bool point_is_visible(KnifeTool_OpData *kcd, float view[3], p_ofs[3]; /* TODO: I think there's a simpler way to get the required raycast ray */ - ED_view3d_unproject(kcd->vc.region, s[0], s[1], 0.0f, view); + ED_view3d_unproject_v3(kcd->vc.region, s[0], s[1], 0.0f, view); mul_m4_v3(kcd->ob_imat, view); @@ -1761,7 +1760,7 @@ static bool point_is_visible(KnifeTool_OpData *kcd, if (RV3D_CLIPPING_ENABLED(kcd->vc.v3d, kcd->vc.rv3d)) { float view_clip[2][3]; - /* note: view_clip[0] should never get clipped */ + /* NOTE: view_clip[0] should never get clipped. */ copy_v3_v3(view_clip[0], p_ofs); madd_v3_v3v3fl(view_clip[1], p_ofs, view, dist); @@ -2140,9 +2139,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) BLI_smallhash_release(&faces); BLI_smallhash_release(&kfes); BLI_smallhash_release(&kfvs); - if (results) { - MEM_freeN(results); - } + MEM_freeN(results); } /** \} */ @@ -2807,8 +2804,12 @@ static void knifetool_finish_ex(KnifeTool_OpData *kcd) knife_make_cuts(kcd); EDBM_selectmode_flush(kcd->em); - EDBM_mesh_normals_update(kcd->em); - EDBM_update_generic(kcd->ob->data, true, true); + EDBM_update(kcd->ob->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); /* Re-tessellating makes this invalid, don't use again by accident. */ knifetool_free_bmbvh(kcd); diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index aa144dd3f3c..09b17acf56d 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -30,6 +30,7 @@ #include "BKE_context.h" #include "BKE_curve.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" @@ -59,7 +60,7 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C, { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); ARegion *region = CTX_wm_region(C); - struct Mesh *me_eval; + const struct Mesh *me_eval; bool me_eval_needs_free; if (ob->type == OB_MESH || ob->runtime.data_eval) { @@ -113,7 +114,7 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C, BKE_nurbList_free(&nurbslist); if (me_eval_needs_free) { - BKE_mesh_free(me_eval); + BKE_mesh_free((struct Mesh *)me_eval); } } diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 2057738221b..0a4fecde6ea 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -209,7 +209,12 @@ static void ringsel_finish(bContext *C, wmOperator *op) /* when used in a macro the tessfaces will be recalculated anyway, * this is needed here because modifiers depend on updated tessellation, see T45920 */ - EDBM_update_generic(lcd->ob->data, true, true); + EDBM_update(lcd->ob->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); if (is_single) { /* de-select endpoints */ @@ -218,7 +223,7 @@ static void ringsel_finish(bContext *C, wmOperator *op) EDBM_selectmode_flush_ex(lcd->em, SCE_SELECT_VERTEX); } - /* we cant slide multiple edges in vertex select mode */ + /* we can't slide multiple edges in vertex select mode */ else if (is_macro && (cuts > 1) && (em->selectmode & SCE_SELECT_VERTEX)) { EDBM_selectmode_disable(lcd->vc.scene, em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); } @@ -236,7 +241,7 @@ static void ringsel_finish(bContext *C, wmOperator *op) * in editmesh_select.c (around line 1000)... */ /* sets as active, useful for other tools */ if (em->selectmode & SCE_SELECT_VERTEX) { - /* low priority TODO, get vertrex close to mouse */ + /* low priority TODO: get vertrex close to mouse. */ BM_select_history_store(em->bm, lcd->eed->v1); } if (em->selectmode & SCE_SELECT_EDGE) { diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index 7d849c096e7..cccfc7e934c 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -126,7 +126,7 @@ static int geometry_extract_apply(bContext *C, .calc_face_normal = true, })); - BMEditMesh *em = BKE_editmesh_create(bm, false); + BMEditMesh *em = BKE_editmesh_create(bm); /* Generate the tags for deleting geometry in the extracted object. */ tag_fn(bm, params); @@ -206,7 +206,7 @@ static int geometry_extract_apply(bContext *C, }), mesh); - BKE_editmesh_free(em); + BKE_editmesh_free_data(em); MEM_freeN(em); if (new_mesh->totvert == 0) { @@ -229,7 +229,7 @@ static int geometry_extract_apply(bContext *C, /* Remove the mask from the new object so it can be sculpted directly after extracting. */ CustomData_free_layers(&new_ob_mesh->vdata, CD_PAINT_MASK, new_ob_mesh->totvert); - BKE_mesh_copy_settings(new_ob_mesh, mesh); + BKE_mesh_copy_parameters_for_eval(new_ob_mesh, mesh); if (params->apply_shrinkwrap) { BKE_shrinkwrap_mesh_nearest_surface_deform(C, new_ob, ob); @@ -567,7 +567,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op) BKE_mesh_nomain_to_mesh(new_ob_mesh, new_ob->data, new_ob, &CD_MASK_MESH, true); BKE_mesh_calc_normals(new_ob->data); - BKE_mesh_copy_settings(new_ob->data, mesh); + BKE_mesh_copy_parameters_for_eval(new_ob->data, mesh); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, new_ob); BKE_mesh_batch_cache_dirty_tag(new_ob->data, BKE_MESH_BATCH_DIRTY_ALL); DEG_relations_tag_update(bmain); diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index b7f671a4157..30a453a32ee 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -29,6 +29,7 @@ #include "DNA_windowmanager_types.h" #ifdef WITH_FREESTYLE +# include "BKE_customdata.h" # include "DNA_meshdata_types.h" #endif @@ -270,7 +271,12 @@ static void mouse_mesh_shortest_path_vert(Scene *UNUSED(scene), } } - EDBM_update_generic(obedit->data, false, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } /** \} */ @@ -474,7 +480,12 @@ static void mouse_mesh_shortest_path_edge(Scene *scene, } } - EDBM_update_generic(obedit->data, false, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); if (op_params->edge_mode == EDGE_MODE_TAG_SEAM) { ED_uvedit_live_unwrap(scene, &obedit, 1); @@ -591,7 +602,12 @@ static void mouse_mesh_shortest_path_face(Scene *UNUSED(scene), BM_mesh_active_face_set(bm, f_dst_last); } - EDBM_update_generic(obedit->data, false, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } /** \} */ diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c index 4d37b78c9b7..303cf41df0d 100644 --- a/source/blender/editors/mesh/editmesh_polybuild.c +++ b/source/blender/editors/mesh/editmesh_polybuild.c @@ -154,8 +154,12 @@ static int edbm_polybuild_transform_at_cursor_invoke(bContext *C, BM_face_select_set(bm, (BMFace *)ele_act, true); } - EDBM_mesh_normals_update(em); - EDBM_update_generic(vc.obedit->data, true, true); + EDBM_update(vc.obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); if (basact != NULL) { if (vc.view_layer->basact != basact) { ED_object_base_activate(C, basact); @@ -237,8 +241,12 @@ static int edbm_polybuild_delete_at_cursor_invoke(bContext *C, } if (changed) { - EDBM_mesh_normals_update(em); - EDBM_update_generic(vc.obedit->data, true, true); + EDBM_update(vc.obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); if (basact != NULL) { if (vc.view_layer->basact != basact) { ED_object_base_activate(C, basact); @@ -400,8 +408,12 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con } if (changed) { - EDBM_mesh_normals_update(em); - EDBM_update_generic(vc.obedit->data, true, true); + EDBM_update(vc.obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); if (basact != NULL) { if (vc.view_layer->basact != basact) { @@ -488,8 +500,12 @@ static int edbm_polybuild_split_at_cursor_invoke(bContext *C, } if (changed) { - EDBM_mesh_normals_update(em); - EDBM_update_generic(vc.obedit->data, true, true); + EDBM_update(vc.obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); WM_event_add_mousemove(vc.win); @@ -559,7 +575,7 @@ static int edbm_polybuild_dissolve_at_cursor_invoke(bContext *C, else { /* too involved to do inline */ - /* Avoid using selection so failure wont leave modified state. */ + /* Avoid using selection so failure won't leave modified state. */ EDBM_flag_disable_all(em, BM_ELEM_TAG); BM_elem_flag_enable(v_act, BM_ELEM_TAG); @@ -578,8 +594,12 @@ static int edbm_polybuild_dissolve_at_cursor_invoke(bContext *C, if (changed) { edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT); - EDBM_mesh_normals_update(em); - EDBM_update_generic(vc.obedit->data, true, true); + EDBM_update(vc.obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); if (vc.view_layer->basact != basact) { ED_object_base_activate(C, basact); diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 222d44f85d8..5a2a090b725 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -170,15 +170,15 @@ static float edbm_rip_edge_side_measure( * * The method used for checking the side of selection is as follows... * - First tag all rip-able edges. - * - Build a contiguous edge list by looping over tagged edges and following each ones tagged + * - Build a contiguous edge list by looping over tagged edges and following each one's tagged * siblings in both directions. - * - The loops are not stored in an array, Instead both loops on either side of each edge has - * its index values set to count down from the last edge, this way, once we have the 'last' - * edge its very easy to walk down the connected edge loops. - * The reason for using loops like this is because when the edges are split we don't which - * face user gets the newly created edge - * (its as good as random so we cant assume new edges will be on once side). - * After splitting, its very simple to walk along boundary loops since each only has one edge + * - The loops are not stored in an array. Instead both loops on either side of each edge has + * its index values set to count down from the last edge. This way once we have the 'last' + * edge it's very easy to walk down the connected edge loops. + * The reason for using loops like this is because when the edges are split we don't know + * which face user gets the newly created edge + * (it's as good as random so we can't assume new edges will be on one side). + * After splitting, it's very simple to walk along boundary loops since each only has one edge * from a single side. * - The end loop pairs are stored in an array however to support multiple edge-selection-islands, * so you can rip multiple selections at once. @@ -189,7 +189,7 @@ static float edbm_rip_edge_side_measure( * * Limitation! * This currently works very poorly with intersecting edge islands - * (verts with more than 2 tagged edges). This is nice to but for now not essential. + * (verts with more than 2 tagged edges). This is nice to do but for now not essential. * * - campbell. */ @@ -270,7 +270,7 @@ static EdgeLoopPair *edbm_ripsel_looptag_helper(BMesh *bm) break; } - /* initialize */ + /* Initialize. */ e_first = e; v_step = e_first->v1; e_step = NULL; /* quiet warning, will never remain this value */ @@ -639,7 +639,7 @@ static int edbm_rip_invoke__vert(bContext *C, const wmEvent *event, Object *obed /* should we go ahead with edge rip or do we need to do special case, split off vertex?: * split off vertex if... - * - we cant find an edge - this means we are ripping a faces vert that is connected to other + * - we can't find an edge - this means we are ripping a faces vert that is connected to other * geometry only at the vertex. * - the boundary edge total is greater than 2, * in this case edge split _can_ work but we get far nicer results if we use this special case. @@ -927,7 +927,7 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed /* single edge, extend */ if (i == 1 && e_best->l) { - /* note: if the case of 3 edges has one change in loop stepping, + /* NOTE: if the case of 3 edges has one change in loop stepping, * if this becomes more involved we may be better off splitting * the 3 edge case into its own else-if branch */ if ((totedge_manifold == 4 || totedge_manifold == 3) || (all_manifold == false)) { @@ -975,7 +975,7 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed BM_mesh_edgesplit(em->bm, true, true, true); - /* note: the output of the bmesh operator is ignored, since we built + /* NOTE: the output of the bmesh operator is ignored, since we built * the contiguous loop pairs to split already, its possible that some * edge did not split even though it was tagged which would not work * as expected (but not crash), however there are checks to ensure @@ -1082,7 +1082,12 @@ static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event) } error_rip_failed = false; - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); diff --git a/source/blender/editors/mesh/editmesh_rip_edge.c b/source/blender/editors/mesh/editmesh_rip_edge.c index 6775cb85ef9..f7e88284d93 100644 --- a/source/blender/editors/mesh/editmesh_rip_edge.c +++ b/source/blender/editors/mesh/editmesh_rip_edge.c @@ -223,7 +223,12 @@ static int edbm_rip_edge_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve BM_mesh_select_mode_flush(bm); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } } diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 6cb103460f6..830c9abb41e 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -35,6 +35,8 @@ #include "BLI_utildefines_stack.h" #include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_layer.h" #include "BKE_report.h" @@ -434,7 +436,7 @@ struct NearestEdgeUserData { struct NearestEdgeUserData_Hit hit_cycle; }; -/* note; uses v3d, so needs active 3d window */ +/* NOTE: uses v3d, so needs active 3d window. */ static void find_nearest_edge__doClosest( void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { @@ -547,8 +549,10 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenEdge( - vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenEdge(vc, + find_nearest_edge_center__doZBuf, + &data, + V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT); *r_dist_center_px_manhattan = data.dist; } @@ -601,7 +605,8 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, *dist_px_manhattan_p; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag); + mesh_foreachScreenEdge( + vc, find_nearest_edge__doClosest, &data, clip_flag | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT); hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; @@ -961,7 +966,7 @@ static bool unified_findnearest(ViewContext *vc, } } - /* return only one of 3 pointers, for frontbuffer redraws */ + /* Return only one of 3 pointers, for front-buffer redraws. */ if (hit.v.ele) { hit.f.ele = NULL; hit.e.ele = NULL; @@ -1802,7 +1807,7 @@ static bool mouse_mesh_loop( V3D_PROJ_RET_OK) { tdist = len_squared_v2v2(mvalf, co); if (tdist < best_dist) { - /* printf("Best face: %p (%f)\n", f, tdist);*/ + // printf("Best face: %p (%f)\n", f, tdist); best_dist = tdist; efa = f; } @@ -2568,7 +2573,7 @@ bool EDBM_selectmode_disable(Scene *scene, const short selectmode_fallback) { /* note essential, but switch out of vertex mode since the - * selected regions wont be nicely isolated after flushing */ + * selected regions won't be nicely isolated after flushing */ if (em->selectmode & selectmode_disable) { if (em->selectmode == selectmode_disable) { em->selectmode = selectmode_fallback; @@ -2980,7 +2985,7 @@ bool EDBM_select_interior_faces(BMEditMesh *em) int i_b = BM_elem_index_get(l_pair[1]->f); if (i_a != i_b) { /* Only for predictable results that don't depend on the order of radial loops, - * not essential. */ + * not essential. */ if (i_a > i_b) { SWAP(int, i_a, i_b); } @@ -3443,7 +3448,7 @@ static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, in select_linked_delimit_begin(bm, delimit); } - /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */ + /* NOTE: logic closely matches #edbm_select_linked_exec, keep in sync. */ if (ele->head.htype == BM_VERT) { BMVert *eve = (BMVert *)ele; @@ -3639,8 +3644,9 @@ static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op) { ViewLayer *view_layer = CTX_data_view_layer(C); - const int object_index = RNA_int_get(op->ptr, "object_index"); - const int index = RNA_int_get(op->ptr, "index"); + /* Intentionally wrap negative values so the lookup fails. */ + const uint object_index = (uint)RNA_int_get(op->ptr, "object_index"); + const uint index = (uint)RNA_int_get(op->ptr, "index"); ele = EDBM_elem_from_index_any_multi(view_layer, object_index, index, &obedit); } @@ -4270,7 +4276,12 @@ static int edbm_select_nth_exec(bContext *C, wmOperator *op) if (edbm_deselect_nth(em, &op_params) == true) { found_active_elt = true; - EDBM_update_generic(obedit->data, false, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } } MEM_freeN(objects); @@ -4643,7 +4654,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op) } } - BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed); + BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed_iter); const int count_select = elem_map_len * randfac; for (int i = 0; i < count_select; i++) { BM_vert_select_set(em->bm, elem_map[i], select); @@ -4659,7 +4670,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op) elem_map[elem_map_len++] = eed; } } - BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed); + BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed_iter); const int count_select = elem_map_len * randfac; for (int i = 0; i < count_select; i++) { BM_edge_select_set(em->bm, elem_map[i], select); @@ -4675,7 +4686,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op) elem_map[elem_map_len++] = efa; } } - BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed); + BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed_iter); const int count_select = elem_map_len * randfac; for (int i = 0; i < count_select; i++) { BM_face_select_set(em->bm, elem_map[i], select); @@ -4730,10 +4741,11 @@ static bool edbm_select_ungrouped_poll(bContext *C) BMEditMesh *em = BKE_editmesh_from_object(obedit); const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT); + const ListBase *defbase = BKE_object_defgroup_list(obedit); if ((em->selectmode & SCE_SELECT_VERTEX) == 0) { CTX_wm_operator_poll_msg_set(C, "Must be in vertex selection mode"); } - else if (BLI_listbase_is_empty(&obedit->defbase) || cd_dvert_offset == -1) { + else if (BLI_listbase_is_empty(defbase) || cd_dvert_offset == -1) { CTX_wm_operator_poll_msg_set(C, "No weights/vertex groups on object"); } else { diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index f3c0da67ecc..c452f7a7487 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -29,6 +29,8 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_layer.h" #include "BKE_material.h" @@ -497,7 +499,12 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) if (changed) { EDBM_selectmode_flush(em); - EDBM_update_generic(ob->data, false, false); + EDBM_update(ob->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } } @@ -519,7 +526,12 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) } } EDBM_selectmode_flush(em); - EDBM_update_generic(ob->data, false, false); + EDBM_update(ob->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } } @@ -549,7 +561,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) * \{ */ /** - * Note: This is not normal, but the edge direction itself and always in + * NOTE: This is not normal, but the edge direction itself and always in * a positive quadrant (tries z, y then x). * Therefore we need to use the entire object transformation matrix. */ @@ -917,7 +929,12 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op) if (changed) { EDBM_selectmode_flush(em); - EDBM_update_generic(ob->data, false, false); + EDBM_update(ob->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } } @@ -939,7 +956,12 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op) } } EDBM_selectmode_flush(em); - EDBM_update_generic(ob->data, false, false); + EDBM_update(ob->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } } @@ -1021,7 +1043,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) if (cd_dvert_offset == -1) { continue; } - defbase_len = BLI_listbase_count(&ob->defbase); + defbase_len = BKE_object_defgroup_count(ob); if (defbase_len == 0) { continue; } @@ -1070,8 +1092,10 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) /* We store the names of the vertex groups, so we can select * vertex groups with the same name in different objects. */ + const ListBase *defbase = BKE_object_defgroup_list(ob); + int i = 0; - LISTBASE_FOREACH (bDeformGroup *, dg, &ob->defbase) { + LISTBASE_FOREACH (bDeformGroup *, dg, defbase) { if (BLI_BITMAP_TEST(defbase_selected, i)) { BLI_gset_add(gset, dg->name); } @@ -1108,7 +1132,8 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) if (cd_dvert_offset == -1) { continue; } - defbase_len = BLI_listbase_count(&ob->defbase); + const ListBase *defbase = BKE_object_defgroup_list(ob); + defbase_len = BLI_listbase_count(defbase); if (defbase_len == 0) { continue; } @@ -1121,7 +1146,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) GSetIterator gs_iter; GSET_ITER (gs_iter, gset) { const char *name = BLI_gsetIterator_getKey(&gs_iter); - int vgroup_id = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)); + int vgroup_id = BLI_findstringindex(defbase, name, offsetof(bDeformGroup, name)); if (vgroup_id != -1) { BLI_BITMAP_ENABLE(defbase_selected, vgroup_id); found_any = true; @@ -1213,7 +1238,12 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) if (changed) { EDBM_selectmode_flush(em); - EDBM_update_generic(ob->data, false, false); + EDBM_update(ob->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index bb332a4094c..41a9f426798 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -44,6 +44,7 @@ #include "BLI_string.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_key.h" @@ -132,7 +133,12 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) false, seed); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -140,7 +146,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -/* Note, these values must match delete_mesh() event values */ +/* NOTE: these values must match delete_mesh() event values. */ static const EnumPropertyItem prop_mesh_cornervert_types[] = { {SUBD_CORNER_INNERVERT, "INNERVERT", 0, "Inner Vert", ""}, {SUBD_CORNER_PATH, "PATH", 0, "Path", ""}, @@ -240,7 +246,7 @@ static void mesh_operator_edgering_props(wmOperatorType *ot, const int cuts_min, const int cuts_default) { - /* Note, these values must match delete_mesh() event values */ + /* NOTE: these values must match delete_mesh() event values. */ static const EnumPropertyItem prop_subd_edgering_types[] = { {SUBD_RING_INTERP_LINEAR, "LINEAR", 0, "Linear", ""}, {SUBD_RING_INTERP_PATH, "PATH", 0, "Blend Path", ""}, @@ -324,7 +330,12 @@ static int edbm_subdivide_edge_ring_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -384,7 +395,12 @@ static int edbm_unsubdivide_exec(bContext *C, wmOperator *op) } EDBM_selectmode_flush(em); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -416,7 +432,7 @@ void MESH_OT_unsubdivide(wmOperatorType *ot) /** \name Delete Operator * \{ */ -/* Note, these values must match delete_mesh() event values */ +/* NOTE: these values must match delete_mesh() event values. */ enum { MESH_DELETE_VERT = 0, MESH_DELETE_EDGE = 1, @@ -499,7 +515,12 @@ static int edbm_delete_exec(bContext *C, wmOperator *op) BM_custom_loop_normals_from_vector_layer(em->bm, false); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); @@ -628,7 +649,12 @@ static int edbm_delete_loose_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } int totelem_new[3]; @@ -686,7 +712,12 @@ static int edbm_collapse_edge_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -943,7 +974,7 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) #ifdef USE_FACE_CREATE_SEL_EXTEND /* normally we would want to leave the new geometry selected, * but being able to press F many times to add geometry is too useful! */ - if (ele_desel && (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) && + if (ele_desel && (BMO_slot_buffer_len(bmop.slots_out, "faces.out") == 1) && (ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out"))) { edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face); } @@ -954,7 +985,7 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) * copying face data from surrounding, may have copied hidden face flag too. * * Important that faces use flushing since 'edges.out' - * wont include hidden edges that already existed. + * won't include hidden edges that already existed. */ BMO_slot_buffer_hflag_disable( em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_HIDDEN, true); @@ -971,7 +1002,12 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); changed_multi = true; } MEM_freeN(objects); @@ -1047,7 +1083,12 @@ static int edbm_mark_seam_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -1117,7 +1158,12 @@ static int edbm_mark_sharp_exec(bContext *C, wmOperator *op) BM_elem_flag_set(eed, BM_ELEM_SMOOTH, clear); } - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -1219,9 +1265,12 @@ static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator * } } if (checks_succeded) { + BMBackup em_backup = EDBM_redo_state_store(em); + BM_custom_loop_normals_to_vector_layer(bm); BMO_op_exec(bm, &bmop); + const bool failure = BMO_error_occurred_at_level(bm, BMO_ERROR_FATAL); len = BMO_slot_get(bmop.slots_out, "edges.out")->len; if (len && is_pair) { @@ -1230,16 +1279,31 @@ static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator * em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true); } - if (!EDBM_op_finish(em, &bmop, op, true)) { + bool em_backup_free = true; + if (!EDBM_op_finish(em, &bmop, op, false)) { len = 0; } + else if (failure) { + len = 0; + EDBM_redo_state_restore_and_free(&em_backup, em, true); + em_backup_free = false; + } else { /* so newly created edges get the selection state from the vertex */ EDBM_selectmode_flush(em); BM_custom_loop_normals_from_vector_layer(bm, false); - EDBM_update_generic(me, true, true); + EDBM_update(me, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); + } + + if (em_backup_free) { + EDBM_redo_state_free(&em_backup); } } MEM_freeN(verts); @@ -1538,7 +1602,12 @@ static int edbm_vert_connect_path_exec(bContext *C, wmOperator *op) BM_custom_loop_normals_from_vector_layer(bm, false); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } else { failed_selection_order_len++; @@ -1603,7 +1672,12 @@ static int edbm_vert_connect_concave_exec(bContext *C, wmOperator *op) em, op, "faces.out", true, "connect_verts_concave faces=%hf", BM_ELEM_SELECT)) { continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -1657,7 +1731,12 @@ static int edbm_vert_connect_nonplaner_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -1726,7 +1805,12 @@ static int edbm_face_make_planar_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -1775,7 +1859,12 @@ static bool edbm_edge_split_selected_edges(wmOperator *op, Object *obedit, BMEdi BM_custom_loop_normals_from_vector_layer(em->bm, false); EDBM_select_flush(em); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); return true; } @@ -1845,7 +1934,12 @@ static bool edbm_edge_split_selected_verts(wmOperator *op, Object *obedit, BMEdi BM_custom_loop_normals_from_vector_layer(em->bm, false); EDBM_select_flush(em); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); return true; } @@ -1958,7 +2052,12 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op) if (!EDBM_op_finish(em, &bmop, op, true)) { continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -2114,7 +2213,12 @@ static int edbm_flip_normals_exec(bContext *C, wmOperator *op) lnor_ed->clnors_data); } BM_loop_normal_editdata_array_free(lnors_ed_arr); - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } continue; } @@ -2133,7 +2237,12 @@ static int edbm_flip_normals_exec(bContext *C, wmOperator *op) } if (flip_custom_normals(em->bm, lnors_ed_arr) || has_flipped_faces) { - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } if (lnors_ed_arr != NULL) { @@ -2214,8 +2323,8 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) } } - /* ok, we don't have two adjacent faces, but we do have two selected ones. - * that's an error condition.*/ + /* OK, we don't have two adjacent faces, but we do have two selected ones. + * that's an error condition. */ if (tot == 0) { continue; } @@ -2236,7 +2345,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) BMO_slot_buffer_hflag_enable( em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true); - const int tot_rotate = BMO_slot_buffer_count(bmop.slots_out, "edges.out"); + const int tot_rotate = BMO_slot_buffer_len(bmop.slots_out, "edges.out"); const int tot_failed = tot - tot_rotate; tot_rotate_all += tot_rotate; @@ -2255,7 +2364,12 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -2341,7 +2455,12 @@ static int edbm_hide_exec(bContext *C, wmOperator *op) } if (EDBM_mesh_hide(em, unselected)) { - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); changed = true; } } @@ -2392,7 +2511,12 @@ static int edbm_reveal_exec(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); if (EDBM_mesh_reveal(em, select)) { - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } } MEM_freeN(objects); @@ -2458,7 +2582,12 @@ static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op) } } - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -2570,7 +2699,12 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) EDBM_verts_mirror_cache_end(em); } - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -2694,7 +2828,12 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) EDBM_verts_mirror_cache_end(em); } - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -2787,7 +2926,12 @@ static int edbm_faces_shade_smooth_exec(bContext *C, wmOperator *UNUSED(op)) } mesh_set_smooth_faces(em, 1); - EDBM_update_generic(obedit->data, false, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -2830,7 +2974,12 @@ static int edbm_faces_shade_flat_exec(bContext *C, wmOperator *UNUSED(op)) } mesh_set_smooth_faces(em, 0); - EDBM_update_generic(obedit->data, false, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -2877,17 +3026,20 @@ static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op) BMOperator bmop; - /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw); - /* execute the operator */ BMO_op_exec(em->bm, &bmop); if (!EDBM_op_finish(em, &bmop, op, true)) { continue; } - EDBM_update_generic(obedit->data, false, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -2910,17 +3062,19 @@ static int edbm_reverse_uvs_exec(bContext *C, wmOperator *op) BMOperator bmop; - /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ EDBM_op_init(em, &bmop, op, "reverse_uvs faces=%hf", BM_ELEM_SELECT); - /* execute the operator */ BMO_op_exec(em->bm, &bmop); - /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, true)) { continue; } - EDBM_update_generic(obedit->data, false, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -2946,19 +3100,21 @@ static int edbm_rotate_colors_exec(bContext *C, wmOperator *op) BMOperator bmop; - /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw); - /* execute the operator */ BMO_op_exec(em->bm, &bmop); - /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, true)) { continue; } /* dependencies graph and notification stuff */ - EDBM_update_generic(ob->data, false, false); + EDBM_update(ob->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -2983,18 +3139,20 @@ static int edbm_reverse_colors_exec(bContext *C, wmOperator *op) BMOperator bmop; - /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ EDBM_op_init(em, &bmop, op, "reverse_colors faces=%hf", BM_ELEM_SELECT); - /* execute the operator */ BMO_op_exec(em->bm, &bmop); - /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, true)) { - return OPERATOR_CANCELLED; + continue; } - EDBM_update_generic(obedit->data, false, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -3243,7 +3401,12 @@ static int edbm_merge_exec(bContext *C, wmOperator *op) BM_custom_loop_normals_from_vector_layer(em->bm, false); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); /* once collapsed, we can't have edge/face selection */ if ((em->selectmode & SCE_SELECT_VERTEX) == 0) { @@ -3422,7 +3585,12 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) if (count) { count_multi += count; - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } } MEM_freeN(objects); @@ -3474,7 +3642,7 @@ void MESH_OT_remove_doubles(wmOperatorType *ot) /** \name Shape Key Propagate Operator * \{ */ -/* BMESH_TODO this should be properly encapsulated in a bmop. but later.*/ +/* BMESH_TODO this should be properly encapsulated in a bmop. but later. */ static bool shape_propagate(BMEditMesh *em) { BMIter iter; @@ -3522,7 +3690,12 @@ static int edbm_shape_propagate_to_all_exec(bContext *C, wmOperator *op) tot_shapekeys++; } - EDBM_update_generic(me, false, false); + EDBM_update(me, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -3562,7 +3735,7 @@ void MESH_OT_shape_propagate_to_all(wmOperatorType *ot) /** \name Blend from Shape Operator * \{ */ -/* BMESH_TODO this should be properly encapsulated in a bmop. but later.*/ +/* BMESH_TODO this should be properly encapsulated in a bmop. but later. */ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op) { Object *obedit_ref = CTX_data_edit_object(C); @@ -3644,7 +3817,12 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op) interp_v3_v3v3(eve->co, eve->co, co, blend); } } - EDBM_update_generic(me, true, false); + EDBM_update(me, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = false, + }); } } MEM_freeN(objects); @@ -3781,7 +3959,12 @@ static int edbm_solidify_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -3858,7 +4041,7 @@ static float bm_edge_seg_isect(const float sco_a[2], b2 = ((x22 * y21) - (x21 * y22)) / xdiff2; } else { - m2 = MAXSLOPE; /* Vertical slope */ + m2 = MAXSLOPE; /* Vertical slope. */ b2 = x22; } @@ -3908,7 +4091,7 @@ static float bm_edge_seg_isect(const float sco_a[2], /* Calculate the distance from point to line. */ if (m2 != MAXSLOPE) { - /* sqrt(m2 * m2 + 1); Only looking for change in sign. Skip extra math .*/ + /* `sqrt(m2 * m2 + 1);` Only looking for change in sign. Skip extra math. */ dist = (y12 - m2 * x12 - b2); } else { @@ -3930,8 +4113,8 @@ static float bm_edge_seg_isect(const float sco_a[2], m1 = MAXSLOPE; b1 = x12; } - x2max = max_ff(x21, x22) + 0.001f; /* prevent missed edges */ - x2min = min_ff(x21, x22) - 0.001f; /* due to round off error */ + x2max = max_ff(x21, x22) + 0.001f; /* Prevent missed edges. */ + x2min = min_ff(x21, x22) - 0.001f; /* Due to round off error. */ y2max = max_ff(y21, y22) + 0.001f; y2min = min_ff(y21, y22) - 0.001f; @@ -3959,9 +4142,9 @@ static float bm_edge_seg_isect(const float sco_a[2], yi = (b1 * m2 - m1 * b2) / (m2 - m1); } - /* Intersect inside bounding box of edge?*/ + /* Intersect inside bounding box of edge? */ if ((xi >= x2min) && (xi <= x2max) && (yi <= y2max) && (yi >= y2min)) { - /* test for vertex intersect that may be 'close enough'*/ + /* Test for vertex intersect that may be 'close enough'. */ if (mode != KNIFE_MULTICUT) { if (xi <= (x21 + threshold) && xi >= (x21 - threshold)) { if (yi <= (y21 + threshold) && yi >= (y21 - threshold)) { @@ -4042,7 +4225,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) /* for ED_view3d_project_float_object */ ED_view3d_init_mats_rv3d(obedit, region->regiondata); - /* TODO, investigate using index lookup for screen_vert_coords() rather than a hash table */ + /* TODO: investigate using index lookup for #screen_vert_coords() rather than a hash table. */ /* the floating point coordinates of verts in screen space will be * stored in a hash table according to the vertices pointer */ @@ -4064,7 +4247,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* store percentage of edge cut for KNIFE_EXACT here.*/ + /* Store percentage of edge cut for KNIFE_EXACT here. */ BMOpSlot *slot_edge_percents = BMO_slot_get(bmop.slots_in, "edge_percents"); BM_ITER_MESH (be, &iter, bm, BM_EDGES_OF_MESH) { bool is_cut = false; @@ -4072,7 +4255,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) const float *sco_a = screen_vert_coords[BM_elem_index_get(be->v1)]; const float *sco_b = screen_vert_coords[BM_elem_index_get(be->v2)]; - /* check for error value (vert cant be projected) */ + /* check for error value (vert can't be projected) */ if ((sco_a[0] != FLT_MAX) && (sco_b[0] != FLT_MAX)) { isect = bm_edge_seg_isect(sco_a, sco_b, mouse_path, len, mode, &isected); @@ -4113,7 +4296,12 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) BM_custom_loop_normals_from_vector_layer(bm, false); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); return OPERATOR_FINISHED; } @@ -4516,7 +4704,12 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) } if (retval) { - EDBM_update_generic(base->object->data, true, true); + EDBM_update(base->object->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } } MEM_freeN(bases); @@ -4563,7 +4756,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) .calc_object_remap = true, })); - DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY_ALL_MODES); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); } @@ -4664,7 +4857,12 @@ static int edbm_fill_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -4958,7 +5156,12 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -5030,7 +5233,12 @@ static int edbm_fill_holes_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -5113,7 +5321,12 @@ static int edbm_beautify_fill_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -5197,9 +5410,12 @@ static int edbm_poke_face_exec(bContext *C, wmOperator *op) continue; } - EDBM_mesh_normals_update(em); - - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -5301,7 +5517,12 @@ static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op) BM_custom_loop_normals_from_vector_layer(em->bm, false); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -5413,7 +5634,12 @@ static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op) BM_custom_loop_normals_from_vector_layer(em->bm, false); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -5514,7 +5740,7 @@ static int edbm_decimate_exec(bContext *C, wmOperator *op) float *vweights = MEM_mallocN(sizeof(*vweights) * bm->totvert, __func__); { const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); - const int defbase_act = obedit->actdef - 1; + const int defbase_act = BKE_object_defgroup_active_index_get(obedit) - 1; if (use_vertex_group && (cd_dvert_offset == -1)) { BKE_report(op->reports, RPT_WARNING, "No active vertex group"); @@ -5597,7 +5823,12 @@ static int edbm_decimate_exec(bContext *C, wmOperator *op) } EDBM_selectmode_flush_ex(em, selectmode); } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -5646,7 +5877,7 @@ void MESH_OT_decimate(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* Note, keep in sync with 'rna_def_modifier_decimate' */ + /* NOTE: keep in sync with 'rna_def_modifier_decimate'. */ RNA_def_float(ot->srna, "ratio", 1.0f, 0.0f, 1.0f, "Ratio", "", 0.0f, 1.0f); RNA_def_boolean(ot->srna, @@ -5736,7 +5967,12 @@ static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op) BM_custom_loop_normals_from_vector_layer(em->bm, false); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -5797,7 +6033,12 @@ static int edbm_dissolve_edges_exec(bContext *C, wmOperator *op) BM_custom_loop_normals_from_vector_layer(em->bm, false); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -5858,7 +6099,12 @@ static int edbm_dissolve_faces_exec(bContext *C, wmOperator *op) BM_custom_loop_normals_from_vector_layer(em->bm, false); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -6003,7 +6249,12 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op) BM_custom_loop_normals_from_vector_layer(em->bm, false); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -6090,7 +6341,12 @@ static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op) /* tricky to maintain correct selection here, so just flush up from verts */ EDBM_select_flush(em); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); totelem_new[0] += bm->totvert; totelem_new[1] += bm->totedge; @@ -6181,7 +6437,12 @@ static int edbm_delete_edgeloop_exec(bContext *C, wmOperator *op) EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -6242,10 +6503,13 @@ static int edbm_split_exec(bContext *C, wmOperator *op) continue; } - /* Geometry has changed, need to recalc normals and looptris */ - EDBM_mesh_normals_update(em); - - EDBM_update_generic(obedit->data, true, true); + /* Geometry has changed, need to recalculate normals and tessellation. */ + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -6297,7 +6561,7 @@ enum { typedef struct BMElemSort { /** Sort factor */ float srt; - /** Original index of this element _in its mempool_ */ + /** Original index of this element (in its #BLI_mempool). */ int org_idx; } BMElemSort; @@ -6490,7 +6754,7 @@ static void sort_bmelem_flag(bContext *C, BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) { if (BM_elem_flag_test(fa, flag)) { /* Reverse materials' order, not order of faces inside each mat! */ - /* Note: cannot use totcol, as mat_nr may sometimes be greater... */ + /* NOTE: cannot use totcol, as mat_nr may sometimes be greater... */ float srt = reverse ? (float)(MAXMAT - fa->mat_nr) : (float)fa->mat_nr; pb[i] = false; sb[affected[2]].org_idx = i; @@ -6697,9 +6961,9 @@ static void sort_bmelem_flag(bContext *C, } } - /* printf("%d vertices: %d to be affected...\n", totelem[0], affected[0]);*/ - /* printf("%d edges: %d to be affected...\n", totelem[1], affected[1]);*/ - /* printf("%d faces: %d to be affected...\n", totelem[2], affected[2]);*/ + // printf("%d vertices: %d to be affected...\n", totelem[0], affected[0]); + // printf("%d edges: %d to be affected...\n", totelem[1], affected[1]); + // printf("%d faces: %d to be affected...\n", totelem[2], affected[2]); if (affected[0] == 0 && affected[1] == 0 && affected[2] == 0) { for (j = 3; j--;) { if (pblock[j]) { @@ -6960,7 +7224,7 @@ static int edbm_bridge_tag_boundary_edges(BMesh *bm) /* check if its only used by selected faces */ BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - /* tag face for removal*/ + /* Tag face for removal. */ if (!BM_elem_flag_test(f, BM_ELEM_TAG)) { BM_elem_flag_enable(f, BM_ELEM_TAG); totface_del++; @@ -7043,7 +7307,7 @@ static int edbm_bridge_edge_loops_for_single_editmesh(wmOperator *op, BMO_op_exec(em->bm, &bmop); - if (!BMO_error_occurred(em->bm)) { + if (!BMO_error_occurred_at_level(em->bm, BMO_ERROR_CANCEL)) { /* when merge is used the edges are joined and remain selected */ if (use_merge == false) { EDBM_flag_disable_all(em, BM_ELEM_SELECT); @@ -7085,7 +7349,12 @@ static int edbm_bridge_edge_loops_for_single_editmesh(wmOperator *op, } if (EDBM_op_finish(em, &bmop, op, true)) { - EDBM_update_generic(me, true, true); + EDBM_update(me, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } /* Always return finished so the user can select different options. */ @@ -7220,7 +7489,12 @@ static int edbm_wireframe_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); } MEM_freeN(objects); @@ -7311,7 +7585,12 @@ static int edbm_offset_edgeloop_exec(bContext *C, wmOperator *op) em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true); if (EDBM_op_finish(em, &bmop, op, true)) { - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); changed_multi = true; } } @@ -7394,7 +7673,7 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) BMO_op_exec(em->bm, &bmop); /* Hull fails if input is coplanar */ - if (BMO_error_occurred(em->bm)) { + if (BMO_error_occurred_at_level(em->bm, BMO_ERROR_CANCEL)) { EDBM_op_finish(em, &bmop, op, true); continue; } @@ -7441,7 +7720,12 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); EDBM_selectmode_flush(em); } @@ -7529,7 +7813,12 @@ static int mesh_symmetrize_exec(bContext *C, wmOperator *op) if (!EDBM_op_finish(em, &bmop, op, true)) { continue; } - EDBM_update_generic(obedit->data, true, true); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = true, + }); EDBM_selectmode_flush(em); } MEM_freeN(objects); @@ -7671,7 +7960,12 @@ static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op) } } } - EDBM_update_generic(obedit->data, false, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); /* No need to end cache, just free the array. */ MEM_freeN(index); @@ -7928,7 +8222,7 @@ enum { EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED = 114, }; -/* called in transform_ops.c, on each regeneration of keymaps */ +/* Called in transform_ops.c, on each regeneration of key-maps. */ wmKeyMap *point_normals_modal_keymap(wmKeyConfig *keyconf) { static const EnumPropertyItem modal_items[] = { @@ -8094,7 +8388,7 @@ static void point_normals_update_header(bContext *C, wmOperator *op) ED_area_status_text(CTX_wm_area(C), header); } -/* TODO move that to generic function in BMesh? */ +/* TODO: move that to generic function in BMesh? */ static void bmesh_selected_verts_center_calc(BMesh *bm, float *r_center) { BMVert *v; @@ -8347,7 +8641,12 @@ static int edbm_point_normals_modal(bContext *C, wmOperator *op, const wmEvent * if (point_normals_ensure(C, op)) { point_normals_apply(C, op, target, do_reset); - EDBM_update_generic(obedit->data, true, false); /* Recheck bools. */ + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); /* Recheck bools. */ point_normals_update_header(C, op); } else { @@ -8404,7 +8703,12 @@ static int edbm_point_normals_exec(bContext *C, wmOperator *op) point_normals_apply(C, op, target, false); - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); point_normals_cancel(C, op); return OPERATOR_FINISHED; @@ -8663,7 +8967,12 @@ static int normals_split_merge(bContext *C, const bool do_merge) BM_loop_normal_editdata_array_free(lnors_ed_arr); } - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -8875,7 +9184,12 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op) } while ((l_curr = l_curr->next) != l_first); } - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } BLI_heapsimple_free(loop_weight, NULL); @@ -9126,7 +9440,12 @@ static int edbm_normals_tools_exec(bContext *C, wmOperator *op) BM_loop_normal_editdata_array_free(lnors_ed_arr); - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -9280,7 +9599,12 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op) MEM_freeN(loop_set); MEM_freeN(vnors); - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -9370,7 +9694,7 @@ static int edbm_smooth_normals_exec(bContext *C, wmOperator *op) BKE_lnor_space_custom_data_to_normal( bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->clnors_data, current_normal); - /* Note: again, this is not true spherical interpolation that normals would need... + /* NOTE: again, this is not true spherical interpolation that normals would need... * But it's probably good enough for now. */ mul_v3_fl(current_normal, 1.0f - factor); mul_v3_fl(smooth_normal[i], factor); @@ -9388,7 +9712,12 @@ static int edbm_smooth_normals_exec(bContext *C, wmOperator *op) BM_loop_normal_editdata_array_free(lnors_ed_arr); MEM_freeN(smooth_normal); - EDBM_update_generic(obedit->data, true, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); @@ -9477,7 +9806,12 @@ static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op) } } - EDBM_update_generic(obedit->data, false, false); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = false, + .calc_normals = false, + .is_destructive = false, + }); } MEM_freeN(objects); diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 79385e28aa9..fc9e1aa8b1a 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -33,6 +33,7 @@ #include "BLI_listbase.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_key.h" #include "BKE_layer.h" @@ -93,6 +94,12 @@ typedef struct BArrayCustomData { #endif typedef struct UndoMesh { + /** + * This undo-meshes in `um_arraystore.local_links`. + * Not to be confused with the next and previous undo steps. + */ + struct UndoMesh *local_next, *local_prev; + Mesh me; int selectmode; @@ -128,7 +135,10 @@ static struct { struct BArrayStore_AtSize bs_stride; int users; - /* We could have the undo API pass in the previous state, for now store a local list */ + /** + * A list of #UndoMesh items ordered from oldest to newest + * used to access previous undo data for a mesh. + */ ListBase local_links; # ifdef USE_ARRAY_STORE_THREAD @@ -520,11 +530,63 @@ static void um_arraystore_free(UndoMesh *um) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Array Store Utilities + * \{ */ + +/** + * Create an array of #UndoMesh from `objects`. + * + * where each element in the resulting array is the most recently created + * undo-mesh for the object's mesh. + * When no undo-mesh can be found that array index is NULL. + * + * This is used for de-duplicating memory between undo steps, + * failure to find the undo step will store a full duplicate in memory. + * define `DEBUG_PRINT` to check memory is de-duplicating as expected. + */ +static UndoMesh **mesh_undostep_reference_elems_from_objects(Object **object, int object_len) +{ + /* Map: `Mesh.id.session_uuid` -> `UndoMesh`. */ + GHash *uuid_map = BLI_ghash_ptr_new_ex(__func__, object_len); + UndoMesh **um_references = MEM_callocN(sizeof(UndoMesh *) * object_len, __func__); + for (int i = 0; i < object_len; i++) { + const Mesh *me = object[i]->data; + BLI_ghash_insert(uuid_map, POINTER_FROM_INT(me->id.session_uuid), &um_references[i]); + } + int uuid_map_len = object_len; + + /* Loop backwards over all previous mesh undo data until either: + * - All elements have been found (where `um_references` we'll have every element set). + * - There are no undo steps left to look for. */ + UndoMesh *um_iter = um_arraystore.local_links.last; + while (um_iter && (uuid_map_len != 0)) { + UndoMesh **um_p; + if ((um_p = BLI_ghash_popkey(uuid_map, POINTER_FROM_INT(um_iter->me.id.session_uuid), NULL))) { + *um_p = um_iter; + uuid_map_len--; + } + um_iter = um_iter->local_prev; + } + BLI_assert(uuid_map_len == BLI_ghash_len(uuid_map)); + BLI_ghash_free(uuid_map, NULL, NULL); + if (uuid_map_len == object_len) { + MEM_freeN(um_references); + um_references = NULL; + } + return um_references; +} + +/** \} */ + #endif /* USE_ARRAY_STORE */ /* for callbacks */ /* undo simply makes copies of a bmesh */ -static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key) +/** + * \param um_ref: The reference to use for de-duplicating memory between undo-steps. + */ +static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, UndoMesh *um_ref) { BLI_assert(BLI_array_is_zeroed(um, 1)); #ifdef USE_ARRAY_STORE_THREAD @@ -560,14 +622,8 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key) #ifdef USE_ARRAY_STORE { - /* We could be more clever here, - * the previous undo state may be from a separate mesh. */ - const UndoMesh *um_ref = um_arraystore.local_links.last ? - ((LinkData *)um_arraystore.local_links.last)->data : - NULL; - /* Add ourselves. */ - BLI_addtail(&um_arraystore.local_links, BLI_genericNodeN(um)); + BLI_addtail(&um_arraystore.local_links, um); # ifdef USE_ARRAY_STORE_THREAD if (um_arraystore.task_pool == NULL) { @@ -583,6 +639,8 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key) um_arraystore_compact_with_info(um, um_ref); # endif } +#else + UNUSED_VARS(um_ref); #endif return um; @@ -614,7 +672,7 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key * em->bm->shapenr = um->shapenr; - EDBM_mesh_free(em); + EDBM_mesh_free_data(em); bm = BM_mesh_create(&allocsize, &((struct BMeshCreateParams){ @@ -624,13 +682,21 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key * BM_mesh_bm_from_me(bm, &um->me, (&(struct BMeshFromMeshParams){ - .calc_face_normal = true, + /* Handled with tessellation. */ + .calc_face_normal = false, .active_shapekey = um->shapenr, })); - em_tmp = BKE_editmesh_create(bm, true); + em_tmp = BKE_editmesh_create(bm); *em = *em_tmp; + /* Calculate face normals and tessellation at once since it's multi-threaded. + * The vertex normals are stored in the undo-mesh, so this doesn't need to be updated. */ + BKE_editmesh_looptri_calc_ex(em, + &(const struct BMeshCalcTessellation_Params){ + .face_normals = true, + }); + em->selectmode = um->selectmode; bm->selectmode = um->selectmode; @@ -682,11 +748,9 @@ static void undomesh_free_data(UndoMesh *um) /* we need to expand so any allocations in custom-data are freed with the mesh */ um_arraystore_expand(um); - { - LinkData *link = BLI_findptr(&um_arraystore.local_links, um, offsetof(LinkData, data)); - BLI_remlink(&um_arraystore.local_links, link); - MEM_freeN(link); - } + BLI_assert(BLI_findindex(&um_arraystore.local_links, um) != -1); + BLI_remlink(&um_arraystore.local_links, um); + um_arraystore_free(um); #endif @@ -720,7 +784,6 @@ static Object *editmesh_object_from_context(bContext *C) * \{ */ typedef struct MeshUndoStep_Elem { - struct MeshUndoStep_Elem *next, *prev; UndoRefID_Object obedit_ref; UndoMesh data; } MeshUndoStep_Elem; @@ -749,6 +812,12 @@ static bool mesh_undosys_step_encode(struct bContext *C, struct Main *bmain, Und us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__); us->elems_len = objects_len; + UndoMesh **um_references = NULL; + +#ifdef USE_ARRAY_STORE + um_references = mesh_undostep_reference_elems_from_objects(objects, objects_len); +#endif + for (uint i = 0; i < objects_len; i++) { Object *ob = objects[i]; MeshUndoStep_Elem *elem = &us->elems[i]; @@ -756,12 +825,22 @@ static bool mesh_undosys_step_encode(struct bContext *C, struct Main *bmain, Und elem->obedit_ref.ptr = ob; Mesh *me = elem->obedit_ref.ptr->data; BMEditMesh *em = me->edit_mesh; - undomesh_from_editmesh(&elem->data, me->edit_mesh, me->key); + undomesh_from_editmesh( + &elem->data, me->edit_mesh, me->key, um_references ? um_references[i] : NULL); em->needs_flush_to_id = 1; us->step.data_size += elem->data.undo_size; + +#ifdef USE_ARRAY_STORE + /** As this is only data storage it is safe to set the session ID here. */ + elem->data.me.id.session_uuid = me->id.session_uuid; +#endif } MEM_freeN(objects); + if (um_references != NULL) { + MEM_freeN(um_references); + } + bmain->is_memfile_undo_flush_needed = true; return true; @@ -795,7 +874,7 @@ static void mesh_undosys_step_decode(struct bContext *C, BMEditMesh *em = me->edit_mesh; undomesh_to_editmesh(&elem->data, obedit, em, me->key); em->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 19c9909039c..85c646d689c 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -68,6 +68,9 @@ * just as the undo stack would. * So leaving this as an interface for further work */ +/** + * Save a copy of the #BMesh for restoring later. + */ BMBackup EDBM_redo_state_store(BMEditMesh *em) { BMBackup backup; @@ -75,42 +78,41 @@ BMBackup EDBM_redo_state_store(BMEditMesh *em) return backup; } -void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess) +void EDBM_redo_state_restore(BMBackup *backup, BMEditMesh *em, bool recalc_looptri) { BMesh *tmpbm; - if (!em || !backup.bmcopy) { - return; - } BM_mesh_data_free(em->bm); - tmpbm = BM_mesh_copy(backup.bmcopy); + tmpbm = BM_mesh_copy(backup->bmcopy); *em->bm = *tmpbm; MEM_freeN(tmpbm); tmpbm = NULL; - if (recalctess) { + if (recalc_looptri) { BKE_editmesh_looptri_calc(em); } } -void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess) +/** + * Delete the backup, flushing it to an edit-mesh. + */ +void EDBM_redo_state_restore_and_free(BMBackup *backup, BMEditMesh *em, bool recalc_looptri) { - if (em && backup->bmcopy) { - BM_mesh_data_free(em->bm); - *em->bm = *backup->bmcopy; - } - else if (backup->bmcopy) { - BM_mesh_data_free(backup->bmcopy); + BM_mesh_data_free(em->bm); + *em->bm = *backup->bmcopy; + MEM_freeN(backup->bmcopy); + backup->bmcopy = NULL; + if (recalc_looptri) { + BKE_editmesh_looptri_calc(em); } +} +void EDBM_redo_state_free(BMBackup *backup) +{ if (backup->bmcopy) { + BM_mesh_data_free(backup->bmcopy); MEM_freeN(backup->bmcopy); } - backup->bmcopy = NULL; - - if (recalctess && em) { - BKE_editmesh_looptri_calc(em); - } } /** \} */ @@ -132,75 +134,76 @@ bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char * return false; } - if (!em->emcopy) { - em->emcopy = BKE_editmesh_copy(em); - } - em->emcopyusers++; - va_end(list); return true; } -/* returns 0 on error, 1 on success. executes and finishes a bmesh operator */ +/** + * The return value: + * - False on error (the mesh must not be changed). + * - True on success, executes and finishes a #BMesh operator. + */ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool do_report) { const char *errmsg; - BMO_op_finish(em->bm, bmop); - - if (BMO_error_get(em->bm, &errmsg, NULL)) { - BMEditMesh *emcopy = em->emcopy; +#ifndef NDEBUG + struct { + int verts_len, edges_len, loops_len, faces_len; + } em_state_prev = { + .verts_len = em->bm->totvert, + .edges_len = em->bm->totedge, + .loops_len = em->bm->totloop, + .faces_len = em->bm->totface, + }; +#endif - if (do_report) { - BKE_report(op->reports, RPT_ERROR, errmsg); - } + BMO_op_finish(em->bm, bmop); - EDBM_mesh_free(em); - *em = *emcopy; - - MEM_freeN(emcopy); - em->emcopyusers = 0; - em->emcopy = NULL; - - /** - * Note, we could pass in the mesh, however this is an exceptional case, allow a slow lookup. - * - * This is needed because the COW mesh makes a full copy of the #BMEditMesh - * instead of sharing the pointer, tagging since this has been freed above, - * the #BMEditMesh.emcopy needs to be flushed to the COW edit-mesh, see T55457. - */ - { - Main *bmain = G_MAIN; - for (Mesh *mesh = bmain->meshes.first; mesh; mesh = mesh->id.next) { - if (mesh->edit_mesh == em) { - DEG_id_tag_update(&mesh->id, ID_RECALC_COPY_ON_WRITE); - break; - } + bool changed = false; + bool changed_was_set = false; + + eBMOpErrorLevel level; + while (BMO_error_pop(em->bm, &errmsg, NULL, &level)) { + ReportType type = RPT_INFO; + switch (level) { + case BMO_ERROR_CANCEL: { + changed_was_set = true; + break; + } + case BMO_ERROR_WARN: { + type = RPT_WARNING; + changed_was_set = true; + changed = true; + break; + } + case BMO_ERROR_FATAL: { + type = RPT_ERROR; + changed_was_set = true; + changed = true; + break; } } - /* when copying, tessellation isn't to for faster copying, - * but means we need to re-tessellate here */ - if (em->looptris == NULL) { - BKE_editmesh_looptri_calc(em); + if (do_report) { + BKE_report(op->reports, type, errmsg); } - - return false; } - - em->emcopyusers--; - if (em->emcopyusers < 0) { - printf("warning: em->emcopyusers was less than zero.\n"); + if (changed_was_set == false) { + changed = true; } - if (em->emcopyusers <= 0) { - BKE_editmesh_free(em->emcopy); - MEM_freeN(em->emcopy); - em->emcopy = NULL; +#ifndef NDEBUG + if (changed == false) { + BLI_assert((em_state_prev.verts_len == em->bm->totvert) && + (em_state_prev.edges_len == em->bm->totedge) && + (em_state_prev.loops_len == em->bm->totloop) && + (em_state_prev.faces_len == em->bm->totface)); } +#endif - return true; + return changed; } bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...) @@ -217,11 +220,6 @@ bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...) return false; } - if (!em->emcopy) { - em->emcopy = BKE_editmesh_copy(em); - } - em->emcopyusers++; - BMO_op_exec(bm, &bmop); va_end(list); @@ -249,11 +247,6 @@ bool EDBM_op_call_and_selectf(BMEditMesh *em, return false; } - if (!em->emcopy) { - em->emcopy = BKE_editmesh_copy(em); - } - em->emcopyusers++; - BMO_op_exec(bm, &bmop); slot_select_out = BMO_slot_get(bmop.slots_out, select_slot_out); @@ -284,11 +277,6 @@ bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...) return false; } - if (!em->emcopy) { - em->emcopy = BKE_editmesh_copy(em); - } - em->emcopyusers++; - BMO_op_exec(bm, &bmop); va_end(list); @@ -317,17 +305,13 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) if (me->edit_mesh) { /* this happens when switching shape keys */ - EDBM_mesh_free(me->edit_mesh); + EDBM_mesh_free_data(me->edit_mesh); MEM_freeN(me->edit_mesh); } - /* currently executing operators re-tessellates, so we can avoid doing here - * but at some point it may need to be added back. */ -#if 0 - me->edit_mesh = BKE_editmesh_create(bm, true); -#else - me->edit_mesh = BKE_editmesh_create(bm, false); -#endif + /* Executing operators re-tessellates, + * so we can avoid doing here but at some point it may need to be added back. */ + me->edit_mesh = BKE_editmesh_create(bm); me->edit_mesh->selectmode = me->edit_mesh->bm->selectmode = select_mode; me->edit_mesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0; @@ -338,7 +322,8 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) /** * \warning This can invalidate the #Mesh runtime cache of other objects (for linked duplicates). - * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913 + * Most callers should run #DEG_id_tag_update on `ob->data`, see: T46738, T46913. + * This ensures #BKE_object_free_derived_caches runs on all objects that use this mesh. */ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data) { @@ -358,25 +343,6 @@ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data) .calc_object_remap = true, .update_shapekey_indices = !free_data, })); - - /* Free derived mesh. usually this would happen through depsgraph but there - * are exceptions like file save that will not cause this, and we want to - * avoid ending up with an invalid derived mesh then. - * - * Do it for all objects which shares the same mesh datablock, since their - * derived meshes might also be referencing data which was just freed, - * - * Annoying enough, but currently seems most efficient way to avoid access - * of freed data on scene update, especially in cases when there are dependency - * cycles. - */ -#if 0 - for (Object *other_object = bmain->objects.first; other_object != NULL; other_object = other_object->id.next) { - if (other_object->data == ob->data) { - BKE_object_free_derived_caches(other_object); - } - } -#endif } void EDBM_mesh_clear(BMEditMesh *em) @@ -384,8 +350,8 @@ void EDBM_mesh_clear(BMEditMesh *em) /* clear bmesh */ BM_mesh_clear(em->bm); - /* free derived meshes */ - BKE_editmesh_free_derivedmesh(em); + /* Free evaluated meshes & cache. */ + BKE_editmesh_free_derived_caches(em); /* free tessellation data */ em->tottri = 0; @@ -401,9 +367,9 @@ void EDBM_mesh_load(Main *bmain, Object *ob) } /** - * Should only be called on the active editmesh, otherwise call #BKE_editmesh_free + * Should only be called on the active edit-mesh, otherwise call #BKE_editmesh_free_data. */ -void EDBM_mesh_free(BMEditMesh *em) +void EDBM_mesh_free_data(BMEditMesh *em) { /* These tables aren't used yet, so it's not strictly necessary * to 'end' them but if someone tries to start using them, @@ -411,7 +377,7 @@ void EDBM_mesh_free(BMEditMesh *em) ED_mesh_mirror_spatial_table_end(NULL); ED_mesh_mirror_topo_table_end(NULL); - BKE_editmesh_free(em); + BKE_editmesh_free_data(em); } /** \} */ @@ -438,7 +404,7 @@ void EDBM_selectmode_to_scene(bContext *C) void EDBM_selectmode_flush_ex(BMEditMesh *em, const short selectmode) { - BM_mesh_select_mode_flush_ex(em->bm, selectmode); + BM_mesh_select_mode_flush_ex(em->bm, selectmode, BM_SELECT_LEN_FLUSH_RECALC_ALL); } void EDBM_selectmode_flush(BMEditMesh *em) @@ -474,7 +440,7 @@ void EDBM_select_more(BMEditMesh *em, const bool use_face_step) use_faces, use_face_step); BMO_op_exec(em->bm, &bmop); - /* don't flush selection in edge/vertex mode */ + /* Don't flush selection in edge/vertex mode. */ BMO_slot_buffer_hflag_enable( em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false); BMO_op_finish(em->bm, &bmop); @@ -496,7 +462,7 @@ void EDBM_select_less(BMEditMesh *em, const bool use_face_step) use_faces, use_face_step); BMO_op_exec(em->bm, &bmop); - /* don't flush selection in edge/vertex mode */ + /* Don't flush selection in edge/vertex mode. */ BMO_slot_buffer_hflag_disable( em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false); BMO_op_finish(em->bm, &bmop); @@ -1011,7 +977,7 @@ BMFace *EDBM_uv_active_face_get(BMEditMesh *em, const bool sloppy, const bool se return NULL; } -/* can we edit UV's for this mesh?*/ +/* Can we edit UV's for this mesh? */ bool EDBM_uv_check(BMEditMesh *em) { /* some of these checks could be a touch overkill */ @@ -1222,12 +1188,12 @@ BMVert *EDBM_verts_mirror_get(BMEditMesh *em, BMVert *v) BMEdge *EDBM_verts_mirror_get_edge(BMEditMesh *em, BMEdge *e) { - BMVert *v1_mirr = EDBM_verts_mirror_get(em, e->v1); - if (v1_mirr) { - BMVert *v2_mirr = EDBM_verts_mirror_get(em, e->v2); - if (v2_mirr) { - return BM_edge_exists(v1_mirr, v2_mirr); - } + BMVert *v1_mirr, *v2_mirr; + if ((v1_mirr = EDBM_verts_mirror_get(em, e->v1)) && + (v2_mirr = EDBM_verts_mirror_get(em, e->v2)) && + /* While highly unlikely, a zero length central edges vertices can match, see T89342. */ + LIKELY(v1_mirr != v2_mirr)) { + return BM_edge_exists(v1_mirr, v2_mirr); } return NULL; @@ -1405,9 +1371,17 @@ bool EDBM_mesh_reveal(BMEditMesh *em, bool select) /** \name Update API * \{ */ +void EDBM_mesh_normals_update_ex(BMEditMesh *em, const struct BMeshNormalsUpdate_Params *params) +{ + BM_mesh_normals_update_ex(em->bm, params); +} + void EDBM_mesh_normals_update(BMEditMesh *em) { - BM_mesh_normals_update(em->bm); + EDBM_mesh_normals_update_ex(em, + &(const struct BMeshNormalsUpdate_Params){ + .face_normals = true, + }); } void EDBM_stats_update(BMEditMesh *em) @@ -1439,21 +1413,32 @@ void EDBM_stats_update(BMEditMesh *em) } } -/* so many tools call these that we better make it a generic function. +/** + * So many tools call these that we better make it a generic function. */ -void EDBM_update_generic(Mesh *mesh, const bool do_tessellation, const bool is_destructive) +void EDBM_update(Mesh *mesh, const struct EDBMUpdate_Params *params) { BMEditMesh *em = mesh->edit_mesh; /* Order of calling isn't important. */ DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_GEOM | ND_DATA, &mesh->id); - if (do_tessellation) { - BKE_editmesh_looptri_calc(em); + if (params->calc_normals && params->calc_looptri) { + /* Calculating both has some performance gains. */ + BKE_editmesh_looptri_and_normals_calc(em); + } + else { + if (params->calc_normals) { + EDBM_mesh_normals_update(em); + } + + if (params->calc_looptri) { + BKE_editmesh_looptri_calc(em); + } } - if (is_destructive) { - /* TODO. we may be able to remove this now! - Campbell */ + if (params->is_destructive) { + /* TODO(campbell): we may be able to remove this now! */ // BM_mesh_elem_table_free(em->bm, BM_ALL_NOLOOP); } else { @@ -1464,8 +1449,8 @@ void EDBM_update_generic(Mesh *mesh, const bool do_tessellation, const bool is_d BM_lnorspace_invalidate(em->bm, false); em->bm->spacearr_dirty &= ~BM_SPACEARR_BMO_SET; } - /* don't keep stale derivedMesh data around, see: T38872. */ - BKE_editmesh_free_derivedmesh(em); + /* Don't keep stale evaluated mesh data around, see: T38872. */ + BKE_editmesh_free_derived_caches(em); #ifdef DEBUG { @@ -1477,6 +1462,17 @@ void EDBM_update_generic(Mesh *mesh, const bool do_tessellation, const bool is_d #endif } +/* Bad level call from Python API. */ +void EDBM_update_extern(struct Mesh *me, const bool do_tessellation, const bool is_destructive) +{ + EDBM_update(me, + &(const struct EDBMUpdate_Params){ + .calc_looptri = do_tessellation, + .calc_normals = false, + .is_destructive = is_destructive, + }); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -1544,7 +1540,7 @@ int EDBM_elem_to_index_any(BMEditMesh *em, BMElem *ele) return index; } -BMElem *EDBM_elem_from_index_any(BMEditMesh *em, int index) +BMElem *EDBM_elem_from_index_any(BMEditMesh *em, uint index) { BMesh *bm = em->bm; @@ -1585,14 +1581,14 @@ int EDBM_elem_to_index_any_multi(ViewLayer *view_layer, } BMElem *EDBM_elem_from_index_any_multi(ViewLayer *view_layer, - int object_index, - int elem_index, + uint object_index, + uint elem_index, Object **r_obedit) { uint bases_len; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(view_layer, NULL, &bases_len); *r_obedit = NULL; - Object *obedit = ((uint)object_index < bases_len) ? bases[object_index]->object : NULL; + Object *obedit = (object_index < bases_len) ? bases[object_index]->object : NULL; MEM_freeN(bases); if (obedit != NULL) { BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -1659,8 +1655,8 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree, scale_point(co1, co2, 0.99); scale_point(co3, co2, 0.99); - /* ok, idea is to generate rays going from the camera origin to the - * three points on the edge (v1, mid, v2)*/ + /* OK, idea is to generate rays going from the camera origin to the + * three points on the edge (v1, mid, v2). */ sub_v3_v3v3(dir1, origin, co1); sub_v3_v3v3(dir2, origin, co2); sub_v3_v3v3(dir3, origin, co3); @@ -1669,8 +1665,8 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree, normalize_v3_length(dir2, epsilon); normalize_v3_length(dir3, epsilon); - /* offset coordinates slightly along view vectors, to avoid - * hitting the faces that own the edge.*/ + /* Offset coordinates slightly along view vectors, + * to avoid hitting the faces that own the edge. */ add_v3_v3v3(co1, co1, dir1); add_v3_v3v3(co2, co2, dir2); add_v3_v3v3(co3, co3, dir3); diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 3a05cde7aa1..73b3fb9724e 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -34,6 +34,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" #include "BKE_report.h" @@ -61,7 +62,6 @@ static CustomData *mesh_customdata_get_type(Mesh *me, const char htype, int *r_t BMesh *bm = (me->edit_mesh) ? me->edit_mesh->bm : NULL; int tot; - /* this */ switch (htype) { case BM_VERT: if (bm) { @@ -167,7 +167,7 @@ static void mesh_uv_reset_array(float **fuv, const int len) fuv[3][0] = 0.0; fuv[3][1] = 1.0; - /*make sure we ignore 2-sided faces*/ + /* Make sure we ignore 2-sided faces. */ } else if (len > 2) { float fac = 0.0f, dfac = 1.0f / (float)len; @@ -253,7 +253,7 @@ void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me) WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); } -/* note: keep in sync with ED_mesh_color_add */ +/* NOTE: keep in sync with #ED_mesh_color_add. */ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set, const bool do_init) { BMEditMesh *em; @@ -378,7 +378,7 @@ bool ED_mesh_uv_texture_remove_named(Mesh *me, const char *name) return false; } -/* note: keep in sync with ED_mesh_uv_texture_add */ +/* NOTE: keep in sync with #ED_mesh_uv_texture_add. */ int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set, const bool do_init) { BMEditMesh *em; @@ -484,7 +484,7 @@ bool ED_mesh_color_remove_named(Mesh *me, const char *name) /*********************** Sculpt Vertex colors operators ************************/ -/* note: keep in sync with ED_mesh_uv_texture_add */ +/* NOTE: keep in sync with #ED_mesh_uv_texture_add. */ int ED_mesh_sculpt_color_add(Mesh *me, const char *name, const bool active_set, const bool do_init) { BMEditMesh *em; @@ -1097,7 +1097,7 @@ static void mesh_add_edges(Mesh *mesh, int len) totedge = mesh->totedge + len; - /* update customdata */ + /* Update custom-data. */ CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_DEFAULT, totedge); CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge); diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 763bdf04d83..f25317e8e85 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -51,7 +51,7 @@ bool EDBM_op_call_and_selectf(struct BMEditMesh *em, const bool select_replace, const char *fmt, ...); -/* Same as above, but doesn't report errors.*/ +/* Same as above, but doesn't report errors. */ bool EDBM_op_call_silentf(struct BMEditMesh *em, const char *fmt, ...); /* these next two functions are the split version of EDBM_op_callf, so you can @@ -77,15 +77,15 @@ struct BMElem *EDBM_elem_from_selectmode(struct BMEditMesh *em, struct BMFace *efa); int EDBM_elem_to_index_any(struct BMEditMesh *em, struct BMElem *ele); -struct BMElem *EDBM_elem_from_index_any(struct BMEditMesh *em, int index); +struct BMElem *EDBM_elem_from_index_any(struct BMEditMesh *em, uint index); int EDBM_elem_to_index_any_multi(struct ViewLayer *view_layer, struct BMEditMesh *em, struct BMElem *ele, int *r_object_index); struct BMElem *EDBM_elem_from_index_any_multi(struct ViewLayer *view_layer, - int object_index, - int elem_index, + uint object_index, + uint elem_index, struct Object **r_obedit); bool edbm_extrude_edges_indiv(struct BMEditMesh *em, diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c index 0f746dfd3a0..5eb69aab48b 100644 --- a/source/blender/editors/mesh/mesh_mirror.c +++ b/source/blender/editors/mesh/mesh_mirror.c @@ -308,8 +308,9 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em, last = 0; - /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2, - * but you cant ever access the last 'a' index of MirrTopoPairs */ + /* Get the pairs out of the sorted hashes. + * NOTE: `totvert + 1` means we can use the previous 2, + * but you can't ever access the last 'a' index of #MirrTopoPairs. */ if (em) { BMVert **vtable = em->bm->vtable; for (a = 1; a <= totvert; a++) { diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 3450d61337c..27fb21e1dfb 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -149,7 +149,7 @@ static void join_mesh_single(Depsgraph *depsgraph, mul_m4_m4m4(cmat, imat, ob_src->obmat); /* transform vertex coordinates into new space */ - for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, mvert++) { + for (a = 0; a < me->totvert; a++, mvert++) { mul_m4_v3(cmat, mvert->co); } @@ -390,7 +390,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* Apply parent transform if the active object's parent was joined to it. - * Note: This doesn't apply recursive parenting. */ + * NOTE: This doesn't apply recursive parenting. */ if (join_parent) { ob->parent = NULL; BKE_object_apply_mat4_ex(ob, ob->obmat, ob->parent, ob->parentinv, false); @@ -475,16 +475,17 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) me = ob_iter->data; /* Join this object's vertex groups to the base one's */ - for (dg = ob_iter->defbase.first; dg; dg = dg->next) { + for (dg = me->vertex_group_names.first; dg; dg = dg->next) { /* See if this group exists in the object (if it doesn't, add it to the end) */ if (!BKE_object_defgroup_find_name(ob, dg->name)) { odg = MEM_mallocN(sizeof(bDeformGroup), "join deformGroup"); memcpy(odg, dg, sizeof(bDeformGroup)); - BLI_addtail(&ob->defbase, odg); + BLI_addtail(&mesh_active->vertex_group_names, odg); } } - if (ob->defbase.first && ob->actdef == 0) { - ob->actdef = 1; + if (!BLI_listbase_is_empty(&mesh_active->vertex_group_names) && + me->vertex_group_active_index == 0) { + me->vertex_group_active_index = 1; } /* Join this object's face maps to the base one's. */ @@ -1060,7 +1061,7 @@ static float *editmesh_get_mirror_uv( cent_vec[1] = face_cent[1]; } - /* TODO - Optimize */ + /* TODO: Optimize. */ { BMIter iter; BMFace *efa; @@ -1473,19 +1474,21 @@ bool ED_mesh_pick_vert( MDeformVert *ED_mesh_active_dvert_get_em(Object *ob, BMVert **r_eve) { - if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH && ob->defbase.first) { + if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH) { Mesh *me = ob->data; - BMesh *bm = me->edit_mesh->bm; - const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); + if (!BLI_listbase_is_empty(&me->vertex_group_names)) { + BMesh *bm = me->edit_mesh->bm; + const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); - if (cd_dvert_offset != -1) { - BMVert *eve = BM_mesh_active_vert_get(bm); + if (cd_dvert_offset != -1) { + BMVert *eve = BM_mesh_active_vert_get(bm); - if (eve) { - if (r_eve) { - *r_eve = eve; + if (eve) { + if (r_eve) { + *r_eve = eve; + } + return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); } - return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); } } } diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c index a8b471a7c92..f7b53b5513f 100644 --- a/source/blender/editors/metaball/editmball_undo.c +++ b/source/blender/editors/metaball/editmball_undo.c @@ -215,7 +215,7 @@ static void mball_undosys_step_decode(struct bContext *C, } undomball_to_editmball(&elem->data, mb); mb->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&mb->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index 77b5379ddd4..4338b043fc9 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -87,7 +87,7 @@ if(WITH_INTERNATIONAL) endif() if(WITH_EXPERIMENTAL_FEATURES) - add_definitions(-DWITH_GEOMETRY_NODES) + add_definitions(-DWITH_SIMULATION_DATABLOCK) add_definitions(-DWITH_POINT_CLOUD) add_definitions(-DWITH_HAIR_NODES) endif() diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index c722a0c00ee..8ae74fbfafa 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -407,7 +407,7 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode) "Enter edit mode when adding this object"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } - /* note: this property gets hidden for add-camera operator */ + /* NOTE: this property gets hidden for add-camera operator. */ prop = RNA_def_enum( ot->srna, "align", align_options, ALIGN_WORLD, "Align", "The alignment of the new object"); RNA_def_property_update_runtime(prop, view_align_update); @@ -456,49 +456,53 @@ void ED_object_add_mesh_props(wmOperatorType *ot) bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view_align_axis, - float loc[3], - float rot[3], - float scale[3], - bool *enter_editmode, - ushort *local_view_bits, - bool *is_view_aligned) -{ - PropertyRNA *prop; - - /* Switch to Edit mode? optional prop */ - if ((prop = RNA_struct_find_property(op->ptr, "enter_editmode"))) { + float r_loc[3], + float r_rot[3], + float r_scale[3], + bool *r_enter_editmode, + ushort *r_local_view_bits, + bool *r_is_view_aligned) +{ + /* Edit Mode! (optional) */ + { bool _enter_editmode; - if (!enter_editmode) { - enter_editmode = &_enter_editmode; + if (!r_enter_editmode) { + r_enter_editmode = &_enter_editmode; } + /* Only to ensure the value is _always_ set. + * Typically the property will exist when the argument is non-NULL. */ + *r_enter_editmode = false; - if (RNA_property_is_set(op->ptr, prop) && enter_editmode) { - *enter_editmode = RNA_property_boolean_get(op->ptr, prop); - } - else { - *enter_editmode = (U.flag & USER_ADD_EDITMODE) != 0; - RNA_property_boolean_set(op->ptr, prop, *enter_editmode); + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "enter_editmode"); + if (prop != NULL) { + if (RNA_property_is_set(op->ptr, prop) && r_enter_editmode) { + *r_enter_editmode = RNA_property_boolean_get(op->ptr, prop); + } + else { + *r_enter_editmode = (U.flag & USER_ADD_EDITMODE) != 0; + RNA_property_boolean_set(op->ptr, prop, *r_enter_editmode); + } } } - if (local_view_bits) { + if (r_local_view_bits) { View3D *v3d = CTX_wm_view3d(C); - *local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; + *r_local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; } /* Location! */ { float _loc[3]; - if (!loc) { - loc = _loc; + if (!r_loc) { + r_loc = _loc; } if (RNA_struct_property_is_set(op->ptr, "location")) { - RNA_float_get_array(op->ptr, "location", loc); + RNA_float_get_array(op->ptr, "location", r_loc); } else { - ED_object_location_from_view(C, loc); - RNA_float_set_array(op->ptr, "location", loc); + ED_object_location_from_view(C, r_loc); + RNA_float_set_array(op->ptr, "location", r_loc); } } @@ -506,33 +510,33 @@ bool ED_object_add_generic_get_opts(bContext *C, { bool _is_view_aligned; float _rot[3]; - if (!is_view_aligned) { - is_view_aligned = &_is_view_aligned; + if (!r_is_view_aligned) { + r_is_view_aligned = &_is_view_aligned; } - if (!rot) { - rot = _rot; + if (!r_rot) { + r_rot = _rot; } 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), don't set it to #ALIGN_WORLD in the op UI though. */ - *is_view_aligned = false; - RNA_float_get_array(op->ptr, "rotation", rot); + *r_is_view_aligned = false; + RNA_float_get_array(op->ptr, "rotation", r_rot); } else { int alignment = ALIGN_WORLD; - prop = RNA_struct_find_property(op->ptr, "align"); + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "align"); if (RNA_property_is_set(op->ptr, prop)) { /* If alignment is set, always use it. */ - *is_view_aligned = alignment == ALIGN_VIEW; + *r_is_view_aligned = alignment == ALIGN_VIEW; alignment = RNA_property_enum_get(op->ptr, prop); } else { /* If alignment is not set, use User Preferences. */ - *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0; - if (*is_view_aligned) { + *r_is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0; + if (*r_is_view_aligned) { RNA_property_enum_set(op->ptr, prop, ALIGN_VIEW); alignment = ALIGN_VIEW; } @@ -547,18 +551,18 @@ bool ED_object_add_generic_get_opts(bContext *C, } switch (alignment) { case ALIGN_WORLD: - RNA_float_get_array(op->ptr, "rotation", rot); + RNA_float_get_array(op->ptr, "rotation", r_rot); break; case ALIGN_VIEW: - ED_object_rotation_from_view(C, rot, view_align_axis); - RNA_float_set_array(op->ptr, "rotation", rot); + ED_object_rotation_from_view(C, r_rot, view_align_axis); + RNA_float_set_array(op->ptr, "rotation", r_rot); break; case ALIGN_CURSOR: { const Scene *scene = CTX_data_scene(C); float tmat[3][3]; BKE_scene_cursor_rot_to_mat3(&scene->cursor, tmat); - mat3_normalized_to_eul(rot, tmat); - RNA_float_set_array(op->ptr, "rotation", rot); + mat3_normalized_to_eul(r_rot, tmat); + RNA_float_set_array(op->ptr, "rotation", r_rot); break; } } @@ -568,19 +572,21 @@ bool ED_object_add_generic_get_opts(bContext *C, /* Scale! */ { float _scale[3]; - if (!scale) { - scale = _scale; + if (!r_scale) { + r_scale = _scale; } /* For now this is optional, we can make it always use. */ - copy_v3_fl(scale, 1.0f); - if ((prop = RNA_struct_find_property(op->ptr, "scale"))) { + copy_v3_fl(r_scale, 1.0f); + + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "scale"); + if (prop != NULL) { if (RNA_property_is_set(op->ptr, prop)) { - RNA_property_float_get_array(op->ptr, prop, scale); + RNA_property_float_get_array(op->ptr, prop, r_scale); } else { - copy_v3_fl(scale, 1.0f); - RNA_property_float_set_array(op->ptr, prop, scale); + copy_v3_fl(r_scale, 1.0f); + RNA_property_float_set_array(op->ptr, prop, r_scale); } } } @@ -1312,13 +1318,14 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op) const int type = RNA_enum_get(op->ptr, "type"); const bool use_in_front = RNA_boolean_get(op->ptr, "use_in_front"); + const bool use_lights = RNA_boolean_get(op->ptr, "use_lights"); const int stroke_depth_order = RNA_enum_get(op->ptr, "stroke_depth_order"); ushort local_view_bits; float loc[3], rot[3]; bool newob = false; - /* Note: We use 'Y' here (not 'Z'), as */ + /* NOTE: We use 'Y' here (not 'Z'), as. */ WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, NULL, NULL, &local_view_bits, NULL)) { return OPERATOR_CANCELLED; @@ -1432,6 +1439,13 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op) id_us_plus(&md->target_material->id); } + if (use_lights) { + ob->dtx |= OB_USE_GPENCIL_LIGHTS; + } + else { + ob->dtx &= ~OB_USE_GPENCIL_LIGHTS; + } + /* Stroke object is drawn in front of meshes by default. */ if (use_in_front) { ob->dtx |= OB_DRAW_IN_FRONT; @@ -1474,6 +1488,7 @@ static void object_add_ui(bContext *UNUSED(C), wmOperator *op) int type = RNA_enum_get(op->ptr, "type"); if (type == GP_LRT_COLLECTION || type == GP_LRT_OBJECT || type == GP_LRT_SCENE) { + uiItemR(layout, op->ptr, "use_lights", 0, NULL, ICON_NONE); uiItemR(layout, op->ptr, "use_in_front", 0, NULL, ICON_NONE); bool in_front = RNA_boolean_get(op->ptr, "use_in_front"); uiLayout *row = uiLayoutRow(layout, false); @@ -1520,6 +1535,8 @@ void OBJECT_OT_gpencil_add(wmOperatorType *ot) false, "In Front", "Show line art grease pencil in front of everything"); + RNA_def_boolean( + ot->srna, "use_lights", false, "Use Lights", "Use lights for this grease pencil object"); RNA_def_enum( ot->srna, "stroke_depth_order", @@ -1828,7 +1845,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) * ready to be moved around to re-time the sound and/or make new sound clips. */ { /* create new data for NLA hierarchy */ - AnimData *adt = BKE_animdata_add_id(&ob->id); + AnimData *adt = BKE_animdata_ensure_id(&ob->id); NlaTrack *nlt = BKE_nlatrack_add(adt, NULL, is_liboverride); NlaStrip *strip = BKE_nla_add_soundstrip(bmain, scene, ob->data); strip->start = CFRA; @@ -1837,7 +1854,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) /* hook them up */ BKE_nlatrack_add_strip(nlt, strip, is_liboverride); - /* auto-name the strip, and give the track an interesting name */ + /* Auto-name the strip, and give the track an interesting name. */ BLI_strncpy(nlt->name, DATA_("SoundTrack"), sizeof(nlt->name)); BKE_nlastrip_validate_name(adt, strip); @@ -1960,7 +1977,7 @@ void OBJECT_OT_pointcloud_add(wmOperatorType *ot) /** \name Delete Object Operator * \{ */ /* remove base from a specific scene */ -/* note: now unlinks constraints as well */ +/* NOTE: now unlinks constraints as well. */ void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob) { if (ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0 && @@ -2137,8 +2154,7 @@ static void copy_object_set_idnew(bContext *C) FOREACH_MAIN_ID_END; #endif - BKE_main_id_tag_all(bmain, LIB_TAG_NEW, false); - BKE_main_id_clear_newpoins(bmain); + BKE_main_id_newptr_and_tag_clear(bmain); } /** \} */ @@ -2147,7 +2163,7 @@ static void copy_object_set_idnew(bContext *C) /** \name Make Instanced Objects Real Operator * \{ */ -/* XXX TODO That whole hierarchy handling based on persistent_id tricks is +/* XXX TODO: That whole hierarchy handling based on persistent_id tricks is * very confusing and convoluted, and it will fail in many cases besides basic ones. * Think this should be replaced by a proper tree-like representation of the instantiations, * should help a lot in both readability, and precise consistent rebuilding of hierarchy. @@ -2426,7 +2442,7 @@ static void make_object_duplilist_real(bContext *C, } if (ob_dst->parent) { - /* note, this may be the parent of other objects, but it should + /* NOTE: this may be the parent of other objects, but it should * still work out ok */ BKE_object_apply_mat4(ob_dst, dob->mat, false, true); @@ -2459,7 +2475,7 @@ static void make_object_duplilist_real(bContext *C, free_object_duplilist(lb_duplis); - BKE_main_id_clear_newpoins(bmain); + BKE_main_id_newptr_and_tag_clear(bmain); base->object->transflag &= ~OB_DUPLI; DEG_id_tag_update(&base->object->id, ID_RECALC_COPY_ON_WRITE); @@ -2474,7 +2490,7 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op) const bool use_base_parent = RNA_boolean_get(op->ptr, "use_base_parent"); const bool use_hierarchy = RNA_boolean_get(op->ptr, "use_hierarchy"); - BKE_main_id_clear_newpoins(bmain); + BKE_main_id_newptr_and_tag_clear(bmain); CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { make_object_duplilist_real(C, depsgraph, scene, base, use_base_parent, use_hierarchy); @@ -2559,7 +2575,7 @@ static void object_data_convert_ensure_curve_cache(Depsgraph *depsgraph, Scene * if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { /* We need 'for render' ON here, to enable computing bevel dipslist if needed. * Also makes sense anyway, we would not want e.g. to lose hidden parts etc. */ - BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false); + BKE_displist_make_curveTypes(depsgraph, scene, ob, true); } else if (ob->type == OB_MBALL) { BKE_displist_make_mball(depsgraph, scene, ob); @@ -2587,8 +2603,8 @@ static void object_data_convert_curve_to_mesh(Main *bmain, Depsgraph *depsgraph, /* Change objects which are using same curve. * A bit annoying, but: * - It's possible to have multiple curve objects selected which are sharing the same curve - * datablock. We don't want mesh to be created for every of those objects. - * - This is how conversion worked for a long long time. */ + * data-block. We don't want mesh to be created for every of those objects. + * - This is how conversion worked for a long time. */ LISTBASE_FOREACH (Object *, other_object, &bmain->objects) { if (other_object->data == curve) { other_object->type = OB_MESH; @@ -2632,10 +2648,10 @@ static Base *duplibase_for_convert( ED_object_base_select(basen, BA_SELECT); ED_object_base_select(base, BA_DESELECT); - /* XXX An ugly hack needed because if we re-run depsgraph with some new MBall objects - * having same 'family name' as orig ones, they will affect end result of MBall computation... + /* XXX: An ugly hack needed because if we re-run depsgraph with some new meta-ball objects + * having same 'family name' as orig ones, they will affect end result of meta-ball computation. * For until we get rid of that name-based thingy in MBalls, that should do the trick - * (this is weak, but other solution (to change name of obn) is even worse imho). + * (this is weak, but other solution (to change name of `obn`) is even worse imho). * See T65996. */ const bool is_meta_ball = (obn->type == OB_MBALL); void *obdata = obn->data; @@ -2778,11 +2794,11 @@ static int object_convert_exec(bContext *C, wmOperator *op) basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); newob = basen->object; - /* decrement original mesh's usage count */ + /* Decrement original mesh's usage count. */ Mesh *me = newob->data; id_us_min(&me->id); - /* make a new copy of the mesh */ + /* Make a new copy of the mesh. */ newob->data = BKE_id_copy(bmain, &me->id); } else { @@ -2852,11 +2868,11 @@ static int object_convert_exec(bContext *C, wmOperator *op) basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); newob = basen->object; - /* decrement original mesh's usage count */ + /* Decrement original mesh's usage count. */ Mesh *me = newob->data; id_us_min(&me->id); - /* make a new copy of the mesh */ + /* Make a new copy of the mesh. */ newob->data = BKE_id_copy(bmain, &me->id); } else { @@ -2877,11 +2893,11 @@ static int object_convert_exec(bContext *C, wmOperator *op) basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); newob = basen->object; - /* decrement original mesh's usage count */ + /* Decrement original mesh's usage count. */ Mesh *me = newob->data; id_us_min(&me->id); - /* make a new copy of the mesh */ + /* Make a new copy of the mesh. */ newob->data = BKE_id_copy(bmain, &me->id); } else { @@ -2890,7 +2906,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) } /* make new mesh data from the original copy */ - /* note: get the mesh from the original, not from the copy in some + /* NOTE: get the mesh from the original, not from the copy in some * cases this doesn't give correct results (when MDEF is used for eg) */ Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); @@ -2899,6 +2915,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) me_eval = BKE_mesh_copy_for_eval(me_eval, false); /* Full (edge-angle based) draw calculation should ideally be performed. */ BKE_mesh_edges_set_draw_render(me_eval); + BKE_object_material_from_eval_data(bmain, newob, &me_eval->id); BKE_mesh_nomain_to_mesh(me_eval, newob->data, newob, &CD_MASK_MESH, true); BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */ } @@ -2909,10 +2926,10 @@ static int object_convert_exec(bContext *C, wmOperator *op) basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); newob = basen->object; - /* decrement original curve's usage count */ + /* Decrement original curve's usage count. */ id_us_min(&((Curve *)newob->data)->id); - /* make a new copy of the curve */ + /* Make a new copy of the curve. */ newob->data = BKE_id_copy(bmain, ob->data); } else { @@ -2990,7 +3007,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); newob = basen->object; - /* decrement original curve's usage count */ + /* Decrement original curve's usage count. */ id_us_min(&((Curve *)newob->data)->id); /* make a new copy of the curve */ @@ -3074,11 +3091,11 @@ static int object_convert_exec(bContext *C, wmOperator *op) basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); newob = basen->object; - /* decrement original pointclouds's usage count */ + /* Decrement original point-cloud's usage count. */ PointCloud *pointcloud = newob->data; id_us_min(&pointcloud->id); - /* make a new copy of the pointcloud */ + /* Make a new copy of the point-cloud. */ newob->data = BKE_id_copy(bmain, &pointcloud->id); } else { @@ -3332,8 +3349,8 @@ static Base *object_add_duplicate_internal(Main *bmain, /* single object duplicate, if dupflag==0, fully linked, else it uses the flags given */ /* leaves selection of base/object unaltered. - * note: don't call this within a loop since clear_* funcs loop over the entire database. - * note: caller must do DAG_relations_tag_update(bmain); + * NOTE: don't call this within a loop since clear_* funcs loop over the entire database. + * NOTE: caller must do DAG_relations_tag_update(bmain); * this is not done automatic since we may duplicate many objects in a batch */ Base *ED_object_add_duplicate( Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, const eDupli_ID_Flags dupflag) @@ -3358,7 +3375,7 @@ Base *ED_object_add_duplicate( DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS); } - BKE_main_id_clear_newpoins(bmain); + BKE_main_id_newptr_and_tag_clear(bmain); return basen; } @@ -3374,8 +3391,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) /* We need to handle that here ourselves, because we may duplicate several objects, in which case * we also want to remap pointers between those... */ - BKE_main_id_tag_all(bmain, LIB_TAG_NEW, false); - BKE_main_id_clear_newpoins(bmain); + BKE_main_id_newptr_and_tag_clear(bmain); CTX_DATA_BEGIN (C, Base *, base, selected_bases) { Base *basen = object_add_duplicate_internal( @@ -3452,6 +3468,19 @@ void OBJECT_OT_duplicate(wmOperatorType *ot) * Use for drag & drop. * \{ */ +static Base *object_add_ensure_in_view_layer(Main *bmain, ViewLayer *view_layer, Object *ob) +{ + Base *base = BKE_view_layer_base_find(view_layer, ob); + + if (!base) { + LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); + BKE_collection_object_add(bmain, layer_collection->collection, ob); + base = BKE_view_layer_base_find(view_layer, ob); + } + + return base; +} + static int object_add_named_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -3459,7 +3488,8 @@ static int object_add_named_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); Base *basen; Object *ob; - const bool linked = RNA_boolean_get(op->ptr, "linked"); + const bool duplicate = RNA_boolean_get(op->ptr, "duplicate"); + const bool linked = duplicate && RNA_boolean_get(op->ptr, "linked"); const eDupli_ID_Flags dupflag = (linked) ? 0 : (eDupli_ID_Flags)U.dupflag; char name[MAX_ID_NAME - 2]; @@ -3473,10 +3503,30 @@ static int object_add_named_exec(bContext *C, wmOperator *op) } /* prepare dupli */ - basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag, 0); + if (duplicate) { + basen = object_add_duplicate_internal( + bmain, + scene, + view_layer, + ob, + dupflag, + /* Sub-process flag because the new-ID remapping (#BKE_libblock_relink_to_newid()) in this + * function will only work if the object is already linked in the view layer, which is not + * the case here. So we have to do the new-ID relinking ourselves + * (#copy_object_set_idnew()). + */ + LIB_ID_DUPLICATE_IS_SUBPROCESS); + } + else { + /* basen is actually not a new base in this case. */ + basen = object_add_ensure_in_view_layer(bmain, view_layer, ob); + } if (basen == NULL) { - BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated"); + BKE_report(op->reports, + RPT_ERROR, + duplicate ? "Object could not be duplicated" : + "Object could not be linked to the view layer"); return OPERATOR_CANCELLED; } @@ -3523,11 +3573,24 @@ void OBJECT_OT_add_named(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + PropertyRNA *prop; + + prop = RNA_def_boolean( + ot->srna, + "duplicate", + true, + "Duplicate", + "Create a duplicate of the object. If not set, only ensures the object is linked into the " + "active view layer, positions and selects/activates it (deselecting others)"); + RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_boolean(ot->srna, "linked", - 0, + false, "Linked", - "Duplicate object but not object data, linking to the original data"); + "Duplicate object but not object data, linking to the original data (ignored if " + "'duplicate' is false)"); + RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Object name to add"); object_add_drop_xy_props(ot); diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index a5cad4e087c..3a10a423e91 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -566,7 +566,7 @@ static int multiresbake_image_exec(bContext *C, wmOperator *op) WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_BAKE_TEXTURE); WM_jobs_customdata_set(wm_job, bkr, multiresbake_freejob); - WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */ + WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO: only draw bake image, can we enforce this. */ WM_jobs_callbacks(wm_job, multiresbake_startjob, NULL, NULL, NULL); G.is_break = false; diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 3370476d466..233f2a65dac 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -158,7 +158,7 @@ static int bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) /** * for exec() when there is no render job - * note: this wont check for the escape key being pressed, but doing so isn't thread-safe. + * NOTE: this won't check for the escape key being pressed, but doing so isn't thread-safe. */ static int bake_break(void *UNUSED(rjv)) { @@ -1374,7 +1374,7 @@ static int bake(const BakeAPIRender *bkr, * the cage is supposed to have interpolated normals * between the faces unless the geometry is physically * split. So we create a copy of the low poly mesh without - * the eventual edge split.*/ + * the eventual edge split. */ if (md->type == eModifierType_EdgeSplit) { BLI_remlink(&ob_low_eval->modifiers, md); @@ -1939,7 +1939,7 @@ static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event) WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_BAKE); WM_jobs_customdata_set(wm_job, bkr, bake_freejob); - /* TODO - only draw bake image, can we enforce this */ + /* TODO: only draw bake image, can we enforce this. */ WM_jobs_timer( wm_job, 0.5, (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) ? NC_GEOM | ND_DATA : NC_IMAGE, 0); WM_jobs_callbacks(wm_job, bake_startjob, NULL, NULL, NULL); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 244124a6e0a..4970338973d 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -547,7 +547,7 @@ static void test_constraint( else { Curve *cu = ct->tar->data; - /* auto-set 'Path' setting on curve so this works */ + /* auto-set 'Path' setting on curve so this works. */ cu->flag |= CU_PATH; } } @@ -696,12 +696,11 @@ static bool edit_constraint_poll_generic(bContext *C, Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); bConstraint *con = ptr.data; - if (!ob) { - CTX_wm_operator_poll_msg_set(C, "Context missing active object"); + if (!ED_operator_object_active_editable_ex(C, ob)) { return false; } - if (ID_IS_LINKED(ob) || (ptr.owner_id && ID_IS_LINKED(ptr.owner_id))) { + if (ptr.owner_id != NULL && ID_IS_LINKED(ptr.owner_id)) { CTX_wm_operator_poll_msg_set(C, "Cannot edit library data"); return false; } @@ -1732,7 +1731,7 @@ static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op)) /* force depsgraph to get recalculated since relationships removed */ DEG_relations_tag_update(bmain); - /* note, calling BIK_clear_data() isn't needed here */ + /* NOTE: calling BIK_clear_data() isn't needed here. */ return OPERATOR_FINISHED; } @@ -1746,8 +1745,8 @@ void POSE_OT_constraints_clear(wmOperatorType *ot) /* callbacks */ ot->exec = pose_constraints_clear_exec; - ot->poll = ED_operator_posemode_exclusive; /* XXX - do we want to ensure there are selected - * bones too? */ + /* XXX: do we want to ensure there are selected bones too? */ + ot->poll = ED_operator_object_active_local_editable_posemode_exclusive; } static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op)) @@ -1978,7 +1977,7 @@ static bool get_new_constraint_target( (!only_curve && !only_mesh)) { /* Only use the object & bone if the bone is visible & selected - * since we may have multiple objects in pose mode at once. */ + * since we may have multiple objects in pose mode at once. */ bPoseChannel *pchan = BKE_pose_channel_active_or_first_selected(ob); if (pchan != NULL) { *tar_pchan = pchan; @@ -2101,7 +2100,7 @@ static int constraint_add_exec( } } - /* do type-specific tweaking to the constraint settings */ + /* Do type-specific tweaking to the constraint settings. */ switch (type) { case CONSTRAINT_TYPE_PYTHON: /* FIXME: this code is not really valid anymore */ { @@ -2462,7 +2461,7 @@ static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op)) /* Refresh depsgraph. */ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - /* Note, notifier might evolve. */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob); } } @@ -2480,7 +2479,7 @@ void POSE_OT_ik_clear(wmOperatorType *ot) /* api callbacks */ ot->exec = pose_ik_clear_exec; - ot->poll = ED_operator_posemode_exclusive; + ot->poll = ED_operator_object_active_local_editable_posemode_exclusive; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 22c9d669ff3..2109fe2a822 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -33,6 +33,7 @@ #include "BKE_context.h" #include "BKE_data_transfer.h" +#include "BKE_deform.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_remap.h" #include "BKE_mesh_runtime.h" @@ -96,7 +97,7 @@ static const EnumPropertyItem DT_layer_items[] = { {0, NULL, 0, NULL, NULL}, }; -/* Note: rna_enum_dt_layers_select_src_items enum is from rna_modifier.c */ +/* NOTE: #rna_enum_dt_layers_select_src_items enum is from rna_modifier.c. */ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), @@ -133,12 +134,13 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C, } if (ob_src) { - bDeformGroup *dg; + const bDeformGroup *dg; int i; RNA_enum_item_add_separator(&item, &totitem); - for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) { + const ListBase *defbase = BKE_object_defgroup_list(ob_src); + for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) { tmp_item.value = i; tmp_item.identifier = tmp_item.name = dg->name; RNA_enum_item_add(&item, &totitem, &tmp_item); @@ -201,7 +203,7 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C, return item; } -/* Note: rna_enum_dt_layers_select_dst_items enum is from rna_modifier.c */ +/* NOTE: #rna_enum_dt_layers_select_dst_items enum is from `rna_modifier.c`. */ static const EnumPropertyItem *dt_layers_select_dst_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), @@ -255,7 +257,7 @@ static const EnumPropertyItem *dt_layers_select_itemf(bContext *C, return dt_layers_select_src_itemf(C, ptr, prop, r_free); } -/* Note: rna_enum_dt_mix_mode_items enum is from rna_modifier.c */ +/* NOTE: rna_enum_dt_mix_mode_items enum is from `rna_modifier.c`. */ static const EnumPropertyItem *dt_mix_mode_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), @@ -511,7 +513,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op) } #if 0 /* TODO */ - /* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */ + /* NOTE: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */ return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED; #else return OPERATOR_FINISHED; @@ -611,23 +613,23 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot) { PropertyRNA *prop; - /* Identifiers.*/ + /* Identifiers. */ ot->name = "Transfer Mesh Data"; ot->idname = "OBJECT_OT_data_transfer"; ot->description = "Transfer data layer(s) (weights, edge sharp, etc.) from active to selected meshes"; - /* API callbacks.*/ + /* API callbacks. */ ot->poll = data_transfer_poll; ot->poll_property = data_transfer_poll_property; ot->invoke = WM_menu_invoke; ot->exec = data_transfer_exec; ot->check = data_transfer_check; - /* Flags.*/ + /* Flags. */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* Properties.*/ + /* Properties. */ prop = RNA_def_boolean(ot->srna, "use_reverse_transfer", false, @@ -767,7 +769,7 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot) } /******************************************************************************/ -/* Note: This operator is hybrid, it can work as a usual standalone Object operator, +/* NOTE: This operator is hybrid, it can work as a usual standalone Object operator, * or as a DataTransfer modifier tool. */ @@ -886,7 +888,7 @@ void OBJECT_OT_datalayout_transfer(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* Properties.*/ + /* Properties. */ edit_modifier_properties(ot); /* Data type to transfer. */ diff --git a/source/blender/editors/object/object_data_transform.c b/source/blender/editors/object/object_data_transform.c index 6e3a5e715f6..4a4ace309e1 100644 --- a/source/blender/editors/object/object_data_transform.c +++ b/source/blender/editors/object/object_data_transform.c @@ -745,8 +745,12 @@ void ED_object_data_xform_tag_update(struct XFormObjectData *xod_base) case ID_ME: { Mesh *me = (Mesh *)xod_base->id; if (xod_base->is_edit_mode) { - EDBM_update_generic(me, true, false); - EDBM_mesh_normals_update(me->edit_mesh); + EDBM_update(me, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = true, + .is_destructive = false, + }); } DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY); break; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 5be572baec5..6108691b2f1 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -105,7 +105,7 @@ #include "CLG_log.h" -/* for menu/popup icons etc etc*/ +/* For menu/popup icons etc etc. */ #include "UI_interface.h" #include "UI_resources.h" @@ -134,8 +134,8 @@ Object *ED_object_context(const bContext *C) return CTX_data_pointer_get_type(C, "object", &RNA_Object).data; } -/* find the correct active object per context - * note: context can be NULL when called from a enum with PROP_ENUM_NO_CONTEXT */ +/* Find the correct active object per context. + * NOTE: context can be NULL when called from a enum with #PROP_ENUM_NO_CONTEXT. */ Object *ED_object_active_context(const bContext *C) { Object *ob = NULL; @@ -157,7 +157,7 @@ Object *ED_object_active_context(const bContext *C) * (assuming they need to be modified). */ Object **ED_object_array_in_mode_or_selected(bContext *C, - bool (*filter_fn)(Object *ob, void *user_data), + bool (*filter_fn)(const Object *ob, void *user_data), void *filter_user_data, uint *r_objects_len) { @@ -557,7 +557,7 @@ static bool ED_object_editmode_load_free_ex(Main *bmain, } if (free_data) { - EDBM_mesh_free(me->edit_mesh); + EDBM_mesh_free_data(me->edit_mesh); MEM_freeN(me->edit_mesh); me->edit_mesh = NULL; } @@ -794,9 +794,7 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag BMEditMesh *em = BKE_editmesh_from_object(ob); if (LIKELY(em)) { - /* order doesn't matter */ - EDBM_mesh_normals_update(em); - BKE_editmesh_looptri_calc(em); + BKE_editmesh_looptri_and_normals_calc(em); } WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL); @@ -1154,7 +1152,7 @@ void ED_objects_recalculate_paths(bContext *C, Scene *scene, eObjectPathCalcRang Depsgraph *depsgraph; bool free_depsgraph = false; /* For a single frame update it's faster to re-use existing dependency graph and avoid overhead - * of building all the relations and so on for a temporary one. */ + * of building all the relations and so on for a temporary one. */ if (range == OBJECT_PATH_CALC_RANGE_CURRENT_FRAME) { /* NOTE: Dependency graph will be evaluated at all the frames, but we first need to access some * nested pointers, like animation data. */ @@ -1992,7 +1990,7 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent * Technically we could use #wmOperator.customdata. However there is no free callback * called to an operator that exit with OPERATOR_INTERFACE to launch a menu. * - * So we are left with a memory that will necessarily leak. It's a small leak though.*/ + * So we are left with a memory that will necessarily leak. It's a small leak though. */ if (master_collection_menu == NULL) { master_collection_menu = MEM_callocN(sizeof(MoveToCollectionData), "MoveToCollectionData menu - expected eventual memleak"); diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index d56ee17a73f..5065a2c00f0 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -105,14 +105,13 @@ static int return_editmesh_indexar(BMEditMesh *em, int *r_tot, int **r_indexar, static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3]) { - const int cd_dvert_offset = obedit->actdef ? + const int active_index = BKE_object_defgroup_active_index_get(obedit); + const int cd_dvert_offset = active_index ? CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT) : -1; - zero_v3(r_cent); - if (cd_dvert_offset != -1) { - const int defgrp_index = obedit->actdef - 1; + const int defgrp_index = active_index - 1; int totvert = 0; MDeformVert *dvert; @@ -129,7 +128,8 @@ static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, } } if (totvert) { - bDeformGroup *dg = BLI_findlink(&obedit->defbase, defgrp_index); + const ListBase *defbase = BKE_object_defgroup_list(obedit); + bDeformGroup *dg = BLI_findlink(defbase, defgrp_index); BLI_strncpy(r_name, dg->name, sizeof(dg->name)); mul_v3_fl(r_cent, 1.0f / (float)totvert); return true; @@ -350,8 +350,7 @@ static bool object_hook_index_array(Main *bmain, em = me->edit_mesh; - EDBM_mesh_normals_update(em); - BKE_editmesh_looptri_calc(em); + BKE_editmesh_looptri_and_normals_calc(em); /* check selected vertices first */ if (return_editmesh_indexar(em, r_tot, r_indexar, r_cent) == 0) { @@ -773,7 +772,7 @@ void OBJECT_OT_hook_remove(wmOperatorType *ot) /* flags */ /* this operator removes modifier which isn't stored in local undo stack, - * so redoing it from redo panel gives totally weird results */ + * so redoing it from redo panel gives totally weird results. */ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; /* properties */ @@ -932,7 +931,7 @@ void OBJECT_OT_hook_assign(wmOperatorType *ot) /* flags */ /* this operator changes data stored in modifier which doesn't get pushed to undo stack, - * so redoing it from redo panel gives totally weird results */ + * so redoing it from redo panel gives totally weird results. */ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; /* properties */ diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 5bf04e195fe..5a3a28b5a3f 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -247,7 +247,6 @@ void OBJECT_OT_vertex_group_assign_new(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_remove_from(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_select(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_deselect(struct wmOperatorType *ot); -void OBJECT_OT_vertex_group_copy_to_linked(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_copy_to_selected(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_normalize(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index dcb294bcb12..36a4f002978 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -30,6 +30,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "BLT_translation.h" #include "BKE_context.h" @@ -399,9 +401,9 @@ void ED_object_mode_generic_exit(struct Main *bmain, ed_object_mode_generic_exit_ex(bmain, depsgraph, scene, ob, false); } -bool ED_object_mode_generic_has_data(struct Depsgraph *depsgraph, struct Object *ob) +bool ED_object_mode_generic_has_data(struct Depsgraph *depsgraph, const struct Object *ob) { - return ed_object_mode_generic_exit_ex(NULL, depsgraph, NULL, ob, true); + return ed_object_mode_generic_exit_ex(NULL, depsgraph, NULL, (Object *)ob, true); } /** \} */ @@ -419,7 +421,7 @@ static bool object_transfer_mode_poll(bContext *C) return false; } const Object *ob = CTX_data_active_object(C); - return ob && (ob->mode & (OB_MODE_SCULPT)); + return ob && (ob->mode != OB_MODE_OBJECT); } /* Update the viewport rotation origin to the mouse cursor. */ @@ -438,6 +440,13 @@ static void object_transfer_mode_reposition_view_pivot(bContext *C, const int mv ups->last_stroke_valid = true; } +static void object_overlay_mode_transfer_animation_start(bContext *C, Object *ob_dst) +{ + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Object *ob_dst_eval = DEG_get_evaluated_object(depsgraph, ob_dst); + ob_dst_eval->runtime.overlay_mode_transfer_start_time = PIL_check_seconds_timer(); +} + static bool object_transfer_mode_to_base(bContext *C, wmOperator *op, Base *base_dst) { Scene *scene = CTX_data_scene(C); @@ -475,6 +484,10 @@ static bool object_transfer_mode_to_base(bContext *C, wmOperator *op, Base *base ob_dst_orig = DEG_get_original_object(ob_dst); ED_object_mode_set_ex(C, last_mode, true, op->reports); + if (RNA_boolean_get(op->ptr, "use_flash_on_transfer")) { + object_overlay_mode_transfer_animation_start(C, ob_dst); + } + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_toolsystem_update_from_context_view3d(C); mode_transfered = true; @@ -567,6 +580,12 @@ void OBJECT_OT_transfer_mode(wmOperatorType *ot) false, "Use Eyedropper", "Pick the object to switch to using an eyedropper"); + + RNA_def_boolean(ot->srna, + "use_flash_on_transfer", + true, + "Flash On Transfer", + "Flash the target object when transfering the mode"); } /** \} */ diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index e71b66b1a72..7bbca7ea9e6 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -63,6 +63,7 @@ #include "BKE_lattice.h" #include "BKE_lib_id.h" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_runtime.h" @@ -124,7 +125,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object * BKE_displist_make_mball(depsgraph, scene_eval, ob_eval); } else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false); + BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false); } else if (ob->type == OB_GPENCIL) { BKE_gpencil_modifiers_calc(depsgraph, scene_eval, ob_eval); @@ -772,6 +773,8 @@ static bool modifier_apply_obdata( return false; } + Main *bmain = DEG_get_bmain(depsgraph); + BKE_object_material_from_eval_data(bmain, ob, &mesh_applied->id); BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, &CD_MASK_MESH, true); if (md_eval->type == eModifierType_Multires) { @@ -2144,7 +2147,7 @@ static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - /* XXX don't remove.. */ + /* XXX don't remove. */ CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop); return OPERATOR_FINISHED; @@ -2595,7 +2598,7 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, BLI_bitmap *edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited"); - /* note: we use EditBones here, easier to set them up and use + /* NOTE: we use EditBones here, easier to set them up and use * edit-armature functions to convert back to regular bones */ for (int v = 0; v < me->totvert; v++) { if (mvert_skin[v].flag & MVERT_SKIN_ROOT) { diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index b50fc3c88fd..a438c760d3b 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -201,7 +201,6 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_vertex_group_remove_from); WM_operatortype_append(OBJECT_OT_vertex_group_select); WM_operatortype_append(OBJECT_OT_vertex_group_deselect); - WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked); WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected); WM_operatortype_append(OBJECT_OT_vertex_group_copy); WM_operatortype_append(OBJECT_OT_vertex_group_normalize); @@ -322,7 +321,7 @@ void ED_keymap_object(wmKeyConfig *keyconf) keymap = WM_keymap_ensure(keyconf, "Object Non-modal", 0, 0); /* Object Mode ---------------------------------------------------------------- */ - /* Note: this keymap gets disabled in non-objectmode, */ + /* NOTE: this keymap gets disabled in non-objectmode. */ keymap = WM_keymap_ensure(keyconf, "Object Mode", 0, 0); keymap->poll = object_mode_poll; } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index b685a93f27b..c61965b3e23 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -153,8 +153,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) em = me->edit_mesh; - EDBM_mesh_normals_update(em); - BKE_editmesh_looptri_calc(em); + BKE_editmesh_looptri_and_normals_calc(em); /* Make sure the evaluated mesh is updated. * @@ -594,7 +593,7 @@ void ED_object_parent_clear(Object *ob, const int type) DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); } -/* note, poll should check for editable scene */ +/* NOTE: poll should check for editable scene. */ static int parent_clear_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -716,7 +715,7 @@ bool ED_object_parent_set(ReportList *reports, cu->flag |= CU_PATH | CU_FOLLOW; cu_eval->flag |= CU_PATH | CU_FOLLOW; /* force creation of path data */ - BKE_displist_make_curveTypes(depsgraph, scene, par, false, false); + BKE_displist_make_curveTypes(depsgraph, scene, par, false); } else { cu->flag |= CU_FOLLOW; @@ -792,8 +791,8 @@ bool ED_object_parent_set(ReportList *reports, * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, * creating the virtual modifiers. */ - ob->partype = PAROBJECT; /* Note: DNA define, not operator property. */ - /* ob->partype = PARSKEL; */ /* Note: DNA define, not operator property. */ + ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */ + /* ob->partype = PARSKEL; */ /* NOTE: DNA define, not operator property. */ /* BUT, to keep the deforms, we need a modifier, * and then we need to set the object that it uses @@ -838,14 +837,14 @@ bool ED_object_parent_set(ReportList *reports, } break; case PAR_BONE: - ob->partype = PARBONE; /* Note: DNA define, not operator property. */ + ob->partype = PARBONE; /* NOTE: DNA define, not operator property. */ if (pchan->bone) { pchan->bone->flag &= ~BONE_RELATIVE_PARENTING; pchan_eval->bone->flag &= ~BONE_RELATIVE_PARENTING; } break; case PAR_BONE_RELATIVE: - ob->partype = PARBONE; /* Note: DNA define, not operator property. */ + ob->partype = PARBONE; /* NOTE: DNA define, not operator property. */ if (pchan->bone) { pchan->bone->flag |= BONE_RELATIVE_PARENTING; pchan_eval->bone->flag |= BONE_RELATIVE_PARENTING; @@ -861,7 +860,7 @@ bool ED_object_parent_set(ReportList *reports, break; case PAR_OBJECT: case PAR_FOLLOW: - ob->partype = PAROBJECT; /* Note: DNA define, not operator property. */ + ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */ break; } @@ -1249,7 +1248,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op) /* set parenting type for object - object only... */ ob->parent = par; - ob->partype = PAROBJECT; /* note, dna define, not operator property */ + ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */ } } } @@ -1299,7 +1298,7 @@ static const EnumPropertyItem prop_clear_track_types[] = { {0, NULL, 0, NULL, NULL}, }; -/* note, poll should check for editable scene */ +/* NOTE: poll should check for editable scene. */ static int object_track_clear_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -1932,7 +1931,7 @@ static void single_object_users( } /* not an especially efficient function, only added so the single user - * button can be functional.*/ + * button can be functional. */ void ED_object_single_user(Main *bmain, Scene *scene, Object *ob) { FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) { @@ -1944,7 +1943,7 @@ void ED_object_single_user(Main *bmain, Scene *scene, Object *ob) ob->flag |= OB_DONE; single_object_users(bmain, scene, NULL, OB_DONE, false); - BKE_main_id_clear_newpoins(bmain); + BKE_main_id_newptr_and_tag_clear(bmain); } static void single_obdata_users( @@ -2023,7 +2022,7 @@ static void single_obdata_users( break; default: printf("ERROR %s: can't copy %s\n", __func__, id->name); - BLI_assert(!"This should never happen."); + BLI_assert_msg(0, "This should never happen."); /* We need to end the FOREACH_OBJECT_FLAG_BEGIN iterator to prevent memory leak. */ BKE_scene_objects_iterator_end(&iter_macro); @@ -2062,6 +2061,23 @@ static void single_object_action_users( FOREACH_OBJECT_FLAG_END; } +static void single_objectdata_action_users( + Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag) +{ + FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) { + if (!ID_IS_LINKED(ob) && ob->data != NULL) { + ID *id_obdata = (ID *)ob->data; + AnimData *adt = BKE_animdata_from_id(id_obdata); + ID *id_act = (ID *)adt->action; + if (id_act && id_act->us > 1) { + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + BKE_animdata_copy_id_action(bmain, id_obdata); + } + } + } + FOREACH_OBJECT_FLAG_END; +} + static void single_mat_users( Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag) { @@ -2237,7 +2253,7 @@ static int make_local_exec(bContext *C, wmOperator *op) const int mode = RNA_enum_get(op->ptr, "type"); int a; - /* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */ + /* NOTE: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */ if (mode == MAKE_LOCAL_ALL) { ViewLayer *view_layer = CTX_data_view_layer(C); Collection *collection = CTX_data_collection(C); @@ -2454,7 +2470,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op) BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); const bool success = BKE_lib_override_library_create( - bmain, scene, view_layer, id_root, &obact->id); + bmain, scene, view_layer, id_root, &obact->id, NULL); /* Remove the instance empty from this scene, the items now have an overridden collection * instead. */ @@ -2570,14 +2586,14 @@ static int convert_proxy_to_override_exec(bContext *C, wmOperator *op) /* Remove the instance empty from this scene, the items now have an overridden collection * instead. */ - if (success && is_override_instancing_object) { + if (is_override_instancing_object) { ED_object_base_free_and_unlink(bmain, scene, ob_proxy_group); } DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_WINDOW, NULL); - return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + return OPERATOR_FINISHED; } void OBJECT_OT_convert_proxy_to_override(wmOperatorType *ot) @@ -2644,7 +2660,11 @@ static int make_single_user_exec(bContext *C, wmOperator *op) single_object_action_users(bmain, scene, view_layer, v3d, flag); } - BKE_main_id_clear_newpoins(bmain); + if (RNA_boolean_get(op->ptr, "obdata_animation")) { + single_objectdata_action_users(bmain, scene, view_layer, v3d, flag); + } + + BKE_main_id_newptr_and_tag_clear(bmain); WM_event_add_notifier(C, NC_WINDOW, NULL); @@ -2685,8 +2705,16 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot) RNA_def_boolean(ot->srna, "object", 0, "Object", "Make single user objects"); RNA_def_boolean(ot->srna, "obdata", 0, "Object Data", "Make single user object data"); RNA_def_boolean(ot->srna, "material", 0, "Materials", "Make materials local to each data-block"); - RNA_def_boolean( - ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object"); + RNA_def_boolean(ot->srna, + "animation", + 0, + "Object Animation", + "Make object animation data local to each object"); + RNA_def_boolean(ot->srna, + "obdata_animation", + 0, + "Object Data Animation", + "Make object data (mesh, curve etc.) animation data local to each object"); } /** \} */ diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c index 9ef2cce875f..05f9980e0ab 100644 --- a/source/blender/editors/object/object_remesh.c +++ b/source/blender/editors/object/object_remesh.c @@ -139,6 +139,13 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + if (mesh->totpoly == 0) { + return OPERATOR_CANCELLED; + } + + /* Output mesh will be all smooth or all flat shading. */ + const bool smooth_normals = mesh->mpoly[0].flag & ME_SMOOTH; + float isovalue = 0.0f; if (mesh->flag & ME_REMESH_REPROJECT_VOLUME) { isovalue = mesh->remesh_voxel_size * 0.3f; @@ -185,7 +192,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true); - if (mesh->flag & ME_REMESH_SMOOTH_NORMALS) { + if (smooth_normals) { BKE_mesh_smooth_flag_set(ob->data, true); } @@ -525,7 +532,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev float d_a[3], d_b[3]; float d_a_proj[2], d_b_proj[2]; - float preview_plane_proj[4][3]; + float preview_plane_proj[4][2]; const float y_axis_proj[2] = {0.0f, 1.0f}; mid_v3_v3v3(text_pos, cd->preview_plane[0], cd->preview_plane[2]); @@ -534,7 +541,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev for (int i = 0; i < 4; i++) { float preview_plane_world_space[3]; mul_v3_m4v3(preview_plane_world_space, active_object->obmat, cd->preview_plane[i]); - ED_view3d_project(region, preview_plane_world_space, preview_plane_proj[i]); + ED_view3d_project_v2(region, preview_plane_world_space, preview_plane_proj[i]); } /* Get the initial X and Y axis of the basis from the edges of the Bounding Box face. */ @@ -581,7 +588,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev /* Write the text position into the matrix. */ copy_v3_v3(cd->text_mat[3], text_pos); - /* Scale the text. */ + /* Scale the text. */ float text_pos_word_space[3]; mul_v3_m4v3(text_pos_word_space, active_object->obmat, text_pos); const float pixelsize = ED_view3d_pixel_size(rv3d, text_pos_word_space); diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index 9160190764c..eb37aebcff2 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -26,6 +26,8 @@ #include <stdlib.h> #include <string.h> +#include "MEM_guardedalloc.h" + #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_collection_types.h" @@ -293,7 +295,7 @@ bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_ return false; } - /* TODO, use 'reveal_hidden', as is done with bones. */ + /* TODO: use 'reveal_hidden', as is done with bones. */ if (view_layer->basact != base || !(base->flag & BASE_SELECTED)) { /* Select if not selected. */ @@ -579,7 +581,7 @@ static bool object_select_all_by_particle(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) { - /* loop through other particles*/ + /* Loop through other particles. */ ParticleSystem *psys; for (psys = base->object->particlesystem.first; psys; psys = psys->next) { @@ -1454,20 +1456,28 @@ void OBJECT_OT_select_less(wmOperatorType *ot) static int object_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, "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 = BLI_rng_new_srandom(seed); + ListBase ctx_data_list; + CTX_data_selectable_bases(C, &ctx_data_list); + const int tot = BLI_listbase_count(&ctx_data_list); + int elem_map_len = 0; + Base **elem_map = MEM_mallocN(sizeof(*elem_map) * tot, __func__); - CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if (BLI_rng_get_float(rng) < randfac) { - ED_object_base_select(base, select); - } + CollectionPointerLink *ctx_link; + for (ctx_link = ctx_data_list.first; ctx_link; ctx_link = ctx_link->next) { + elem_map[elem_map_len++] = ctx_link->ptr.data; } - CTX_DATA_END; + BLI_freelistN(&ctx_data_list); - BLI_rng_free(rng); + BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed); + const int count_select = elem_map_len * randfac; + for (int i = 0; i < count_select; i++) { + ED_object_base_select(elem_map[i], select); + } + MEM_freeN(elem_map); Scene *scene = CTX_data_scene(C); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); @@ -1486,7 +1496,7 @@ void OBJECT_OT_select_random(wmOperatorType *ot) ot->idname = "OBJECT_OT_select_random"; /* api callbacks */ - /*ot->invoke = object_select_random_invoke XXX - need a number popup ;*/ + /*ot->invoke = object_select_random_invoke XXX: need a number popup ;*/ ot->exec = object_select_random_exec; ot->poll = objects_selectable_poll; diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c index 585a1e22a84..2723d7ad1e3 100644 --- a/source/blender/editors/object/object_shader_fx.c +++ b/source/blender/editors/object/object_shader_fx.c @@ -64,7 +64,9 @@ #include "object_intern.h" -/******************************** API ****************************/ +/* -------------------------------------------------------------------- */ +/** \name Public API + * \{ */ ShaderFxData *ED_object_shaderfx_add( ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type) @@ -261,7 +263,59 @@ void ED_object_shaderfx_copy(Object *dst, ShaderFxData *fx) WM_main_add_notifier(NC_OBJECT | ND_SHADERFX, dst); } -/************************ add effect operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Generic Poll Callback Helpers + * \{ */ + +static bool edit_shaderfx_poll_generic(bContext *C, + StructRNA *rna_type, + int obtype_flag, + const bool is_liboverride_allowed) +{ + PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", rna_type); + Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); + ShaderFxData *fx = ptr.data; /* May be NULL. */ + + if (!ED_operator_object_active_editable_ex(C, ob)) { + return false; + } + + /* NOTE: Temporary 'forbid all' for overrides, until we implement support to add shaderfx to + * overrides. */ + if (ID_IS_OVERRIDE_LIBRARY(ob)) { + CTX_wm_operator_poll_msg_set(C, "Cannot edit shaderfxs in a library override"); + return false; + } + + if (obtype_flag != 0 && ((1 << ob->type) & obtype_flag) == 0) { + CTX_wm_operator_poll_msg_set(C, "Object type is not supported"); + return false; + } + if (ptr.owner_id != NULL && ID_IS_LINKED(ptr.owner_id)) { + CTX_wm_operator_poll_msg_set(C, "Cannot edit library data"); + return false; + } + if (!is_liboverride_allowed && BKE_shaderfx_is_nonlocal_in_liboverride(ob, fx)) { + CTX_wm_operator_poll_msg_set( + C, "Cannot edit shaderfxs coming from linked data in a library override"); + return false; + } + + return true; +} + +static bool edit_shaderfx_poll(bContext *C) +{ + return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0, false); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Effect Operator + * \{ */ static int shaderfx_add_exec(bContext *C, wmOperator *op) { @@ -334,7 +388,7 @@ void OBJECT_OT_shaderfx_add(wmOperatorType *ot) /* api callbacks */ ot->invoke = WM_menu_invoke; ot->exec = shaderfx_add_exec; - ot->poll = ED_operator_object_active_editable; + ot->poll = edit_shaderfx_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -352,37 +406,6 @@ void OBJECT_OT_shaderfx_add(wmOperatorType *ot) /** \name Generic Functions for Operators Using Names and Data Context * \{ */ -static bool edit_shaderfx_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag) -{ - PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", rna_type); - Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); - ShaderFxData *fx = ptr.data; /* May be NULL. */ - - if (!ob || ID_IS_LINKED(ob)) { - return false; - } - if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) { - return false; - } - if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) { - return false; - } - - if (ID_IS_OVERRIDE_LIBRARY(ob)) { - if ((fx == NULL) || (fx->flag & eShaderFxFlag_OverrideLibrary_Local) == 0) { - CTX_wm_operator_poll_msg_set(C, "Cannot edit shaderfxs coming from library override"); - return false; - } - } - - return true; -} - -static bool edit_shaderfx_poll(bContext *C) -{ - return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0); -} - static void edit_shaderfx_properties(wmOperatorType *ot) { PropertyRNA *prop = RNA_def_string( @@ -461,7 +484,9 @@ static ShaderFxData *edit_shaderfx_property_get(wmOperator *op, Object *ob, int /** \} */ -/************************ remove shaderfx operator *********************/ +/* -------------------------------------------------------------------- */ +/** \name Remove ShaderFX Operator + * \{ */ static int shaderfx_remove_exec(bContext *C, wmOperator *op) { @@ -511,7 +536,11 @@ void OBJECT_OT_shaderfx_remove(wmOperatorType *ot) edit_shaderfx_report_property(ot); } -/************************ move up shaderfx operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Move up ShaderFX Operator + * \{ */ static int shaderfx_move_up_exec(bContext *C, wmOperator *op) { @@ -552,7 +581,11 @@ void OBJECT_OT_shaderfx_move_up(wmOperatorType *ot) edit_shaderfx_properties(ot); } -/************************ move down shaderfx operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Move Down ShaderFX Operator + * \{ */ static int shaderfx_move_down_exec(bContext *C, wmOperator *op) { @@ -593,12 +626,11 @@ void OBJECT_OT_shaderfx_move_down(wmOperatorType *ot) edit_shaderfx_properties(ot); } -/************************ move shaderfx to index operator *********************/ +/** \} */ -static bool shaderfx_move_to_index_poll(bContext *C) -{ - return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0); -} +/* -------------------------------------------------------------------- */ +/** \name Move ShaderFX to Index Operator + * \{ */ static int shaderfx_move_to_index_exec(bContext *C, wmOperator *op) { @@ -632,7 +664,7 @@ void OBJECT_OT_shaderfx_move_to_index(wmOperatorType *ot) ot->invoke = shaderfx_move_to_index_invoke; ot->exec = shaderfx_move_to_index_exec; - ot->poll = shaderfx_move_to_index_poll; + ot->poll = edit_shaderfx_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; @@ -641,7 +673,11 @@ void OBJECT_OT_shaderfx_move_to_index(wmOperatorType *ot) ot->srna, "index", 0, 0, INT_MAX, "Index", "The index to move the effect to", 0, INT_MAX); } -/************************ copy shader operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy Shader Operator + * \{ */ static int shaderfx_copy_exec(bContext *C, wmOperator *op) { @@ -675,11 +711,6 @@ static int shaderfx_copy_invoke(bContext *C, wmOperator *op, const wmEvent *even return retval; } -static bool shaderfx_copy_poll(bContext *C) -{ - return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0); -} - void OBJECT_OT_shaderfx_copy(wmOperatorType *ot) { ot->name = "Copy Effect"; @@ -688,9 +719,11 @@ void OBJECT_OT_shaderfx_copy(wmOperatorType *ot) ot->invoke = shaderfx_copy_invoke; ot->exec = shaderfx_copy_exec; - ot->poll = shaderfx_copy_poll; + ot->poll = edit_shaderfx_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; edit_shaderfx_properties(ot); } + +/** \} */ diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index a87b5054efa..4c4727f51ee 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -709,7 +709,7 @@ static int apply_objects_internal(bContext *C, if (has_unparented_layers == false) { BKE_reportf(reports, RPT_ERROR, - "Can't apply to a GP datablock where all layers are parented: Object " + "Can't apply to a GP data-block where all layers are parented: Object " "\"%s\", %s \"%s\", aborting", ob->id.name + 2, BKE_idtype_idcode_to_name(ID_GD), @@ -722,7 +722,7 @@ static int apply_objects_internal(bContext *C, BKE_reportf( reports, RPT_ERROR, - "Can't apply to GP datablock with no layers: Object \"%s\", %s \"%s\", aborting", + "Can't apply to GP data-block with no layers: Object \"%s\", %s \"%s\", aborting", ob->id.name + 2, BKE_idtype_idcode_to_name(ID_GD), gpd->id.name + 2); @@ -1152,51 +1152,53 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) for (int object_index = 0; object_index < num_objects; object_index++) { Object *ob = objects[object_index]; + if (ob->flag & OB_DONE) { + continue; + } - if ((ob->flag & OB_DONE) == 0) { - bool do_inverse_offset = false; - ob->flag |= OB_DONE; + bool do_inverse_offset = false; + ob->flag |= OB_DONE; - if (centermode == ORIGIN_TO_CURSOR) { - copy_v3_v3(cent, cursor); - invert_m4_m4(ob->imat, ob->obmat); - mul_m4_v3(ob->imat, cent); - } + if (centermode == ORIGIN_TO_CURSOR) { + copy_v3_v3(cent, cursor); + invert_m4_m4(ob->imat, ob->obmat); + mul_m4_v3(ob->imat, cent); + } - if (ob->data == NULL) { - /* special support for dupligroups */ - if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection && - (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) { - if (ID_IS_LINKED(ob->instance_collection)) { - tot_lib_error++; + if (ob->data == NULL) { + /* special support for dupligroups */ + if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection && + (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) { + if (ID_IS_LINKED(ob->instance_collection)) { + tot_lib_error++; + } + else { + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ } else { - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else { - float min[3], max[3]; - /* only bounds support */ - INIT_MINMAX(min, max); - BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true); - mid_v3_v3v3(cent, min, max); - invert_m4_m4(ob->imat, ob->obmat); - mul_m4_v3(ob->imat, cent); - } + float min[3], max[3]; + /* only bounds support */ + INIT_MINMAX(min, max); + BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true); + mid_v3_v3v3(cent, min, max); + invert_m4_m4(ob->imat, ob->obmat); + mul_m4_v3(ob->imat, cent); + } - add_v3_v3(ob->instance_collection->instance_offset, cent); + add_v3_v3(ob->instance_collection->instance_offset, cent); - tot_change++; - ob->instance_collection->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; - } + tot_change++; + ob->instance_collection->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; } } - else if (ID_IS_LINKED(ob->data)) { - tot_lib_error++; - } - - if (obedit == NULL && ob->type == OB_MESH) { + } + else if (ID_IS_LINKED(ob->data)) { + tot_lib_error++; + } + else if (ob->type == OB_MESH) { + if (obedit == NULL) { Mesh *me = ob->data; if (centermode == ORIGIN_TO_CURSOR) { @@ -1222,265 +1224,265 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) me->id.tag |= LIB_TAG_DOIT; do_inverse_offset = true; } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { - Curve *cu = ob->data; + } + else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + Curve *cu = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else if (around == V3D_AROUND_CENTER_BOUNDS) { - BKE_curve_center_bounds(cu, cent); - } - else { /* #V3D_AROUND_CENTER_MEDIAN. */ - BKE_curve_center_median(cu, cent); - } + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ + } + else if (around == V3D_AROUND_CENTER_BOUNDS) { + BKE_curve_center_bounds(cu, cent); + } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_curve_center_median(cu, cent); + } - /* don't allow Z change if curve is 2D */ - if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) { - cent[2] = 0.0; - } + /* don't allow Z change if curve is 2D */ + if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) { + cent[2] = 0.0; + } - negate_v3_v3(cent_neg, cent); - BKE_curve_translate(cu, cent_neg, 1); + negate_v3_v3(cent_neg, cent); + BKE_curve_translate(cu, cent_neg, 1); - tot_change++; - cu->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; + tot_change++; + cu->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; - if (obedit) { - if (centermode == GEOMETRY_TO_ORIGIN) { - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); - } - break; + if (obedit) { + if (centermode == GEOMETRY_TO_ORIGIN) { + DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } + break; } - else if (ob->type == OB_FONT) { - /* get from bb */ + } + else if (ob->type == OB_FONT) { + /* Get from bounding-box. */ - Curve *cu = ob->data; + Curve *cu = ob->data; - if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) { - /* do nothing*/ + if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) { + /* Do nothing. */ + } + else { + if (centermode == ORIGIN_TO_CURSOR) { + /* Done. */ } else { - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else { - /* extra 0.5 is the height o above line */ - cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]); - cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]); - } + /* extra 0.5 is the height o above line */ + cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]); + cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]); + } - cent[2] = 0.0f; + cent[2] = 0.0f; - cu->xof = cu->xof - cent[0]; - cu->yof = cu->yof - cent[1]; + cu->xof = cu->xof - cent[0]; + cu->yof = cu->yof - cent[1]; - tot_change++; - cu->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; - } + tot_change++; + cu->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; } - else if (ob->type == OB_ARMATURE) { - bArmature *arm = ob->data; + } + else if (ob->type == OB_ARMATURE) { + bArmature *arm = ob->data; - if (ID_REAL_USERS(arm) > 1) { + if (ID_REAL_USERS(arm) > 1) { #if 0 BKE_report(op->reports, RPT_ERROR, "Cannot apply to a multi user armature"); return; #endif - tot_multiuser_arm_error++; - } - else { - /* Function to recenter armatures in editarmature.c - * Bone + object locations are handled there. - */ - ED_armature_origin_set(bmain, ob, cursor, centermode, around); + tot_multiuser_arm_error++; + } + else { + /* Function to recenter armatures in editarmature.c + * Bone + object locations are handled there. + */ + ED_armature_origin_set(bmain, ob, cursor, centermode, around); - tot_change++; - arm->id.tag |= LIB_TAG_DOIT; - /* do_inverse_offset = true; */ /* docenter_armature() handles this */ + tot_change++; + arm->id.tag |= LIB_TAG_DOIT; + /* do_inverse_offset = true; */ /* docenter_armature() handles this */ - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - BKE_object_transform_copy(ob_eval, ob); - BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); - BKE_object_where_is_calc(depsgraph, scene, ob_eval); - BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */ + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + BKE_object_transform_copy(ob_eval, ob); + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); + BKE_object_where_is_calc(depsgraph, scene, ob_eval); + BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */ - ignore_parent_tx(bmain, depsgraph, scene, ob); + ignore_parent_tx(bmain, depsgraph, scene, ob); - if (obedit) { - break; - } + if (obedit) { + break; } } - else if (ob->type == OB_MBALL) { - MetaBall *mb = ob->data; + } + else if (ob->type == OB_MBALL) { + MetaBall *mb = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else if (around == V3D_AROUND_CENTER_BOUNDS) { - BKE_mball_center_bounds(mb, cent); - } - else { /* #V3D_AROUND_CENTER_MEDIAN. */ - BKE_mball_center_median(mb, cent); - } + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ + } + else if (around == V3D_AROUND_CENTER_BOUNDS) { + BKE_mball_center_bounds(mb, cent); + } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_mball_center_median(mb, cent); + } - negate_v3_v3(cent_neg, cent); - BKE_mball_translate(mb, cent_neg); + negate_v3_v3(cent_neg, cent); + BKE_mball_translate(mb, cent_neg); - tot_change++; - mb->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; + tot_change++; + mb->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; - if (obedit) { - if (centermode == GEOMETRY_TO_ORIGIN) { - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); - } - break; + if (obedit) { + if (centermode == GEOMETRY_TO_ORIGIN) { + DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } + break; } - else if (ob->type == OB_LATTICE) { - Lattice *lt = ob->data; + } + else if (ob->type == OB_LATTICE) { + Lattice *lt = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else if (around == V3D_AROUND_CENTER_BOUNDS) { - BKE_lattice_center_bounds(lt, cent); - } - else { /* #V3D_AROUND_CENTER_MEDIAN. */ - BKE_lattice_center_median(lt, cent); - } + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ + } + else if (around == V3D_AROUND_CENTER_BOUNDS) { + BKE_lattice_center_bounds(lt, cent); + } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_lattice_center_median(lt, cent); + } - negate_v3_v3(cent_neg, cent); - BKE_lattice_translate(lt, cent_neg, 1); + negate_v3_v3(cent_neg, cent); + BKE_lattice_translate(lt, cent_neg, 1); - tot_change++; - lt->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; - } - else if (ob->type == OB_GPENCIL) { - bGPdata *gpd = ob->data; - float gpcenter[3]; - if (gpd) { - if (centermode == ORIGIN_TO_GEOMETRY) { - zero_v3(gpcenter); - BKE_gpencil_centroid_3d(gpd, gpcenter); - add_v3_v3(gpcenter, ob->obmat[3]); - } - if (centermode == ORIGIN_TO_CURSOR) { - copy_v3_v3(gpcenter, cursor); - } - if (ELEM(centermode, ORIGIN_TO_GEOMETRY, ORIGIN_TO_CURSOR)) { - bGPDspoint *pt; - float imat[3][3], bmat[3][3]; - float offset_global[3]; - float offset_local[3]; - int i; - - sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]); - copy_m3_m4(bmat, obact->obmat); - invert_m3_m3(imat, bmat); - mul_m3_v3(imat, offset_global); - mul_v3_m3v3(offset_local, imat, offset_global); - - float diff_mat[4][4]; - float inverse_diff_mat[4][4]; - - /* recalculate all strokes - * (all layers are considered without evaluating lock attributes) */ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* calculate difference matrix */ - BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); - /* undo matrix */ - invert_m4_m4(inverse_diff_mat, diff_mat); - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - float mpt[3]; - mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x); - sub_v3_v3(mpt, offset_local); - mul_v3_m4v3(&pt->x, diff_mat, mpt); - } + tot_change++; + lt->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; + } + else if (ob->type == OB_GPENCIL) { + bGPdata *gpd = ob->data; + float gpcenter[3]; + if (gpd) { + if (centermode == ORIGIN_TO_GEOMETRY) { + zero_v3(gpcenter); + BKE_gpencil_centroid_3d(gpd, gpcenter); + add_v3_v3(gpcenter, ob->obmat[3]); + } + if (centermode == ORIGIN_TO_CURSOR) { + copy_v3_v3(gpcenter, cursor); + } + if (ELEM(centermode, ORIGIN_TO_GEOMETRY, ORIGIN_TO_CURSOR)) { + bGPDspoint *pt; + float imat[3][3], bmat[3][3]; + float offset_global[3]; + float offset_local[3]; + int i; + + sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]); + copy_m3_m4(bmat, obact->obmat); + invert_m3_m3(imat, bmat); + mul_m3_v3(imat, offset_global); + mul_v3_m3v3(offset_local, imat, offset_global); + + float diff_mat[4][4]; + float inverse_diff_mat[4][4]; + + /* recalculate all strokes + * (all layers are considered without evaluating lock attributes) */ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* calculate difference matrix */ + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + /* undo matrix */ + invert_m4_m4(inverse_diff_mat, diff_mat); + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + float mpt[3]; + mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x); + sub_v3_v3(mpt, offset_local); + mul_v3_m4v3(&pt->x, diff_mat, mpt); } } } - tot_change++; - if (centermode == ORIGIN_TO_GEOMETRY) { - copy_v3_v3(ob->loc, gpcenter); - } - DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); - - ob->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; } - else { - BKE_report(op->reports, - RPT_WARNING, - "Grease Pencil Object does not support this set origin option"); + tot_change++; + if (centermode == ORIGIN_TO_GEOMETRY) { + copy_v3_v3(ob->loc, gpcenter); } + DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); + + ob->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; + } + else { + BKE_report(op->reports, + RPT_WARNING, + "Grease Pencil Object does not support this set origin option"); } } + } - /* offset other selected objects */ - if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) { - float obmat[4][4]; + /* offset other selected objects */ + if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) { + float obmat[4][4]; - /* was the object data modified - * note: the functions above must set 'cent' */ + /* was the object data modified + * NOTE: the functions above must set 'cent'. */ - /* convert the offset to parent space */ - BKE_object_to_mat4(ob, obmat); - mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */ + /* convert the offset to parent space */ + BKE_object_to_mat4(ob, obmat); + mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */ - add_v3_v3(ob->loc, centn); + add_v3_v3(ob->loc, centn); - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - BKE_object_transform_copy(ob_eval, ob); - BKE_object_where_is_calc(depsgraph, scene, ob_eval); - if (ob->type == OB_ARMATURE) { - /* needed for bone parents */ - BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); - BKE_pose_where_is(depsgraph, scene, ob_eval); - } - - ignore_parent_tx(bmain, depsgraph, scene, ob); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + BKE_object_transform_copy(ob_eval, ob); + BKE_object_where_is_calc(depsgraph, scene, ob_eval); + if (ob->type == OB_ARMATURE) { + /* needed for bone parents */ + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); + BKE_pose_where_is(depsgraph, scene, ob_eval); + } - /* other users? */ - // CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects) - //{ - - /* use existing context looper */ - for (int other_object_index = 0; other_object_index < num_objects; other_object_index++) { - Object *ob_other = objects[other_object_index]; - - if ((ob_other->flag & OB_DONE) == 0 && - ((ob->data && (ob->data == ob_other->data)) || - (ob->instance_collection == ob_other->instance_collection && - (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION))) { - ob_other->flag |= OB_DONE; - DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - - mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */ - add_v3_v3(ob_other->loc, centn); - - Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other); - BKE_object_transform_copy(ob_other_eval, ob_other); - BKE_object_where_is_calc(depsgraph, scene, ob_other_eval); - if (ob_other->type == OB_ARMATURE) { - /* needed for bone parents */ - BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); - BKE_pose_where_is(depsgraph, scene, ob_other_eval); - } - ignore_parent_tx(bmain, depsgraph, scene, ob_other); + ignore_parent_tx(bmain, depsgraph, scene, ob); + + /* other users? */ + // CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects) + //{ + + /* use existing context looper */ + for (int other_object_index = 0; other_object_index < num_objects; other_object_index++) { + Object *ob_other = objects[other_object_index]; + + if ((ob_other->flag & OB_DONE) == 0 && + ((ob->data && (ob->data == ob_other->data)) || + (ob->instance_collection == ob_other->instance_collection && + (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION))) { + ob_other->flag |= OB_DONE; + DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + + mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */ + add_v3_v3(ob_other->loc, centn); + + Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other); + BKE_object_transform_copy(ob_other_eval, ob_other); + BKE_object_where_is_calc(depsgraph, scene, ob_other_eval); + if (ob_other->type == OB_ARMATURE) { + /* needed for bone parents */ + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); + BKE_pose_where_is(depsgraph, scene, ob_other_eval); } + ignore_parent_tx(bmain, depsgraph, scene, ob_other); } - // CTX_DATA_END; } + // CTX_DATA_END; } } MEM_freeN(objects); @@ -1490,7 +1492,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) BKE_object_batch_cache_dirty_tag(tob); DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); } - /* special support for dupligroups */ + /* Special support for dupli-groups. */ else if (tob->instance_collection && tob->instance_collection->id.tag & LIB_TAG_DOIT) { DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM); DEG_id_tag_update(&tob->instance_collection->id, ID_RECALC_COPY_ON_WRITE); @@ -1615,6 +1617,7 @@ struct XFormAxisItem { struct XFormAxisData { ViewContext vc; + ViewDepths *depths; struct { float depth; float normal[3]; @@ -1654,7 +1657,7 @@ static void object_transform_axis_target_calc_depth_init(struct XFormAxisData *x if (center_tot) { mul_v3_fl(center, 1.0f / center_tot); float center_proj[3]; - ED_view3d_project(xfd->vc.region, center, center_proj); + ED_view3d_project_v3(xfd->vc.region, center, center_proj); xfd->prev.depth = center_proj[2]; xfd->prev.is_depth_valid = true; } @@ -1684,8 +1687,8 @@ static void object_transform_axis_target_free_data(wmOperator *op) struct XFormAxisItem *item = xfd->object_data; #ifdef USE_RENDER_OVERRIDE - if (xfd->vc.rv3d->depths) { - xfd->vc.rv3d->depths->damaged = true; + if (xfd->depths) { + ED_view3d_depths_free(xfd->depths); } #endif @@ -1782,13 +1785,14 @@ static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, cons vc.v3d->flag2 |= V3D_HIDE_OVERLAYS; #endif - ED_view3d_depth_override(vc.depsgraph, vc.region, vc.v3d, NULL, V3D_DEPTH_NO_GPENCIL, true); + ViewDepths *depths = NULL; + ED_view3d_depth_override(vc.depsgraph, vc.region, vc.v3d, NULL, V3D_DEPTH_NO_GPENCIL, &depths); #ifdef USE_RENDER_OVERRIDE vc.v3d->flag2 = flag2_prev; #endif - if (vc.rv3d->depths == NULL) { + if (depths == NULL) { BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane"); return OPERATOR_CANCELLED; } @@ -1800,6 +1804,7 @@ static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, cons /* Don't change this at runtime. */ xfd->vc = vc; + xfd->depths = depths; xfd->vc.mval[0] = event->mval[0]; xfd->vc.mval[1] = event->mval[1]; @@ -1863,7 +1868,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const const bool is_translate_init = is_translate && (xfd->is_translate != is_translate); if (event->type == MOUSEMOVE || is_translate_init) { - const ViewDepths *depths = xfd->vc.rv3d->depths; + const ViewDepths *depths = xfd->depths; if (depths && ((uint)event->mval[0] < depths->w) && ((uint)event->mval[1] < depths->h)) { float depth_fl = 1.0f; ED_view3d_depth_read_cached(depths, event->mval, 0, &depth_fl); @@ -1890,12 +1895,12 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { xfd->prev.depth = depth_fl; xfd->prev.is_depth_valid = true; - if (ED_view3d_depth_unproject(region, event->mval, depth, location_world)) { + if (ED_view3d_depth_unproject_v3(region, event->mval, depth, location_world)) { if (is_translate) { float normal[3]; bool normal_found = false; - if (ED_view3d_depth_read_cached_normal(&xfd->vc, event->mval, normal)) { + if (ED_view3d_depth_read_cached_normal(region, depths, event->mval, normal)) { normal_found = true; /* cheap attempt to smooth normals out a bit! */ @@ -1905,7 +1910,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const if (x != 0 && y != 0) { const int mval_ofs[2] = {event->mval[0] + x, event->mval[1] + y}; float n[3]; - if (ED_view3d_depth_read_cached_normal(&xfd->vc, mval_ofs, n)) { + if (ED_view3d_depth_read_cached_normal(region, depths, mval_ofs, n)) { add_v3_v3(normal, n); } } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 5f81f9afe4f..4ea599fd30e 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -83,7 +83,7 @@ static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob); /** \name Local Utility Functions * \{ */ -static bool object_array_for_wpaint_filter(Object *ob, void *user_data) +static bool object_array_for_wpaint_filter(const Object *ob, void *user_data) { bContext *C = user_data; if (vertex_group_supported_poll_ex(C, ob)) { @@ -130,7 +130,7 @@ bool ED_vgroup_sync_from_pose(Object *ob) if (arm->act_bone) { int def_num = BKE_object_defgroup_name_index(ob, arm->act_bone->name); if (def_num != -1) { - ob->actdef = def_num + 1; + BKE_object_defgroup_active_index_set(ob, def_num + 1); return true; } } @@ -389,11 +389,16 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) int dvert_tot_from; int dvert_tot; int i; - int defbase_tot_from = BLI_listbase_count(&ob_from->defbase); - int defbase_tot = BLI_listbase_count(&ob->defbase); + ListBase *defbase_dst = BKE_object_defgroup_list_mutable(ob); + const ListBase *defbase_src = BKE_object_defgroup_list(ob_from); + + int defbase_tot_from = BLI_listbase_count(defbase_src); + int defbase_tot = BLI_listbase_count(defbase_dst); bool new_vgroup = false; - if (ob == ob_from) { + BLI_assert(ob != ob_from); + + if (ob->data == ob_from->data) { return true; } @@ -429,9 +434,9 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) } /* do the copy */ - BLI_freelistN(&ob->defbase); - BLI_duplicatelist(&ob->defbase, &ob_from->defbase); - ob->actdef = ob_from->actdef; + BLI_freelistN(defbase_dst); + BLI_duplicatelist(defbase_dst, defbase_src); + BKE_object_defgroup_active_index_set(ob, BKE_object_defgroup_active_index_get(ob_from)); if (defbase_tot_from < defbase_tot) { /* correct vgroup indices because the number of vgroups is being reduced. */ @@ -509,21 +514,21 @@ void ED_vgroup_parray_from_weight_array(MDeformVert **dvert_array, } } -/* TODO, cache flip data to speedup calls within a loop. */ +/* TODO: cache flip data to speedup calls within a loop. */ static void mesh_defvert_mirror_update_internal(Object *ob, MDeformVert *dvert_dst, MDeformVert *dvert_src, const int def_nr) { if (def_nr == -1) { - /* all vgroups, add groups where needed */ + /* All vgroups, add groups where needed. */ int flip_map_len; int *flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, true); BKE_defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true); MEM_freeN(flip_map); } else { - /* single vgroup */ + /* Single vgroup. */ MDeformWeight *dw = BKE_defvert_ensure_index(dvert_dst, BKE_object_defgroup_flip_index(ob, def_nr, 1)); if (dw) { @@ -882,7 +887,8 @@ void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, /* add the vert to the deform group with the * specified assign mode */ - const int def_nr = BLI_findindex(&ob->defbase, dg); + const ListBase *defbase = BKE_object_defgroup_list(ob); + const int def_nr = BLI_findindex(defbase, dg); MDeformVert *dv = NULL; int tot; @@ -913,7 +919,8 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum) /* TODO(campbell): This is slow in a loop, better pass def_nr directly, * but leave for later. */ - const int def_nr = BLI_findindex(&ob->defbase, dg); + const ListBase *defbase = BKE_object_defgroup_list(ob); + const int def_nr = BLI_findindex(defbase, dg); if (def_nr != -1) { MDeformVert *dvert = NULL; @@ -989,7 +996,8 @@ static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum) float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum) { - const int def_nr = BLI_findindex(&ob->defbase, dg); + const ListBase *defbase = BKE_object_defgroup_list(ob); + const int def_nr = BLI_findindex(defbase, dg); if (def_nr == -1) { return -1; @@ -1000,9 +1008,9 @@ float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum) void ED_vgroup_select_by_name(Object *ob, const char *name) { - /* note: ob->actdef==0 signals on painting to create a new one, + /* NOTE: actdef==0 signals on painting to create a new one, * if a bone in posemode is selected */ - ob->actdef = BKE_object_defgroup_name_index(ob, name) + 1; + BKE_object_defgroup_active_index_set(ob, BKE_object_defgroup_name_index(ob, name) + 1); } /** \} */ @@ -1014,9 +1022,10 @@ void ED_vgroup_select_by_name(Object *ob, const char *name) /* only in editmode */ static void vgroup_select_verts(Object *ob, int select) { - const int def_nr = ob->actdef - 1; + const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + if (!BLI_findlink(defbase, def_nr)) { return; } @@ -1111,7 +1120,9 @@ static void vgroup_duplicate(Object *ob) MDeformVert **dvert_array = NULL; int i, idg, icdg, dvert_tot = 0; - dg = BLI_findlink(&ob->defbase, (ob->actdef - 1)); + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); + + dg = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1); if (!dg) { return; } @@ -1127,13 +1138,13 @@ static void vgroup_duplicate(Object *ob) BLI_strncpy(cdg->name, name, sizeof(cdg->name)); BKE_object_defgroup_unique_name(cdg, ob); - BLI_addtail(&ob->defbase, cdg); + BLI_addtail(defbase, cdg); - idg = (ob->actdef - 1); - ob->actdef = BLI_listbase_count(&ob->defbase); - icdg = (ob->actdef - 1); + idg = BKE_object_defgroup_active_index_get(ob) - 1; + BKE_object_defgroup_active_index_set(ob, BLI_listbase_count(defbase)); + icdg = BKE_object_defgroup_active_index_get(ob) - 1; - /* TODO, we might want to allow only copy selected verts here? - campbell */ + /* TODO(campbell): we might want to allow only copy selected verts here? */ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); if (dvert_array) { @@ -1157,11 +1168,12 @@ static bool vgroup_normalize(Object *ob) MDeformWeight *dw; MDeformVert *dv, **dvert_array = NULL; int dvert_tot = 0; - const int def_nr = ob->actdef - 1; + const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; const bool use_vert_sel = vertex_group_use_vert_sel(ob); - if (!BLI_findlink(&ob->defbase, def_nr)) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + if (!BLI_findlink(defbase, def_nr)) { return false; } @@ -1639,7 +1651,7 @@ static bool vgroup_normalize_all(Object *ob, { MDeformVert *dv, **dvert_array = NULL; int i, dvert_tot = 0; - const int def_nr = ob->actdef - 1; + const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; const bool use_vert_sel = vertex_group_use_vert_sel(ob); @@ -1651,7 +1663,8 @@ static bool vgroup_normalize_all(Object *ob, ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); if (dvert_array) { - const int defbase_tot = BLI_listbase_count(&ob->defbase); + const ListBase *defbase = BKE_object_defgroup_list(ob); + const int defbase_tot = BLI_listbase_count(defbase); bool *lock_flags = BKE_object_defgroup_lock_flags_get(ob, defbase_tot); bool changed = false; @@ -1742,7 +1755,7 @@ static const EnumPropertyItem vgroup_lock_mask[] = { static bool *vgroup_selected_get(Object *ob) { - int sel_count = 0, defbase_tot = BLI_listbase_count(&ob->defbase); + int sel_count = 0, defbase_tot = BKE_object_defgroup_count(ob); bool *mask; if (ob->mode & OB_MODE_WEIGHT_PAINT) { @@ -1759,8 +1772,9 @@ static bool *vgroup_selected_get(Object *ob) mask = MEM_callocN(defbase_tot * sizeof(bool), __func__); } - if (sel_count == 0 && ob->actdef >= 1 && ob->actdef <= defbase_tot) { - mask[ob->actdef - 1] = true; + const int actdef = BKE_object_defgroup_active_index_get(ob); + if (sel_count == 0 && actdef >= 1 && actdef <= defbase_tot) { + mask[actdef - 1] = true; } return mask; @@ -1775,11 +1789,12 @@ static void vgroup_lock_all(Object *ob, int action, int mask) if (mask != VGROUP_MASK_ALL) { selected = vgroup_selected_get(ob); } + const ListBase *defbase = BKE_object_defgroup_list(ob); if (action == VGROUP_TOGGLE) { action = VGROUP_LOCK; - for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) { + for (dg = defbase->first, i = 0; dg; dg = dg->next, i++) { switch (mask) { case VGROUP_MASK_INVERT_UNSELECTED: case VGROUP_MASK_SELECTED: @@ -1802,7 +1817,7 @@ static void vgroup_lock_all(Object *ob, int action, int mask) } } - for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) { + for (dg = defbase->first, i = 0; dg; dg = dg->next, i++) { switch (mask) { case VGROUP_MASK_SELECTED: if (!selected[i]) { @@ -2352,8 +2367,8 @@ static void dvert_mirror_op(MDeformVert *dvert, } } -/* TODO, vgroup locking */ -/* TODO, face masking */ +/* TODO: vgroup locking. */ +/* TODO: face masking. */ void ED_vgroup_mirror(Object *ob, const bool mirror_weights, const bool flip_vgroups, @@ -2379,13 +2394,15 @@ void ED_vgroup_mirror(Object *ob, MDeformVert *dvert, *dvert_mirr; char sel, sel_mirr; int *flip_map = NULL, flip_map_len; - const int def_nr = ob->actdef - 1; + const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; int totmirr = 0, totfail = 0; *r_totmirr = *r_totfail = 0; + const ListBase *defbase = BKE_object_defgroup_list(ob); + if ((mirror_weights == false && flip_vgroups == false) || - (BLI_findlink(&ob->defbase, def_nr) == NULL)) { + (BLI_findlink(defbase, def_nr) == NULL)) { return; } @@ -2569,7 +2586,8 @@ cleanup: static void vgroup_delete_active(Object *ob) { - bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1); + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *dg = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1); if (!dg) { return; } @@ -2580,9 +2598,10 @@ static void vgroup_delete_active(Object *ob) /* only in editmode */ static void vgroup_assign_verts(Object *ob, const float weight) { - const int def_nr = ob->actdef - 1; + const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + if (!BLI_findlink(defbase, def_nr)) { return; } @@ -2700,7 +2719,8 @@ static bool vertex_group_poll_ex(bContext *C, Object *ob) return false; } - if (BLI_listbase_is_empty(&ob->defbase)) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + if (BLI_listbase_is_empty(defbase)) { CTX_wm_operator_poll_msg_set(C, "Object has no vertex groups"); return false; } @@ -2823,8 +2843,10 @@ static bool vertex_group_vert_select_unlocked_poll(bContext *C) return false; } - if (ob->actdef != 0) { - bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1); + const int def_nr = BKE_object_defgroup_active_index_get(ob); + if (def_nr != 0) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + const bDeformGroup *dg = BLI_findlink(defbase, def_nr - 1); if (dg) { return !(dg->flag & DG_LOCK_WEIGHT); } @@ -3025,8 +3047,8 @@ static int vertex_group_remove_from_exec(bContext *C, wmOperator *op) } } else { - bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1); - + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *dg = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1); if ((dg == NULL) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) { return OPERATOR_CANCELLED; } @@ -3774,7 +3796,7 @@ static int vertex_group_limit_total_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - /* note, would normally return canceled, except we want the redo + /* NOTE: would normally return canceled, except we want the redo * UI to show up for users to change */ return OPERATOR_FINISHED; } @@ -3860,55 +3882,6 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Vertex Group Copy to Linked Operator - * \{ */ - -static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Scene *scene = CTX_data_scene(C); - Object *ob_active = ED_object_context(C); - int retval = OPERATOR_CANCELLED; - - FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) { - if (ob_iter->type == ob_active->type) { - if (ob_iter != ob_active && ob_iter->data == ob_active->data) { - BLI_freelistN(&ob_iter->defbase); - BLI_duplicatelist(&ob_iter->defbase, &ob_active->defbase); - ob_iter->actdef = ob_active->actdef; - - DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter); - WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_iter->data); - - retval = OPERATOR_FINISHED; - } - } - } - FOREACH_SCENE_OBJECT_END; - - return retval; -} - -void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Copy Vertex Groups to Linked"; - ot->idname = "OBJECT_OT_vertex_group_copy_to_linked"; - ot->description = - "Replace vertex groups of all users of the same geometry data by vertex groups of active " - "object"; - - /* api callbacks */ - ot->poll = vertex_group_poll; - ot->exec = vertex_group_copy_to_linked_exec; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Vertex Group Copy to Selected Operator * \{ */ @@ -3972,7 +3945,7 @@ static int set_active_group_exec(bContext *C, wmOperator *op) int nr = RNA_enum_get(op->ptr, "group"); BLI_assert(nr + 1 >= 0); - ob->actdef = nr + 1; + BKE_object_defgroup_active_index_set(ob, nr + 1); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); @@ -3985,6 +3958,10 @@ static const EnumPropertyItem *vgroup_itemf(bContext *C, PropertyRNA *UNUSED(prop), bool *r_free) { + if (C == NULL) { + return DummyRNA_NULL_items; + } + Object *ob = ED_object_context(C); EnumPropertyItem tmp = {0, "", 0, "", ""}; EnumPropertyItem *item = NULL; @@ -3995,7 +3972,8 @@ static const EnumPropertyItem *vgroup_itemf(bContext *C, return DummyRNA_NULL_items; } - for (a = 0, def = ob->defbase.first; def; def = def->next, a++) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + for (a = 0, def = defbase->first; def; def = def->next, a++) { tmp.value = a; tmp.icon = ICON_GROUP_VERTEX; tmp.identifier = def->name; @@ -4044,13 +4022,13 @@ void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot) * with the order of vgroups then call vgroup_do_remap after */ static char *vgroup_init_remap(Object *ob) { - bDeformGroup *def; - int defbase_tot = BLI_listbase_count(&ob->defbase); + const ListBase *defbase = BKE_object_defgroup_list(ob); + int defbase_tot = BLI_listbase_count(defbase); char *name_array = MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups"); char *name; name = name_array; - for (def = ob->defbase.first; def; def = def->next) { + for (const bDeformGroup *def = defbase->first; def; def = def->next) { BLI_strncpy(name, def->name, MAX_VGROUP_NAME); name += MAX_VGROUP_NAME; } @@ -4061,10 +4039,11 @@ static char *vgroup_init_remap(Object *ob) static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) { MDeformVert *dvert = NULL; - bDeformGroup *def; - int defbase_tot = BLI_listbase_count(&ob->defbase); + const bDeformGroup *def; + const ListBase *defbase = BKE_object_defgroup_list(ob); + int defbase_tot = BLI_listbase_count(defbase); - /* needs a dummy index at the start*/ + /* Needs a dummy index at the start. */ int *sort_map_update = MEM_mallocN(sizeof(int) * (defbase_tot + 1), "sort vgroups"); int *sort_map = sort_map_update + 1; @@ -4072,8 +4051,8 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) int i; name = name_array; - for (def = ob->defbase.first, i = 0; def; def = def->next, i++) { - sort_map[i] = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)); + for (def = defbase->first, i = 0; def; def = def->next, i++) { + sort_map[i] = BLI_findstringindex(defbase, name, offsetof(bDeformGroup, name)); name += MAX_VGROUP_NAME; BLI_assert(sort_map[i] != -1); @@ -4107,7 +4086,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) BKE_object_defgroup_array_get(ob->data, &dvert, &dvert_tot); - /*create as necessary*/ + /* Create as necessary. */ if (dvert) { while (dvert_tot--) { if (dvert->totweight) { @@ -4126,8 +4105,9 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) sort_map_update[0] = 0; BKE_object_defgroup_remap_update_users(ob, sort_map_update); - BLI_assert(sort_map_update[ob->actdef] >= 0); - ob->actdef = sort_map_update[ob->actdef]; + BLI_assert(sort_map_update[BKE_object_defgroup_active_index_get(ob)] >= 0); + BKE_object_defgroup_active_index_set(ob, + sort_map_update[BKE_object_defgroup_active_index_get(ob)]); MEM_freeN(sort_map_update); @@ -4155,6 +4135,7 @@ static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase) bonebase = &armature->bonebase; } } + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); if (bonebase != NULL) { Bone *bone; @@ -4163,8 +4144,8 @@ static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase) vgroup_sort_bone_hierarchy(ob, &bone->childbase); if (dg != NULL) { - BLI_remlink(&ob->defbase, dg); - BLI_addhead(&ob->defbase, dg); + BLI_remlink(defbase, dg); + BLI_addhead(defbase, dg); } } } @@ -4182,20 +4163,22 @@ static int vertex_group_sort_exec(bContext *C, wmOperator *op) int ret; int sort_type = RNA_enum_get(op->ptr, "sort_type"); - /*init remapping*/ + /* Init remapping. */ name_array = vgroup_init_remap(ob); - /*sort vgroup names*/ + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); + + /* Sort vgroup names. */ switch (sort_type) { case SORT_TYPE_NAME: - BLI_listbase_sort(&ob->defbase, vgroup_sort_name); + BLI_listbase_sort(defbase, vgroup_sort_name); break; case SORT_TYPE_BONEHIERARCHY: vgroup_sort_bone_hierarchy(ob, NULL); break; } - /*remap vgroup data to map to correct names*/ + /* Remap vgroup data to map to correct names. */ ret = vgroup_do_remap(ob, name_array, op); if (ret != OPERATOR_CANCELLED) { @@ -4246,14 +4229,16 @@ static int vgroup_move_exec(bContext *C, wmOperator *op) int dir = RNA_enum_get(op->ptr, "direction"); int ret = OPERATOR_FINISHED; - def = BLI_findlink(&ob->defbase, ob->actdef - 1); + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); + + def = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1); if (!def) { return OPERATOR_CANCELLED; } name_array = vgroup_init_remap(ob); - if (BLI_listbase_link_move(&ob->defbase, def, dir)) { + if (BLI_listbase_link_move(defbase, def, dir)) { ret = vgroup_do_remap(ob, name_array, op); if (ret != OPERATOR_CANCELLED) { @@ -4372,7 +4357,8 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) static bool check_vertex_group_accessible(wmOperator *op, Object *ob, int def_nr) { - bDeformGroup *dg = BLI_findlink(&ob->defbase, def_nr); + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *dg = BLI_findlink(defbase, def_nr); if (!dg) { BKE_report(op->reports, RPT_ERROR, "Invalid vertex group index"); @@ -4494,7 +4480,7 @@ static int vertex_weight_set_active_exec(bContext *C, wmOperator *op) const int wg_index = RNA_int_get(op->ptr, "weight_group"); if (wg_index != -1) { - ob->actdef = wg_index + 1; + BKE_object_defgroup_active_index_set(ob, wg_index + 1); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); } diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c index a761701f60b..56f32ff603c 100644 --- a/source/blender/editors/physics/dynamicpaint_ops.c +++ b/source/blender/editors/physics/dynamicpaint_ops.c @@ -454,7 +454,7 @@ static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update job->start = PIL_check_seconds_timer(); job->success = 1; - G.is_break = false; /* reset BKE_blender_test_break*/ + G.is_break = false; /* XXX annoying hack: needed to prevent data corruption when changing * scene frame in separate threads diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 5b545784e5b..f2bbd6d5084 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -300,7 +300,7 @@ static void pe_update_hair_particle_edit_pointers(PTCacheEdit *edit) /* always gets at least the first particlesystem even if PSYS_CURRENT flag is not set * - * note: this function runs on poll, therefore it can runs many times a second + * NOTE: this function runs on poll, therefore it can runs many times a second * keep it fast! */ static PTCacheEdit *pe_get_current(Depsgraph *depsgraph, Scene *scene, Object *ob, bool create) { @@ -466,6 +466,7 @@ static int pe_x_mirror(Object *ob) typedef struct PEData { ViewContext vc; + ViewDepths *depths; const bContext *context; Main *bmain; @@ -524,21 +525,19 @@ static void PE_set_view3d_data(bContext *C, PEData *data) ED_view3d_viewcontext_init(C, &data->vc, data->depsgraph); if (!XRAY_ENABLED(data->vc.v3d)) { - if (!(data->vc.v3d->runtime.flag & V3D_RUNTIME_DEPTHBUF_OVERRIDDEN)) { - ED_view3d_depth_override(data->depsgraph, - data->vc.region, - data->vc.v3d, - data->vc.obact, - V3D_DEPTH_OBJECT_ONLY, - true); - } + ED_view3d_depth_override(data->depsgraph, + data->vc.region, + data->vc.v3d, + data->vc.obact, + V3D_DEPTH_OBJECT_ONLY, + &data->depths); } } static bool PE_create_shape_tree(PEData *data, Object *shapeob) { Object *shapeob_eval = DEG_get_evaluated_object(data->depsgraph, shapeob); - Mesh *mesh = BKE_object_get_evaluated_mesh(shapeob_eval); + const Mesh *mesh = BKE_object_get_evaluated_mesh(shapeob_eval); memset(&data->shape_bvh, 0, sizeof(data->shape_bvh)); @@ -570,6 +569,16 @@ static void PE_free_random_generator(PEData *data) } } +static void PE_data_free(PEData *data) +{ + PE_free_random_generator(data); + PE_free_shape_tree(data); + if (data->depths) { + ED_view3d_depths_free(data->depths); + data->depths = NULL; + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -579,7 +588,7 @@ static void PE_free_random_generator(PEData *data) static bool key_test_depth(const PEData *data, const float co[3], const int screen_co[2]) { View3D *v3d = data->vc.v3d; - ViewDepths *vd = data->vc.rv3d->depths; + ViewDepths *vd = data->depths; float depth; /* nothing to do */ @@ -609,7 +618,7 @@ static bool key_test_depth(const PEData *data, const float co[3], const int scre } float win[3]; - ED_view3d_project(data->vc.region, co, win); + ED_view3d_project_v3(data->vc.region, co, win); if (win[2] - 0.00001f > depth) { return 0; @@ -622,7 +631,7 @@ static bool key_inside_circle(const PEData *data, float rad, const float co[3], float dx, dy, dist; int screen_co[2]; - /* TODO, should this check V3D_PROJ_TEST_CLIP_BB too? */ + /* TODO: should this check V3D_PROJ_TEST_CLIP_BB too? */ if (ED_view3d_project_int_global(data->vc.region, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) != V3D_PROJ_RET_OK) { return 0; @@ -1447,7 +1456,7 @@ void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *UNUSED(ob), Part BLI_kdtree_3d_free(edit->emitter_field); totface = mesh->totface; - /*totvert=dm->getNumVerts(dm);*/ /*UNUSED*/ + // totvert = dm->getNumVerts(dm); /* UNUSED */ edit->emitter_cosnos = MEM_callocN(sizeof(float[6]) * totface, "emitter cosnos"); @@ -1555,7 +1564,7 @@ void update_world_cos(Object *ob, PTCacheEdit *edit) } static void update_velocities(PTCacheEdit *edit) { - /*TODO: get frs_sec properly */ + /* TODO: get frs_sec properly. */ float vec1[3], vec2[3], frs_sec, dfra; POINT_P; KEY_K; @@ -1871,15 +1880,13 @@ void PARTICLE_OT_select_all(wmOperatorType *ot) bool PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) { - PEData data; + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); POINT_P; KEY_K; - PE_set_view3d_data(C, &data); - - PTCacheEdit *edit = PE_get_current(data.depsgraph, scene, ob); + PTCacheEdit *edit = PE_get_current(depsgraph, scene, ob); if (!PE_start_edit(edit)) { return false; @@ -1894,6 +1901,8 @@ bool PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool desele } } + PEData data; + PE_set_view3d_data(C, &data); data.mval = mval; data.rad = ED_view3d_select_dist_px(); @@ -1913,6 +1922,8 @@ bool PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool desele WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob); } + PE_data_free(&data); + return true; } @@ -2204,6 +2215,7 @@ static int select_linked_pick_exec(bContext *C, wmOperator *op) for_mouse_hit_keys(&data, select_keys, PSEL_NEAREST); PE_update_selection(data.depsgraph, data.scene, data.ob, 1); WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob); + PE_data_free(&data); return OPERATOR_FINISHED; } @@ -2298,11 +2310,14 @@ bool PE_box_select(bContext *C, const rcti *rect, const int sel_op) for_mouse_hit_keys(&data, select_key_op, PSEL_ALL_KEYS); } - if (data.is_changed) { - PE_update_selection(data.depsgraph, scene, ob, 1); + bool is_changed = data.is_changed; + PE_data_free(&data); + + if (is_changed) { + PE_update_selection(depsgraph, scene, ob, 1); WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob); } - return data.is_changed; + return is_changed; } /** \} */ @@ -2311,35 +2326,53 @@ bool PE_box_select(bContext *C, const rcti *rect, const int sel_op) /** \name Circle Select Operator * \{ */ -bool PE_circle_select(bContext *C, const int sel_op, const int mval[2], float rad) +static void pe_select_cache_free_generic_userdata(void *data) +{ + PE_data_free(data); + MEM_freeN(data); +} + +static void pe_select_cache_init_with_generic_userdata(bContext *C, wmGenericUserData *wm_userdata) +{ + struct PEData *data = MEM_callocN(sizeof(*data), __func__); + wm_userdata->data = data; + wm_userdata->free_fn = pe_select_cache_free_generic_userdata; + wm_userdata->use_free = true; + PE_set_view3d_data(C, data); +} + +bool PE_circle_select( + bContext *C, wmGenericUserData *wm_userdata, const int sel_op, const int mval[2], float rad) { BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); PTCacheEdit *edit = PE_get_current(depsgraph, scene, ob); - PEData data; if (!PE_start_edit(edit)) { return false; } - const bool select = (sel_op != SEL_OP_SUB); + if (wm_userdata->data == NULL) { + pe_select_cache_init_with_generic_userdata(C, wm_userdata); + } - PE_set_view3d_data(C, &data); - data.mval = mval; - data.rad = rad; - data.select = select; + PEData *data = wm_userdata->data; + data->mval = mval; + data->rad = rad; + data->select = (sel_op != SEL_OP_SUB); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - data.is_changed = PE_deselect_all_visible_ex(edit); + data->is_changed = PE_deselect_all_visible_ex(edit); } - for_mouse_hit_keys(&data, select_key, 0); - if (data.is_changed) { - PE_update_selection(data.depsgraph, scene, ob, 1); + for_mouse_hit_keys(data, select_key, 0); + + if (data->is_changed) { + PE_update_selection(depsgraph, scene, ob, 1); WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob); } - return data.is_changed; + return data->is_changed; } /** \} */ @@ -2425,8 +2458,11 @@ int PE_lasso_select(bContext *C, const int mcoords[][2], const int mcoords_len, } } - if (data.is_changed) { - PE_update_selection(data.depsgraph, scene, ob, 1); + bool is_changed = data.is_changed; + PE_data_free(&data); + + if (is_changed) { + PE_update_selection(depsgraph, scene, ob, 1); WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob); return OPERATOR_FINISHED; } @@ -2967,7 +3003,7 @@ static void remove_tagged_keys(Depsgraph *depsgraph, Object *ob, ParticleSystem LOOP_TAGGED_KEYS { new_totkey--; } - /* we can't have elements with less than two keys*/ + /* We can't have elements with less than two keys. */ if (new_totkey < 2) { point->flag |= PEP_TAG; } @@ -3106,7 +3142,7 @@ static void subdivide_particle(PEData *data, int pa_index) nkey++; } } - /*tip still not copied*/ + /* Tip still not copied. */ memcpy(nkey, key, sizeof(HairKey)); memcpy(nekey, ekey, sizeof(PTCacheEditKey)); @@ -3919,7 +3955,7 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance) /* keep the same distance from the root or we get glitches T35406. */ dist_ensure_v3_v3fl(co, co_root, length_accum); - /* re-use dco to compare before and after translation and add to the offset */ + /* Re-use dco to compare before and after translation and add to the offset. */ copy_v3_v3(dco, key->co); mul_v3_m4v3(key->co, imat, co); @@ -3938,7 +3974,7 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance) /* this is simple but looks bad, adds annoying kinks */ add_v3_v3(key->co, ofs); #else - /* translate (not rotate) the rest of the hair if its not selected */ + /* Translate (not rotate) the rest of the hair if its not selected. */ { /* NOLINTNEXTLINE: readability-redundant-preprocessor */ # if 0 /* kindof works but looks worse than what's below */ @@ -4921,7 +4957,7 @@ static void brush_edit_exit(wmOperator *op) { BrushEdit *bedit = op->customdata; - PE_free_random_generator(&bedit->data); + PE_data_free(&bedit->data); MEM_freeN(bedit); } @@ -5408,7 +5444,7 @@ void ED_object_particle_edit_mode_enter_ex(Depsgraph *depsgraph, Scene *scene, O edit = PE_create_current(depsgraph, scene, ob); /* Mesh may have changed since last entering editmode. - * note, this may have run before if the edit data was just created, + * NOTE: this may have run before if the edit data was just created, * so could avoid this and speed up a little. */ if (edit && edit->psys) { /* Make sure pointer to the evaluated modifier data is up to date, diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 6bcc9df16bf..387d10d538b 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -848,7 +848,8 @@ static bool remap_hair_emitter(Depsgraph *depsgraph, copy_m4_m4(imat, target_ob->obmat); } else { - /* note: using target_dm here, which is in target_ob object space and has full modifiers */ + /* NOTE: using target_dm here, which is in target_ob object space and has full modifiers. + */ psys_mat_hair_to_object(target_ob, target_mesh, target_psys->part->from, tpa, hairmat); invert_m4_m4(imat, hairmat); } @@ -1160,7 +1161,7 @@ static bool copy_particle_systems_to_object(const bContext *C, } MEM_freeN(tmp_psys); - /* note: do this after creating DM copies for all the particle system modifiers, + /* NOTE: do this after creating DM copies for all the particle system modifiers, * the remapping otherwise makes final_dm invalid! */ for (psys = psys_start, psys_from = PSYS_FROM_FIRST, i = 0; psys; diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index a94a2b9b764..cbab4fbd3d1 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -403,8 +403,10 @@ static void fluid_bake_startjob(void *customdata, short *stop, short *do_update, BLI_path_join( temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, NULL); BLI_path_abs(temp_dir, relbase); - BLI_dir_create_recursive( - temp_dir); /* Create 'particles' subdir if it does not exist already */ + + /* Create 'particles' subdir if it does not exist already */ + BLI_dir_create_recursive(temp_dir); + fds->cache_flag &= ~(FLUID_DOMAIN_BAKED_PARTICLES | FLUID_DOMAIN_OUTDATED_PARTICLES); fds->cache_flag |= FLUID_DOMAIN_BAKING_PARTICLES; job->pause_frame = &fds->cache_frame_pause_particles; diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h index 4dc3ded9bd7..ef07d73826a 100644 --- a/source/blender/editors/physics/physics_intern.h +++ b/source/blender/editors/physics/physics_intern.h @@ -147,7 +147,7 @@ void RIGIDBODY_OT_mass_calculate(struct wmOperatorType *ot); void RIGIDBODY_OT_constraint_add(struct wmOperatorType *ot); void RIGIDBODY_OT_constraint_remove(struct wmOperatorType *ot); -/*rigidbody_world.c */ +/* rigidbody_world.c */ void RIGIDBODY_OT_world_add(struct wmOperatorType *ot); void RIGIDBODY_OT_world_remove(struct wmOperatorType *ot); void RIGIDBODY_OT_world_export(struct wmOperatorType *ot); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 0bec509cd7e..d5ad5a5eb84 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -121,7 +121,7 @@ static bool image_buffer_calc_tile_rect(const RenderResult *rr, { int tile_y, tile_height, tile_x, tile_width; - /* if renrect argument, we only refresh scanlines */ + /* When `renrect` argument is not NULL, we only refresh scan-lines. */ if (renrect) { /* if (tile_height == recty), rendering of layer is ready, * we should not draw, other things happen... */ @@ -285,7 +285,7 @@ static void screen_render_single_layer_set( scn = (Scene *)BLI_findstring(&mainp->scenes, scene_name, offsetof(ID, name) + 2); if (scn) { - /* camera switch wont have updated */ + /* camera switch won't have updated */ scn->r.cfra = (*scene)->r.cfra; BKE_scene_camera_switch_update(scn); @@ -773,7 +773,7 @@ static void render_endjob(void *rjv) * was locked before running the job. */ WM_set_locked_interface(G_MAIN->wm.first, false); - DEG_on_visible_update(G_MAIN, false); + DEG_tag_on_visible_update(G_MAIN, false); } } @@ -793,7 +793,7 @@ static int render_breakjob(void *rjv) /** * For exec() when there is no render job - * note: this wont check for the escape key being pressed, but doing so isn't thread-safe. + * NOTE: this won't check for the escape key being pressed, but doing so isn't thread-safe. */ static int render_break(void *UNUSED(rjv)) { diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 48f937fb4ec..17aaa5aa79d 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -141,7 +141,9 @@ typedef struct OGLRender { wmWindowManager *wm; wmWindow *win; - wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/ + /** Use to check if running modal or not (invoke'd or exec'd). */ + wmTimer *timer; + void **movie_ctx_arr; TaskPool *task_pool; @@ -461,7 +463,7 @@ static void screen_opengl_render_write(OGLRender *oglrender) static void UNUSED_FUNCTION(addAlphaOverFloat)(float dest[4], const float source[4]) { - /* d = s + (1-alpha_s)d*/ + /* `d = s + (1-alpha_s)d` */ float mul; mul = 1.0f - source[3]; @@ -544,7 +546,7 @@ static void gather_frames_to_render_for_adt(const OGLRender *oglrender, const An continue; } - bool found = false; /* Not interesting, we just want a starting point for the for-loop.*/ + bool found = false; /* Not interesting, we just want a starting point for the for-loop. */ int key_index = BKE_fcurve_bezt_binarysearch_index( fcu->bezt, frame_start, fcu->totvert, &found); for (; key_index < fcu->totvert; key_index++) { @@ -645,7 +647,7 @@ static int gather_frames_to_render_for_id(LibraryIDLinkCallbackData *cb_data) case ID_WM: /* WindowManager */ case ID_LS: /* FreestyleLineStyle */ case ID_PAL: /* Palette */ - case ID_PC: /* PaintCurve */ + case ID_PC: /* PaintCurve */ case ID_CF: /* CacheFile */ case ID_WS: /* WorkSpace */ /* Only follow pointers to specific datablocks, to avoid ending up in diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 157f2b3ecb4..7f7ee45a803 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -70,6 +70,7 @@ #include "BKE_node.h" #include "BKE_object.h" #include "BKE_scene.h" +#include "BKE_screen.h" #include "BKE_texture.h" #include "BKE_world.h" @@ -252,7 +253,7 @@ static const char *preview_collection_name(const char pr_type) case MA_ATMOS: return "Atmosphere"; default: - BLI_assert(!"Unknown preview type"); + BLI_assert_msg(0, "Unknown preview type"); return ""; } } @@ -334,7 +335,7 @@ static ID *duplicate_ids(ID *id, const bool allow_failure) return NULL; default: if (!allow_failure) { - BLI_assert(!"ID type preview not supported."); + BLI_assert_msg(0, "ID type preview not supported."); } return NULL; } @@ -610,9 +611,7 @@ static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect float fy = rect->ymin; /* material preview only needs monoscopy (view 0) */ - if (re) { - RE_AcquiredResultGet32(re, &rres, (uint *)rect_byte, 0); - } + RE_AcquiredResultGet32(re, &rres, (uint *)rect_byte, 0); IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); immDrawPixelsTex( @@ -776,21 +775,26 @@ static void object_preview_render(IconPreview *preview, IconPreviewSize *preview U.pixelsize = 2.0f; + View3DShading shading; + BKE_screen_view3d_shading_init(&shading); + /* Enable shadows, makes it a bit easier to see the shape. */ + shading.flag |= V3D_SHADING_SHADOW; + ImBuf *ibuf = ED_view3d_draw_offscreen_imbuf_simple( depsgraph, DEG_get_evaluated_scene(depsgraph), - NULL, - OB_SOLID, + &shading, + OB_TEXTURE, DEG_get_evaluated_object(depsgraph, scene->camera), preview_sized->sizex, preview_sized->sizey, IB_rect, - V3D_OFSDRAW_NONE, + V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS, R_ALPHAPREMUL, NULL, NULL, err_out); - /* TODO color-management? */ + /* TODO: color-management? */ U.pixelsize = pixelsize_old; @@ -951,7 +955,7 @@ static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Rend for (int x = 0; x < width; x++) { tex_coord[0] = ((float)x / (float)height) * 2.0f - 1.0f; - /* Evaluate texture at tex_coord .*/ + /* Evaluate texture at tex_coord. */ TexResult texres = {0}; BKE_texture_get_value_ex(sce, tex, tex_coord, &texres, img_pool, color_manage); @@ -1465,7 +1469,7 @@ static int icon_previewimg_size_index_get(const IconPreviewSize *icon_size, } } - BLI_assert(!"The searched icon size does not match any in the preview image"); + BLI_assert_msg(0, "The searched icon size does not match any in the preview image"); return -1; } diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index b4cac58db1f..d2b1ebdad78 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -103,7 +103,7 @@ static bool object_materials_supported_poll_ex(bContext *C, const Object *ob); /** \name Local Utilities * \{ */ -static bool object_array_for_shading_edit_mode_enabled_filter(Object *ob, void *user_data) +static bool object_array_for_shading_edit_mode_enabled_filter(const Object *ob, void *user_data) { bContext *C = user_data; if (object_materials_supported_poll_ex(C, ob)) { @@ -120,7 +120,7 @@ static Object **object_array_for_shading_edit_mode_enabled(bContext *C, uint *r_ C, object_array_for_shading_edit_mode_enabled_filter, C, r_objects_len); } -static bool object_array_for_shading_edit_mode_disabled_filter(Object *ob, void *user_data) +static bool object_array_for_shading_edit_mode_disabled_filter(const Object *ob, void *user_data) { bContext *C = user_data; if (object_materials_supported_poll_ex(C, ob)) { @@ -227,7 +227,7 @@ static int material_slot_remove_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* Removing material slots in edit mode screws things up, see bug T21822.*/ + /* Removing material slots in edit mode screws things up, see bug T21822. */ if (ob == CTX_data_edit_object(C)) { BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode"); return OPERATOR_CANCELLED; @@ -294,7 +294,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op)) } else { /* Find the first matching material. - * Note: there may be multiple but that's not a common use case. */ + * NOTE: there may be multiple but that's not a common use case. */ for (int i = 0; i < ob->totcol; i++) { const Material *mat = BKE_object_material_get(ob, i + 1); if (mat_active == mat) { @@ -401,7 +401,7 @@ static int material_slot_de_select(bContext *C, bool select) } else { /* Find the first matching material. - * Note: there may be multiple but that's not a common use case. */ + * NOTE: there may be multiple but that's not a common use case. */ for (int i = 0; i < ob->totcol; i++) { const Material *mat = BKE_object_material_get(ob, i + 1); if (mat_active == mat) { @@ -1183,7 +1183,7 @@ static int light_cache_bake_exec(bContext *C, wmOperator *op) G.is_break = false; - /* TODO abort if selected engine is not eevee. */ + /* TODO: abort if selected engine is not eevee. */ void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false, scene->r.cfra); light_cache_bake_tag_cache(scene, op); @@ -2418,7 +2418,7 @@ static void paste_mtex_copybuf(ID *id) mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]); break; default: - BLI_assert(!"invalid id type"); + BLI_assert_msg(0, "invalid id type"); return; } diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 3e8a1bda2f0..80b5623b9c3 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -216,7 +216,7 @@ void ED_render_view_layer_changed(Main *bmain, bScreen *screen) /***************************** Updates *********************************** * ED_render_id_flush_update gets called from DEG_id_tag_update, to do * * editor level updates when the ID changes. when these ID blocks are in * - * the dependency graph, we can get rid of the manual dependency checks */ + * the dependency graph, we can get rid of the manual dependency checks. */ static void material_changed(Main *UNUSED(bmain), Material *ma) { diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c index 465438f814a..97ecb67d6cc 100644 --- a/source/blender/editors/render/render_view.c +++ b/source/blender/editors/render/render_view.c @@ -51,9 +51,11 @@ /*********************** utilities for finding areas *************************/ -/* returns biggest area that is not uv/image editor. Note that it uses buttons */ -/* window as the last possible alternative. */ -/* would use BKE_screen_find_big_area(...) but this is too specific */ +/** + * Returns biggest area that is not uv/image editor. Note that it uses buttons + * window as the last possible alternative. + * would use #BKE_screen_find_big_area(...) but this is too specific. + */ static ScrArea *biggest_non_image_area(bContext *C) { bScreen *screen = CTX_wm_screen(C); @@ -164,6 +166,7 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports) sizex, sizey, SPACE_IMAGE, + true, false, true, WIN_ALIGN_LOCATION_CENTER) == NULL) { diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c index 2b2a0d10e29..5195bc8303a 100644 --- a/source/blender/editors/scene/scene_edit.c +++ b/source/blender/editors/scene/scene_edit.c @@ -120,7 +120,7 @@ void ED_scene_change_update(Main *bmain, Scene *scene, ViewLayer *layer) BKE_scene_set_background(bmain, scene); DEG_graph_relations_update(depsgraph); - DEG_on_visible_update(bmain, false); + DEG_tag_on_visible_update(bmain, false); ED_render_engine_changed(bmain, false); ED_update_for_newframe(bmain, depsgraph); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index b83eccdcfdd..f4109981aae 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1385,7 +1385,7 @@ static void region_rect_recursive( region->flag |= RGN_FLAG_SIZE_CLAMP_Y; } - /* We need to use a test that wont have been previously clamped. */ + /* We need to use a test that won't have been previously clamped. */ rcti winrct_test = { .xmin = region->winrct.xmin, .ymin = region->winrct.ymin, @@ -1461,7 +1461,7 @@ static void region_rect_recursive( } } else if (ELEM(alignment, RGN_ALIGN_VSPLIT, RGN_ALIGN_HSPLIT)) { - /* percentage subdiv*/ + /* Percentage subdiv. */ region->winrct = *remainder; if (alignment == RGN_ALIGN_HSPLIT) { @@ -1527,8 +1527,8 @@ static void region_rect_recursive( BLI_rcti_init(remainder, 0, 0, 0, 0); } - /* Fix any negative dimensions. This can happen when a quad split 3d view gets to small. (see - * T72200). */ + /* Fix any negative dimensions. This can happen when a quad split 3d view gets too small. + * (see T72200). */ BLI_rcti_sanitize(®ion->winrct); quad++; @@ -1539,8 +1539,8 @@ static void region_rect_recursive( region->winx = BLI_rcti_size_x(®ion->winrct) + 1; region->winy = BLI_rcti_size_y(®ion->winrct) + 1; - /* if region opened normally, we store this for hide/reveal usage */ - /* prevent rounding errors for UI_DPI_FAC mult and divide */ + /* If region opened normally, we store this for hide/reveal usage. */ + /* Prevent rounding errors for UI_DPI_FAC multiply and divide. */ if (region->winx > 1) { region->sizex = (region->winx + 0.5f) / UI_DPI_FAC; } @@ -1680,7 +1680,7 @@ static void ed_default_handlers( { BLI_assert(region ? (®ion->handlers == handlers) : (&area->handlers == handlers)); - /* note, add-handler checks if it already exists */ + /* NOTE: add-handler checks if it already exists. */ /* XXX it would be good to have boundbox checks for some of these... */ if (flag & ED_KEYMAP_UI) { @@ -2081,7 +2081,7 @@ void ED_area_data_copy(ScrArea *area_dst, ScrArea *area_src, const bool do_free) } BKE_spacedata_copylist(&area_dst->spacedata, &area_src->spacedata); - /* Note; SPACE_EMPTY is possible on new screens */ + /* NOTE: SPACE_EMPTY is possible on new screens. */ /* regions */ if (do_free) { @@ -2387,7 +2387,7 @@ void ED_area_newspace(bContext *C, ScrArea *area, int type, const bool skip_regi * However, add-on install for example, forces the header to the top which shouldn't * be applied back to the previous space type when closing - see: T57724 * - * Newly created windows wont have any space data, use the alignment + * Newly-created windows won't have any space data, use the alignment * the space type defaults to in this case instead * (needed for preferences to have space-type on bottom). */ @@ -3325,10 +3325,10 @@ void ED_region_header_layout(const bContext *C, ARegion *region) maxco += UI_HEADER_OFFSET; } - /* always as last */ + /* Always as last. */ UI_view2d_totRect_set(®ion->v2d, maxco, region->winy); - /* restore view matrix */ + /* Restore view matrix. */ UI_view2d_view_restore(C); } @@ -3672,7 +3672,7 @@ static void region_visible_rect_calc(ARegion *region, rcti *rect) /* Skip floating. */ } else { - BLI_assert(!"Region overlap with unknown alignment"); + BLI_assert_msg(0, "Region overlap with unknown alignment"); } } } diff --git a/source/blender/editors/screen/area_query.c b/source/blender/editors/screen/area_query.c index d569e56e11b..fd4f3964398 100644 --- a/source/blender/editors/screen/area_query.c +++ b/source/blender/editors/screen/area_query.c @@ -88,7 +88,7 @@ bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_re r_region_gutter->xmin = r_region_gutter->xmax - category_tabs_width; } else { - BLI_assert(!"Unsupported alignment"); + BLI_assert_msg(0, "Unsupported alignment"); } return true; } diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index e366760a55d..f651fd4fb61 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -126,7 +126,7 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, components = 1; } else { - BLI_assert(!"Incompatible format passed to immDrawPixels"); + BLI_assert_msg(0, "Incompatible format passed to immDrawPixels"); return; } @@ -426,7 +426,7 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf, format = GPU_RGBA16F; } else { - BLI_assert(!"Incompatible number of channels for GLSL display"); + BLI_assert_msg(0, "Incompatible number of channels for GLSL display"); } if (format != 0) { diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 627a67358f2..d50962a56a9 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -874,7 +874,7 @@ static eContextResult screen_ctx_editable_gpencil_strokes(const bContext *C, } } } - /* if not multiedit out of loop */ + /* If not multi-edit out of loop. */ if (!is_multiedit) { break; } @@ -896,11 +896,11 @@ static eContextResult screen_ctx_active_operator(const bContext *C, bContextData /* do nothing */ } else { - /* note, this checks poll, could be a problem, but this also + /* NOTE: this checks poll, could be a problem, but this also * happens for the toolbar */ op = WM_operator_last_redo(C); } - /* TODO, get the operator from popup's */ + /* TODO: get the operator from popup's. */ if (op && op->ptr) { CTX_data_pointer_set(result, NULL, &RNA_Operator, op); diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c index 2c45524ef94..dca464bbf22 100644 --- a/source/blender/editors/screen/screen_draw.c +++ b/source/blender/editors/screen/screen_draw.c @@ -244,7 +244,7 @@ void screen_draw_join_highlight(ScrArea *sa1, ScrArea *sa2) return; } - /* Rect of the combined areas.*/ + /* Rect of the combined areas. */ const bool vertical = SCREEN_DIR_IS_VERTICAL(dir); const rctf combined = { .xmin = vertical ? MAX2(sa1->totrct.xmin, sa2->totrct.xmin) : diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 6fb5f33d836..2a81fcfde8f 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -68,7 +68,7 @@ static ScrArea *screen_addarea_ex(ScrAreaMap *area_map, ScrVert *top_left, ScrVert *top_right, ScrVert *bottom_right, - short spacetype) + const eSpace_Type space_type) { ScrArea *area = MEM_callocN(sizeof(ScrArea), "addscrarea"); @@ -76,7 +76,7 @@ static ScrArea *screen_addarea_ex(ScrAreaMap *area_map, area->v2 = top_left; area->v3 = top_right; area->v4 = bottom_right; - area->spacetype = spacetype; + area->spacetype = space_type; BLI_addtail(&area_map->areabase, area); @@ -87,10 +87,10 @@ static ScrArea *screen_addarea(bScreen *screen, ScrVert *left_top, ScrVert *right_top, ScrVert *right_bottom, - short spacetype) + const eSpace_Type space_type) { return screen_addarea_ex( - AREAMAP_FROM_SCREEN(screen), left_bottom, left_top, right_top, right_bottom, spacetype); + AREAMAP_FROM_SCREEN(screen), left_bottom, left_top, right_top, right_bottom, space_type); } static void screen_delarea(bContext *C, bScreen *screen, ScrArea *area) @@ -125,9 +125,9 @@ ScrArea *area_split(const wmWindow *win, return NULL; } - /* note regarding (fac > 0.5f) checks below. + /* NOTE(campbell): regarding (fac > 0.5f) checks below. * normally it shouldn't matter which is used since the copy should match the original - * however with viewport rendering and python console this isn't the case. - campbell */ + * however with viewport rendering and python console this isn't the case. */ if (dir_axis == SCREEN_AXIS_H) { /* new vertices */ @@ -972,7 +972,7 @@ int ED_screen_area_active(const bContext *C) */ static ScrArea *screen_area_create_with_geometry(ScrAreaMap *area_map, const rcti *rect, - short spacetype) + eSpace_Type space_type) { ScrVert *bottom_left = screen_geom_vertex_add_ex(area_map, rect->xmin, rect->ymin); ScrVert *top_left = screen_geom_vertex_add_ex(area_map, rect->xmin, rect->ymax); @@ -984,7 +984,7 @@ static ScrArea *screen_area_create_with_geometry(ScrAreaMap *area_map, screen_geom_edge_add_ex(area_map, top_right, bottom_right); screen_geom_edge_add_ex(area_map, bottom_right, bottom_left); - return screen_addarea_ex(area_map, bottom_left, top_left, top_right, bottom_right, spacetype); + return screen_addarea_ex(area_map, bottom_left, top_left, top_right, bottom_right, space_type); } static void screen_area_set_geometry_rect(ScrArea *area, const rcti *rect) @@ -1001,7 +1001,7 @@ static void screen_area_set_geometry_rect(ScrArea *area, const rcti *rect) static void screen_global_area_refresh(wmWindow *win, bScreen *screen, - eSpace_Type space_type, + const eSpace_Type space_type, GlobalAreaAlign align, const rcti *rect, const short height_cur, @@ -1275,11 +1275,14 @@ void ED_screen_scene_change(bContext *C, wmWindow *win, Scene *scene) ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *area, int type) { + bScreen *newscreen = NULL; ScrArea *newsa = NULL; SpaceLink *newsl; if (!area || area->full == NULL) { - newsa = ED_screen_state_maximized_create(C); + newscreen = ED_screen_state_maximized_create(C); + newsa = newscreen->areabase.first; + BLI_assert(newsa->spacetype == SPACE_EMPTY); } if (!newsa) { @@ -1296,6 +1299,10 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *area, int type) ED_area_newspace(C, newsa, type, (newsl && newsl->link_flag & SPACE_FLAG_TYPE_TEMPORARY)); + if (newscreen) { + ED_screen_change(C, newscreen); + } + return newsa; } @@ -1361,6 +1368,10 @@ 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 empty * area, when toggling back it can be swapped back again. * \return The newly created screen with the non-normal area. + * + * \note The caller must run #ED_screen_change this is not done in this function + * as it would attempt to initialize areas that don't yet have a space-type assigned + * (converting them to 3D view without creating the space-data). */ static bScreen *screen_state_to_nonnormal(bContext *C, wmWindow *win, @@ -1429,7 +1440,6 @@ static bScreen *screen_state_to_nonnormal(bContext *C, } newa->full = oldscreen; - ED_screen_change(C, screen); ED_area_tag_refresh(newa); return screen; @@ -1442,10 +1452,9 @@ static bScreen *screen_state_to_nonnormal(bContext *C, * Use this to just create a new maximized screen/area, rather than maximizing an existing one. * Otherwise, maximize with #ED_screen_state_toggle(). */ -ScrArea *ED_screen_state_maximized_create(bContext *C) +bScreen *ED_screen_state_maximized_create(bContext *C) { - bScreen *screen = screen_state_to_nonnormal(C, CTX_wm_window(C), NULL, SCREENMAXIMIZED); - return screen->areabase.first; + return screen_state_to_nonnormal(C, CTX_wm_window(C), NULL, SCREENMAXIMIZED); } /** @@ -1548,11 +1557,21 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const } screen = screen_state_to_nonnormal(C, win, toggle_area, state); + + ED_screen_change(C, screen); } BLI_assert(CTX_wm_screen(C) == screen); BLI_assert(CTX_wm_area(C) == NULL); /* May have been freed. */ + /* Setting the area is only needed for Python scripts that call + * operators in succession before returning to the main event loop. + * Without this, scripts can't run any operators that require + * an area after toggling full-screen for example (see: T89526). + * NOTE: an old comment stated this was "bad code", + * however it doesn't cause problems so leave as-is. */ + CTX_wm_area_set(C, screen->areabase.first); + return screen->areabase.first; } @@ -1585,6 +1604,7 @@ ScrArea *ED_screen_temp_space_open(bContext *C, sizex, sizey, (int)space_type, + false, dialog, true, WIN_ALIGN_LOCATION_CENTER)) { @@ -1663,7 +1683,7 @@ void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable) sad->region = CTX_wm_region(C); /* If start-frame is larger than current frame, we put current-frame on start-frame. - * note: first frame then is not drawn! (ton) */ + * NOTE(ton): first frame then is not drawn! */ if (PRVRANGEON) { if (scene->r.psfra > scene->r.cfra) { sad->sfra = scene->r.cfra; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 6b8d4e73f12..ffeaf514642 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -279,6 +279,11 @@ bool ED_operator_file_active(bContext *C) return ed_spacetype_test(C, SPACE_FILE); } +bool ED_operator_spreadsheet_active(bContext *C) +{ + return ed_spacetype_test(C, SPACE_SPREADSHEET); +} + bool ED_operator_action_active(bContext *C) { return ed_spacetype_test(C, SPACE_ACTION); @@ -358,9 +363,24 @@ bool ED_operator_object_active(bContext *C) return ((ob != NULL) && !ed_object_hidden(ob)); } -bool ED_operator_object_active_editable_ex(bContext *UNUSED(C), const Object *ob) +bool ED_operator_object_active_editable_ex(bContext *C, const Object *ob) { - return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob)); + if (ob == NULL) { + CTX_wm_operator_poll_msg_set(C, "Context missing active object"); + return false; + } + + if (ID_IS_LINKED(ob)) { + CTX_wm_operator_poll_msg_set(C, "Cannot edit library linked object"); + return false; + } + + if (ed_object_hidden(ob)) { + CTX_wm_operator_poll_msg_set(C, "Cannot edit hidden obect"); + return false; + } + + return true; } bool ED_operator_object_active_editable(bContext *C) @@ -444,28 +464,48 @@ bool ED_operator_editarmature(bContext *C) } /** - * \brief check for pose mode (no mixed modes) + * Check for pose mode (no mixed modes). * - * We want to enable most pose operations in weight paint mode, - * when it comes to transforming bones, but managing bones layers/groups - * can be left for pose mode only. (not weight paint mode) + * We want to enable most pose operations in weight paint mode, when it comes to transforming + * bones, but managing bones layers/groups and their constraints can be left for pose mode only + * (not weight paint mode). */ -bool ED_operator_posemode_exclusive(bContext *C) +static bool ed_operator_posemode_exclusive_ex(bContext *C, Object *obact) { - Object *obact = CTX_data_active_object(C); - - if (obact && !(obact->mode & OB_MODE_EDIT)) { - Object *obpose = BKE_object_pose_armature_get(obact); - if (obpose != NULL) { - if (obact == obpose) { - return true; - } + if (obact != NULL && !(obact->mode & OB_MODE_EDIT)) { + if (obact == BKE_object_pose_armature_get(obact)) { + return true; } } + CTX_wm_operator_poll_msg_set(C, "No object, or not exclusively in pose mode"); return false; } +bool ED_operator_posemode_exclusive(bContext *C) +{ + Object *obact = ED_object_active_context(C); + + return ed_operator_posemode_exclusive_ex(C, obact); +} + +/** Object must be editable, fully local (i.e. not an override), and exclusively in Pose mode. */ +bool ED_operator_object_active_local_editable_posemode_exclusive(bContext *C) +{ + Object *obact = ED_object_active_context(C); + + if (!ed_operator_posemode_exclusive_ex(C, obact)) { + return false; + } + + if (ID_IS_OVERRIDE_LIBRARY(obact)) { + CTX_wm_operator_poll_msg_set(C, "Object is a local library override"); + return false; + } + + return true; +} + /* allows for pinned pose objects to be used in the object buttons * and the non-active pose object to be used in the 3D view */ bool ED_operator_posemode_context(bContext *C) @@ -1362,6 +1402,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event) area->winx, area->winy, SPACE_EMPTY, + false, true, false, WIN_ALIGN_ABSOLUTE); @@ -2076,16 +2117,16 @@ static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *area, ScrArea *sb) ScrVert *sbv3 = sb->v3; ScrVert *sbv4 = sb->v4; - if (sav1 == sbv4 && sav2 == sbv3) { /* area to right of sb = W */ + if (sav1 == sbv4 && sav2 == sbv3) { /* Area to right of sb = W. */ return BKE_screen_find_edge(screen, sav1, sav2); } - if (sav2 == sbv1 && sav3 == sbv4) { /* area to bottom of sb = N */ + if (sav2 == sbv1 && sav3 == sbv4) { /* Area to bottom of sb = N. */ return BKE_screen_find_edge(screen, sav2, sav3); } - if (sav3 == sbv2 && sav4 == sbv1) { /* area to left of sb = E */ + if (sav3 == sbv2 && sav4 == sbv1) { /* Area to left of sb = E. */ return BKE_screen_find_edge(screen, sav3, sav4); } - if (sav1 == sbv2 && sav4 == sbv3) { /* area on top of sb = S*/ + if (sav1 == sbv2 && sav4 == sbv3) { /* Area on top of sb = S. */ return BKE_screen_find_edge(screen, sav1, sav4); } @@ -2751,9 +2792,9 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) } CLAMP(rmd->region->sizey, 0, rmd->maxsize); - /* note, 'UI_UNIT_Y/4' means you need to drag the footer and execute region + /* NOTE: `UI_UNIT_Y / 4` means you need to drag the footer and execute region * almost all the way down for it to become hidden, this is done - * otherwise its too easy to do this by accident */ + * otherwise its too easy to do this by accident. */ if (size_no_snap < (UI_UNIT_Y / 4) / aspect) { rmd->region->sizey = rmd->origval; if (!(rmd->region->flag & RGN_FLAG_HIDDEN)) { @@ -4446,9 +4487,17 @@ static void screen_animation_region_tag_redraw(ScrArea *area, /* No need to do a full redraw as the current frame indicator is only updated. * We do need to redraw when this area is in full screen as no other areas * will be tagged for redrawing. */ - if ((region->regiontype == RGN_TYPE_WINDOW) && - (ELEM(area->spacetype, SPACE_GRAPH, SPACE_NLA, SPACE_ACTION)) && !area->full) { - return; + if (region->regiontype == RGN_TYPE_WINDOW && !area->full) { + if (ELEM(area->spacetype, SPACE_GRAPH, SPACE_NLA, SPACE_ACTION)) { + return; + } + + if (area->spacetype == SPACE_SEQ) { + const SpaceSeq *sseq = area->spacedata.first; + if (!ED_space_sequencer_has_playback_animation(sseq, scene)) { + return; + } + } } ED_region_tag_redraw(region); } @@ -4948,6 +4997,7 @@ static int userpref_show_exec(bContext *C, wmOperator *op) sizey, SPACE_USERPREF, false, + false, true, WIN_ALIGN_LOCATION_CENTER) != NULL) { /* The header only contains the editor switcher and looks empty. @@ -5014,6 +5064,7 @@ static int drivers_editor_show_exec(bContext *C, wmOperator *op) sizey, SPACE_GRAPH, false, + false, true, WIN_ALIGN_LOCATION_CENTER) != NULL) { ED_drivers_editor_init(C, CTX_wm_area(C)); @@ -5082,6 +5133,7 @@ static int info_log_show_exec(bContext *C, wmOperator *op) sizey, SPACE_INFO, false, + false, true, WIN_ALIGN_LOCATION_CENTER) != NULL) { return OPERATOR_FINISHED; @@ -5167,7 +5219,7 @@ static void SCREEN_OT_delete(wmOperatorType *ot) /* -------------------------------------------------------------------- */ /** \name Region Alpha Blending Operator * - * Implementation note: a disappearing region needs at least 1 last draw with + * Implementation NOTE: a disappearing region needs at least 1 last draw with * 100% back-buffer texture over it - then triple buffer will clear it entirely. * This because flag #RGN_FLAG_HIDDEN is set in end - region doesn't draw at all then. * @@ -5546,13 +5598,13 @@ static void SCREEN_OT_workspace_cycle(wmOperatorType *ot) /* called in spacetypes.c */ void ED_operatortypes_screen(void) { - /* generic UI stuff */ + /* Generic UI stuff. */ WM_operatortype_append(SCREEN_OT_actionzone); WM_operatortype_append(SCREEN_OT_repeat_last); WM_operatortype_append(SCREEN_OT_repeat_history); WM_operatortype_append(SCREEN_OT_redo_last); - /* screen tools */ + /* Screen tools. */ WM_operatortype_append(SCREEN_OT_area_move); WM_operatortype_append(SCREEN_OT_area_split); WM_operatortype_append(SCREEN_OT_area_join); @@ -5579,7 +5631,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(SCREEN_OT_space_context_cycle); WM_operatortype_append(SCREEN_OT_workspace_cycle); - /*frame changes*/ + /* Frame changes. */ WM_operatortype_append(SCREEN_OT_frame_offset); WM_operatortype_append(SCREEN_OT_frame_jump); WM_operatortype_append(SCREEN_OT_keyframe_jump); @@ -5589,7 +5641,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(SCREEN_OT_animation_play); WM_operatortype_append(SCREEN_OT_animation_cancel); - /* new/delete */ + /* New/delete. */ WM_operatortype_append(SCREEN_OT_new); WM_operatortype_append(SCREEN_OT_delete); } diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 3829aeebbeb..ab2b2f4b16b 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -940,7 +940,7 @@ static void paint_draw_curve_cursor(Brush *brush, ViewContext *vc) int j; PaintCurvePoint *cp_next = cp + 1; float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2]; - /* Use color coding to distinguish handles vs curve segments. */ + /* Use color coding to distinguish handles vs curve segments. */ draw_bezier_handle_lines(pos, selec_col, &cp->bez); draw_tri_point(pos, selec_col, pivot_col, &cp->bez.vec[1][0], 10.0f, cp->bez.f2); draw_rect_point( @@ -1039,7 +1039,7 @@ static void cursor_draw_point_screen_space(const uint gpuattr, float translation_vertex_cursor[3], location[3]; copy_v3_v3(location, true_location); mul_m4_v3(obmat, location); - ED_view3d_project(region, location, translation_vertex_cursor); + ED_view3d_project_v3(region, location, translation_vertex_cursor); /* Do not draw points behind the view. Z [near, far] is mapped to [-1, 1]. */ if (translation_vertex_cursor[2] <= 1.0f) { imm_draw_circle_fill_3d( diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 324fd5d3075..39d776e0054 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -176,7 +176,7 @@ void imapaint_image_update( ibuf->userflags |= IB_MIPMAP_INVALID; } - /* todo: should set_tpage create ->rect? */ + /* TODO: should set_tpage create ->rect? */ if (texpaint || (sima && sima->lock)) { int w = imapaintpartial.x2 - imapaintpartial.x1; int h = imapaintpartial.y2 - imapaintpartial.y1; @@ -681,7 +681,7 @@ static bool paint_stroke_test_start(bContext *C, wmOperator *op, const float mou { PaintOperation *pop; - /* TODO Should avoid putting this here. Instead, last position should be requested + /* TODO: Should avoid putting this here. Instead, last position should be requested * from stroke system. */ if (!(pop = texture_paint_init(C, op, mouse))) { diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index f0923cf3d28..ffa6f6ac962 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -745,7 +745,7 @@ static void brush_painter_2d_tex_mapping(ImagePaintState *s, mapping->ymax = (ymax - ymin) / (float)diameter; } else if (mapmode == MTEX_MAP_MODE_3D) { - /* 3D mapping, just mapping to canvas 0..1 */ + /* 3D mapping, just mapping to canvas 0..1. */ mapping->xmin = 2.0f * (ipos[0] * invw - 0.5f); mapping->ymin = 2.0f * (ipos[1] * invh - 0.5f); mapping->xmax = 2.0f * invw; @@ -1248,7 +1248,7 @@ static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos, short paint static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, const int *pos) { - /* note: allocImbuf returns zero'd memory, so regions outside image will + /* NOTE: allocImbuf returns zero'd memory, so regions outside image will * have zero alpha, and hence not be blended onto the image */ int w = ibufb->x, h = ibufb->y, destx = 0, desty = 0, srcx = pos[0], srcy = pos[1]; ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 530689ce049..bd05d309421 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -122,7 +122,7 @@ BLI_INLINE uchar f_to_char(const float val) * * When 3 - a brush should have ~9 buckets under it at once * ...this helps for threading while painting as well as - * avoiding initializing pixels that wont touch the brush */ + * avoiding initializing pixels that won't touch the brush */ #define PROJ_BUCKET_BRUSH_DIV 4 #define PROJ_BUCKET_RECT_MIN 4 @@ -300,7 +300,7 @@ typedef struct ProjPaintState { /** Calculated from screenMin & screenMax. */ float screen_width; float screen_height; - /** from the carea or from the projection render. */ + /** From the area or from the projection render. */ int winx, winy; /* options for projection painting */ @@ -391,7 +391,7 @@ typedef struct ProjPaintState { float *cavities; #ifndef PROJ_DEBUG_NOSEAMBLEED - /** store info about faces, if they are initialized etc*/ + /** Store info about faces, if they are initialized etc. */ ushort *faceSeamFlags; /** save the winding of the face in uv space, * helps as an extra validation step for seam detection. */ @@ -576,7 +576,9 @@ static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_i return slot ? slot->ima : ps->clone_ima; } -/* fast projection bucket array lookup, use the safe version for bound checking */ +/** + * 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 screen-space 2D coords we could simple do... @@ -928,7 +930,7 @@ static bool project_bucket_point_occluded(const ProjPaintState *ps, } if (isect_ret >= 1) { - /* TODO - we may want to cache the first hit, + /* TODO: we may want to cache the first hit, * it is not possible to swap the face order in the list anymore */ return true; } @@ -957,7 +959,7 @@ static int line_isect_y(const float p1[2], const float p2[2], const float y_leve return ISECT_TRUE_P2; } - /** yuck, horizontal line, we cant do much here. */ + /** yuck, horizontal line, we can't do much here. */ y_diff = fabsf(p1[1] - p2[1]); if (y_diff < 0.000001f) { @@ -991,10 +993,10 @@ static int line_isect_x(const float p1[2], const float p2[2], const float x_leve return ISECT_TRUE_P2; } - /* yuck, horizontal line, we cant do much here */ + /* yuck, horizontal line, we can't do much here */ x_diff = fabsf(p1[0] - p2[0]); - /* yuck, vertical line, we cant do much here */ + /* yuck, vertical line, we can't do much here */ if (x_diff < 0.000001f) { *y_isect = (p1[0] + p2[0]) * 0.5f; return ISECT_TRUE; @@ -1071,7 +1073,7 @@ static bool pixel_bounds_uv(const float uv_quad[4][2], bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1; bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1; - /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/ + // printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]); /* face uses no UV area when quantized to pixels? */ return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? false : true; @@ -1101,7 +1103,7 @@ static bool pixel_bounds_array( bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1; bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1; - /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/ + // printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]); /* face uses no UV area when quantized to pixels? */ return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? false : true; @@ -1659,7 +1661,7 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps, const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index]; const float *lt_other_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt_other)}; - /* BKE_image_acquire_ibuf - TODO - this may be slow */ + /* #BKE_image_acquire_ibuf - TODO: this may be slow. */ uchar rgba_ub[4]; float rgba_f[4]; @@ -1766,13 +1768,13 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps, angle_cos = dot_v3v3(viewDirPersp, no); } - /* If backface culling is disabled, allow painting on back faces. */ + /* If back-face culling is disabled, allow painting on back faces. */ if (!ps->do_backfacecull) { angle_cos = fabsf(angle_cos); } if (angle_cos <= ps->normal_angle__cos) { - /* outsize the normal limit*/ + /* Outsize the normal limit. */ return 0.0f; } if (angle_cos < ps->normal_angle_inner__cos) { @@ -1876,7 +1878,7 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps, int x_tile, y_tile; int x_round, y_round; int tile_offset; - /* volatile is important here to ensure pending check is not optimized away by compiler*/ + /* Volatile is important here to ensure pending check is not optimized away by compiler. */ volatile int tile_index; ProjPaintImage *projima = tinf->pjima; @@ -1957,7 +1959,7 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps, const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other)}; - /* BKE_image_acquire_ibuf - TODO - this may be slow */ + /* #BKE_image_acquire_ibuf - TODO: this may be slow. */ if (ibuf->rect_float) { if (ibuf_other->rect_float) { /* from float to float */ @@ -2050,7 +2052,7 @@ static bool line_clip_rect2f(const rctf *cliprect, float l2_clip[2]) { /* first account for horizontal, then vertical lines */ - /* horiz */ + /* Horizontal. */ if (fabsf(l1[1] - l2[1]) < PROJ_PIXEL_TOLERANCE) { /* is the line out of range on its Y axis? */ if (l1[1] < rect->ymin || l1[1] > rect->ymax) { @@ -2061,7 +2063,7 @@ static bool line_clip_rect2f(const rctf *cliprect, return false; } - /* this is a single point (or close to)*/ + /* This is a single point (or close to). */ if (fabsf(l1[0] - l2[0]) < PROJ_PIXEL_TOLERANCE) { if (BLI_rctf_isect_pt_v(rect, l1)) { copy_v2_v2(l1_clip, l1); @@ -2088,7 +2090,7 @@ static bool line_clip_rect2f(const rctf *cliprect, return false; } - /* this is a single point (or close to)*/ + /* This is a single point (or close to). */ if (fabsf(l1[1] - l2[1]) < PROJ_PIXEL_TOLERANCE) { if (BLI_rctf_isect_pt_v(rect, l1)) { copy_v2_v2(l1_clip, l1); @@ -2600,8 +2602,8 @@ static void project_bucket_clip_face(const bool is_ortho, return; } - /* get the UV space bounding box */ - /* use IsectPT2Df_limit here so we catch points are are touching the tri edge + /* Get the UV space bounding box. */ + /* Use #IsectPT2Df_limit here so we catch points are touching the triangles edge * (or a small fraction over) */ bucket_bounds_ss[0][0] = bucket_bounds->xmax; bucket_bounds_ss[0][1] = bucket_bounds->ymin; @@ -2676,7 +2678,7 @@ static void project_bucket_clip_face(const bool is_ortho, /* calc center */ float cent[2] = {0.0f, 0.0f}; - /*float up[2] = {0.0f, 1.0f};*/ + // float up[2] = {0.0f, 1.0f}; bool doubles; (*tot) = 0; @@ -2969,7 +2971,7 @@ static void project_paint_face_init(const ProjPaintState *ps, ImBuf *ibuf, ImBuf **tmpibuf) { - /* Projection vars, to get the 3D locations into screen space */ + /* Projection vars, to get the 3D locations into screen space. */ MemArena *arena = ps->arena_mt[thread_index]; LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index; LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index]; @@ -3011,7 +3013,7 @@ static void project_paint_face_init(const ProjPaintState *ps, rcti bounds_px; /* Variables for getting UV-space bounds. */ - /* bucket bounds in UV space so we can init pixels only for this face, */ + /* Bucket bounds in UV space so we can init pixels only for this face. */ float lt_uv_pxoffset[3][2]; float xhalfpx, yhalfpx; const float ibuf_xf = (float)ibuf->x, ibuf_yf = (float)ibuf->y; @@ -3063,7 +3065,7 @@ static void project_paint_face_init(const ProjPaintState *ps, v2coSS = ps->screenCoords[lt_vtri[1]]; v3coSS = ps->screenCoords[lt_vtri[2]]; - /* This function gives is a concave polyline in UV space from the clipped tri*/ + /* This function gives is a concave polyline in UV space from the clipped tri. */ project_bucket_clip_face(is_ortho, is_flip_object, clip_rect, @@ -3152,13 +3154,13 @@ static void project_paint_face_init(const ProjPaintState *ps, } //#if 0 else if (has_x_isect) { - /* assuming the face is not a bow-tie - we know we cant intersect again on the X */ + /* assuming the face is not a bow-tie - we know we can't intersect again on the X */ break; } //#endif } -#if 0 /* TODO - investigate why this doesn't work sometimes! it should! */ +#if 0 /* TODO: investigate why this doesn't work sometimes! it should! */ /* no intersection for this entire row, * after some intersection above means we can quit now */ if (has_x_isect == 0 && has_isect) { @@ -3239,7 +3241,7 @@ static void project_paint_face_init(const ProjPaintState *ps, uv_image_outset(ps, lt_uv_pxoffset, lt_puv, tri_index, ibuf->x, ibuf->y); } - /* ps->loopSeamUVs cant be modified when threading, now this is done we can unlock. */ + /* ps->loopSeamUVs can't be modified when threading, now this is done we can unlock. */ if (threaded) { /* Other threads could be modifying these vars */ BLI_thread_unlock(LOCK_CUSTOM1); @@ -3292,7 +3294,7 @@ static void project_paint_face_init(const ProjPaintState *ps, interp_v2_v2v2(seam_subsection[3], seam_uvs[0], seam_uvs[1], fac1); /* if the bucket_clip_edges values Z values was kept we could avoid this - * Inset needs to be added so occlusion tests wont hit adjacent faces */ + * Inset needs to be added so occlusion tests won't hit adjacent faces */ interp_v3_v3v3(edge_verts_inset_clip[0], insetCos[fidx1], insetCos[fidx2], fac1); interp_v3_v3v3(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2); @@ -3399,7 +3401,7 @@ static void project_paint_face_init(const ProjPaintState *ps, } } -# if 0 /* TODO - investigate why this doesn't work sometimes! it should! */ +# if 0 /* TODO: investigate why this doesn't work sometimes! it should! */ /* no intersection for this entire row, * after some intersection above means we can quit now */ if (has_x_isect == 0 && has_isect) { @@ -3430,8 +3432,8 @@ static void project_paint_bucket_bounds(const ProjPaintState *ps, { /* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */ - /* XXX: the offset of 0.5 is always truncated to zero and the offset of 1.5f - * is always truncated to 1, is this really correct?? - jwilkins */ + /* XXX(jwilkins ): the offset of 0.5 is always truncated to zero and the offset of 1.5f + * is always truncated to 1, is this really correct? */ /* these offsets of 0.5 and 1.5 seem odd but they are correct */ bucketMin[0] = @@ -3551,18 +3553,18 @@ static void project_bucket_init(const ProjPaintState *ps, ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT; } -/* We want to know if a bucket and a face overlap in screen-space +/* We want to know if a bucket and a face overlap in screen-space. * - * Note, if this ever returns false positives its not that bad, since a face in the bounding area + * NOTE: if this ever returns false positives its not that bad, since a face in the bounding area * will have its pixels calculated when it might not be needed later, (at the moment at least) - * obviously it shouldn't have bugs though */ + * obviously it shouldn't have bugs though. */ static bool project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int bucket_y, const MLoopTri *lt) { - /* TODO - replace this with a trickier method that uses side-of-line for all + /* TODO: replace this with a trickier method that uses side-of-line for all * #ProjPaintState.screenCoords edges against the closest bucket corner. */ const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)}; rctf bucket_bounds; @@ -3609,7 +3611,7 @@ static bool project_bucket_face_isect(ProjPaintState *ps, } /* Add faces to the bucket but don't initialize its pixels - * TODO - when painting occluded, sort the faces on their min-Z + * TODO: when painting occluded, sort the faces on their min-Z * and only add faces that faces that are not occluded */ static void project_paint_delayed_face_init(ProjPaintState *ps, const MLoopTri *lt, @@ -3648,7 +3650,7 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, has_x_isect = has_isect = 1; } else if (has_x_isect) { - /* assuming the face is not a bow-tie - we know we cant intersect again on the X */ + /* assuming the face is not a bow-tie - we know we can't intersect again on the X */ break; } } @@ -3822,7 +3824,7 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo); } else { - /* TODO - deal with cases where 1 side of a face goes behind the view ? + /* TODO: deal with cases where 1 side of a face goes behind the view ? * * After some research this is actually very tricky, only option is to * clip the derived mesh before painting, which is a Pain */ @@ -4356,7 +4358,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, #endif // PROJ_DEBUG_WINCLIP - /* backface culls individual triangles but mask normal will use polygon */ + /* Back-face culls individual triangles but mask normal will use polygon. */ if (ps->do_backfacecull) { if (ps->do_mask_normal) { if (prev_poly != lt->poly) { @@ -4428,7 +4430,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, } } - /* build an array of images we use*/ + /* Build an array of images we use. */ if (ps->is_shared_user == false) { project_paint_build_proj_ima(ps, arena, &used_images); } @@ -4516,8 +4518,8 @@ static void project_paint_begin(const bContext *C, reset_threads = true; } - /* really high values could cause problems since it has to allocate a few - * (ps->buckets_x*ps->buckets_y) sized arrays */ + /* Really high values could cause problems since it has to allocate a few + * `(ps->buckets_x * ps->buckets_y)` sized arrays. */ CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX); CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX); @@ -4694,7 +4696,7 @@ static bool project_image_refresh_tagged(ProjPaintState *ps) /* look over each bound cell */ for (i = 0; i < PROJ_BOUNDBOX_SQUARED; i++) { pr = &(projIma->partRedrawRect[i]); - if (pr->x2 != -1) { /* TODO - use 'enabled' ? */ + if (pr->x2 != -1) { /* TODO: use 'enabled' ? */ set_imapaintpartial(pr); imapaint_image_update(NULL, projIma->ima, projIma->ibuf, &projIma->iuser, true); redraw = 1; @@ -4768,7 +4770,7 @@ static bool project_bucket_iter_next(ProjPaintState *ps, BLI_assert(bucket_y >= ps->bucketMin[1] && bucket_y < ps->bucketMax[1]); if (bucket_x >= ps->bucketMin[0] && bucket_x < ps->bucketMax[0]) { - /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/ + /* Use bucket_bounds for #project_bucket_isect_circle and #project_bucket_init. */ project_bucket_bounds(ps, bucket_x, bucket_y, bucket_bounds); if ((ps->source != PROJ_SRC_VIEW) || @@ -5354,7 +5356,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v dist_sq = len_squared_v2v2(projPixel->projCoSS, pos); - /*if (dist < radius) {*/ /* correct but uses a sqrtf */ + /* Faster alternative to `dist < radius` without a #sqrtf. */ if (dist_sq <= brush_radius_sq) { dist = sqrtf(dist_sq); @@ -5364,7 +5366,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v float texrgb[3]; float mask; - /* Extra mask for normal, layer stencil, .. */ + /* Extra mask for normal, layer stencil, etc. */ float custom_mask = ((float)projPixel->mask) * (1.0f / 65535.0f); /* Mask texture. */ @@ -5391,7 +5393,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v samplecos[2] = 0.0f; } - /* note, for clone and smear, + /* NOTE: for clone and smear, * we only use the alpha, could be a special function */ BKE_brush_sample_tex_3d(ps->scene, brush, samplecos, texrgba, thread_index, pool); @@ -5447,7 +5449,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v } /* end copy */ - /* validate undo tile, since we will modify t*/ + /* Validate undo tile, since we will modify it. */ *projPixel->valid = true; last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index; @@ -5514,7 +5516,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v if (tool == PAINT_TOOL_SMEAR) { - for (node = smearPixels; node; node = node->next) { /* this wont run for a float image */ + for (node = smearPixels; node; node = node->next) { /* this won't run for a float image */ projPixel = node->link; *projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint; if (lock_alpha) { @@ -5534,7 +5536,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v } else if (tool == PAINT_TOOL_SOFTEN) { - for (node = softenPixels; node; node = node->next) { /* this wont run for a float image */ + for (node = softenPixels; node; node = node->next) { /* this won't run for a float image */ projPixel = node->link; *projPixel->pixel.uint_pt = projPixel->newColor.uint; if (lock_alpha) { @@ -5812,7 +5814,7 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int ps->is_maskbrush = (brush->mask_mtex.tex) ? true : false; } else { - /* brush may be NULL*/ + /* Brush may be NULL. */ ps->do_masking = false; ps->is_texbrush = false; ps->is_maskbrush = false; @@ -6468,6 +6470,8 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain, bool is_data) alpha = RNA_boolean_get(op->ptr, "alpha"); RNA_string_get(op->ptr, "name", imagename); } + + /* TODO(lukas): Add option for tiled image. */ ima = BKE_image_add_generated(bmain, width, height, @@ -6478,7 +6482,7 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain, bool is_data) color, false, is_data, - false); /* TODO(lukas): Add option */ + false); return ima; } diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 3f5093222e9..7341d984c91 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -304,7 +304,7 @@ bool paint_curve_poll(struct bContext *C); bool facemask_paint_poll(struct bContext *C); void flip_v3_v3(float out[3], const float in[3], const enum ePaintSymmetryFlags symm); -void flip_qt_qt(float out[3], const float in[3], const enum ePaintSymmetryFlags symm); +void flip_qt_qt(float out[4], const float in[4], const enum ePaintSymmetryFlags symm); /* stroke operator */ typedef enum BrushStrokeMode { diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index b6ae6f8bee7..d968b6cc319 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -293,8 +293,8 @@ typedef struct SculptGestureContext { /* These store the view origin and normal in world space, which is used in some gestures to * generate geometry aligned from the view directly in world space. */ /* World space view origin and normal are not affected by object symmetry when doing symmetry - * passes, so there is no separate variables with the true_ prefix to store their original values - * without symmetry modifications. */ + * passes, so there is no separate variables with the `true_` prefix to store their original + * values without symmetry modifications. */ float world_space_view_origin[3]; float world_space_view_normal[3]; @@ -1239,10 +1239,9 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext) })); const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); - int tottri; BMLoop *(*looptris)[3]; looptris = MEM_malloc_arrayN(looptris_tot, sizeof(*looptris), __func__); - BM_mesh_calc_tessellation_beauty(bm, looptris, &tottri); + BM_mesh_calc_tessellation_beauty(bm, looptris); BMIter iter; int i; @@ -1290,7 +1289,7 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext) break; } BM_mesh_boolean( - bm, looptris, tottri, bm_face_isect_pair, NULL, 2, true, true, false, boolean_mode); + bm, looptris, looptris_tot, bm_face_isect_pair, NULL, 2, true, true, false, boolean_mode); } MEM_freeN(looptris); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index fed89e02e8f..f08771292a8 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -62,7 +62,7 @@ /* Brush operators */ static int brush_add_exec(bContext *C, wmOperator *UNUSED(op)) { - /*int type = RNA_enum_get(op->ptr, "type");*/ + // int type = RNA_enum_get(op->ptr, "type"); Paint *paint = BKE_paint_get_active_from_context(C); Brush *br = BKE_paint_brush(paint); Main *bmain = CTX_data_main(C); @@ -97,7 +97,7 @@ static void BRUSH_OT_add(wmOperatorType *ot) static int brush_add_gpencil_exec(bContext *C, wmOperator *UNUSED(op)) { - /*int type = RNA_enum_get(op->ptr, "type");*/ + // int type = RNA_enum_get(op->ptr, "type"); ToolSettings *ts = CTX_data_tool_settings(C); Paint *paint = &ts->gp_paint->paint; Brush *br = BKE_paint_brush(paint); @@ -1307,7 +1307,7 @@ void ED_operatortypes_paint(void) WM_operatortype_append(BRUSH_OT_stencil_fit_image_aspect); WM_operatortype_append(BRUSH_OT_stencil_reset_transform); - /* note, particle uses a different system, can be added with existing operators in wm.py */ + /* NOTE: particle uses a different system, can be added with existing operators in `wm.py`. */ WM_operatortype_append(PAINT_OT_brush_select); /* image */ @@ -1385,7 +1385,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf) keymap = WM_keymap_ensure(keyconf, "Weight Paint", 0, 0); keymap->poll = weight_paint_mode_poll; - /*Weight paint's Vertex Selection Mode */ + /* Weight paint's Vertex Selection Mode. */ keymap = WM_keymap_ensure(keyconf, "Paint Vertex Selection (Weight, Vertex)", 0, 0); keymap->poll = vert_paint_poll; diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index b093f07226e..de01bc3a474 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -541,7 +541,7 @@ static void paint_brush_stroke_add_step(bContext *C, * It's strange that only texpaint had these guards. */ #if 0 /* special exception here for too high pressure values on first touch in - * windows for some tablets, then we just skip first touch .. */ + * windows for some tablets, then we just skip first touch. */ if (tablet && (pressure >= 0.99f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(pop->s.brush) || @@ -846,7 +846,7 @@ static int paint_space_stroke(bContext *C, while (length > 0.0f) { float spacing = paint_space_stroke_spacing_variable( C, scene, stroke, pressure, dpressure, length); - float mouse[3]; + float mouse[2]; if (length >= spacing) { if (use_scene_spacing) { @@ -856,7 +856,7 @@ static int paint_space_stroke(bContext *C, add_v3_v3v3(final_world_space_position, stroke->last_world_space_position, final_world_space_position); - ED_view3d_project(region, final_world_space_position, mouse); + ED_view3d_project_v2(region, final_world_space_position, mouse); } else { mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing; @@ -1115,7 +1115,7 @@ bool paint_supports_dynamic_tex_coords(Brush *br, ePaintMode mode) #define PAINT_STROKE_MODAL_CANCEL 1 -/* called in paint_ops.c, on each regeneration of keymaps */ +/* Called in paint_ops.c, on each regeneration of key-maps. */ struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf) { static struct EnumPropertyItem modal_items[] = { @@ -1240,7 +1240,7 @@ static void paint_line_strokes_spacing(bContext *C, mul_v3_v3fl(final_world_space_position, d_world_space_position, spacing_final); add_v3_v3v3( final_world_space_position, world_space_position_old, final_world_space_position); - ED_view3d_project(region, final_world_space_position, mouse); + ED_view3d_project_v2(region, final_world_space_position, mouse); } else { mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final; diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 2484f382ed4..709e04d807d 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -752,7 +752,7 @@ static int vert_select_ungrouped_exec(bContext *C, wmOperator *op) Object *ob = CTX_data_active_object(C); Mesh *me = ob->data; - if (BLI_listbase_is_empty(&ob->defbase) || (me->dvert == NULL)) { + if (BLI_listbase_is_empty(&me->vertex_group_names) || (me->dvert == NULL)) { BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index daccc6f228a..9387b84f437 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -179,7 +179,7 @@ static MDeformVert *defweight_prev_init(MDeformVert *dvert_prev, * (without evaluating modifiers) */ static bool vertex_paint_use_fast_update_check(Object *ob) { - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); if (me_eval != NULL) { Mesh *me = BKE_mesh_from_object(ob); @@ -725,7 +725,7 @@ typedef struct WeightPaintInfo { * length of defbase_tot */ const bool *lock_flags; /* boolean array for selected bones, - * length of defbase_tot, cant be const because of how its passed */ + * length of defbase_tot, can't be const because of how it's passed */ const bool *defbase_sel; /* same as WeightPaintData.vgroup_validmap, * only added here for convenience */ @@ -917,7 +917,7 @@ static void do_weight_paint_vertex_single( * 'resist' so you couldn't instantly zero out other weights by painting 1.0 on the active. * * However this gave a problem since applying mirror, then normalize both verts - * the resulting weight wont match on both sides. + * the resulting weight won't match on both sides. * * If this 'resisting', slower normalize is nicer, we could call * do_weight_paint_normalize_all() and only use... @@ -941,13 +941,13 @@ static void do_weight_paint_vertex_single( * - Auto normalize is enabled. * - The group you are painting onto has a L / R version. * - * We want L/R vgroups to have the same weight but this cant be if both are over 0.5, + * We want L/R vgroups to have the same weight but this can't be if both are over 0.5, * We _could_ have special check for that, but this would need its own * normalize function which holds 2 groups from changing at once. * * So! just balance out the 2 weights, it keeps them equal and everything normalized. * - * While it wont hit the desired weight immediately as the user waggles their mouse, + * While it won't hit the desired weight immediately as the user waggles their mouse, * constant painting and re-normalizing will get there. this is also just simpler logic. * - campbell */ dw_mirr->weight = dw->weight = (dw_mirr->weight + dw->weight) * 0.5f; @@ -996,7 +996,7 @@ static void do_weight_paint_vertex_multi( dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->is_normalized); if (curw == 0.0f) { - /* note: no weight to assign to this vertex, could add all groups? */ + /* NOTE: no weight to assign to this vertex, could add all groups? */ return; } @@ -1607,13 +1607,13 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo /* check if we are attempting to paint onto a locked vertex group, * and other options disallow it from doing anything useful */ bDeformGroup *dg; - dg = BLI_findlink(&ob->defbase, vgroup_index.active); + dg = BLI_findlink(&me->vertex_group_names, vgroup_index.active); if (dg->flag & DG_LOCK_WEIGHT) { BKE_report(op->reports, RPT_WARNING, "Active group is locked, aborting"); return false; } if (vgroup_index.mirror != -1) { - dg = BLI_findlink(&ob->defbase, vgroup_index.mirror); + dg = BLI_findlink(&me->vertex_group_names, vgroup_index.mirror); if (dg->flag & DG_LOCK_WEIGHT) { BKE_report(op->reports, RPT_WARNING, "Mirror group is locked, aborting"); return false; @@ -1622,7 +1622,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo } /* check that multipaint groups are unlocked */ - defbase_tot = BLI_listbase_count(&ob->defbase); + defbase_tot = BLI_listbase_count(&me->vertex_group_names); defbase_sel = BKE_object_defgroup_selected_get(ob, defbase_tot, &defbase_tot_sel); if (ts->multipaint && defbase_tot_sel > 1) { @@ -1636,7 +1636,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo for (i = 0; i < defbase_tot; i++) { if (defbase_sel[i]) { - dg = BLI_findlink(&ob->defbase, i); + dg = BLI_findlink(&me->vertex_group_names, i); if (dg->flag & DG_LOCK_WEIGHT) { BKE_report(op->reports, RPT_WARNING, "Multipaint group is locked, aborting"); MEM_freeN(defbase_sel); @@ -2025,7 +2025,7 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, const Brush *brush = data->brush; const StrokeCache *cache = ss->cache; - /* note: normally `BKE_brush_weight_get(scene, brush)` is used, + /* NOTE: normally `BKE_brush_weight_get(scene, brush)` is used, * however in this case we calculate a new weight each time. */ const float paintweight = data->strength; float brush_size_pressure, brush_alpha_value, brush_alpha_pressure; @@ -2046,7 +2046,7 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { /* Test to see if the vertex coordinates are within the spherical brush region. */ if (sculpt_brush_test_sq_fn(&test, vd.co)) { - /* Note: grids are 1:1 with corners (aka loops). + /* NOTE: grids are 1:1 with corners (aka loops). * For multires, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : @@ -2498,7 +2498,7 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) for (psys = ob->particlesystem.first; psys; psys = psys->next) { for (i = 0; i < PSYS_TOT_VG; i++) { - if (psys->vgroup[i] == ob->actdef) { + if (psys->vgroup[i] == BKE_object_defgroup_active_index_get(ob)) { psys->recalc |= ID_RECALC_PSYS_RESET; break; } @@ -2750,11 +2750,11 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f * if not we can skip face map trickiness */ if (vertex_paint_use_fast_update_check(ob)) { vpd->use_fast_update = true; - /* printf("Fast update!\n");*/ + // printf("Fast update!\n"); } else { vpd->use_fast_update = false; - /* printf("No fast update!\n");*/ + // printf("No fast update!\n"); } /* to keep tracked of modified loops for shared vertex color blending */ @@ -2885,7 +2885,7 @@ static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { /* Test to see if the vertex coordinates are within the spherical brush region. */ if (sculpt_brush_test_sq_fn(&test, vd.co)) { - /* Note: Grids are 1:1 with corners (aka loops). + /* NOTE: Grids are 1:1 with corners (aka loops). * For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : @@ -2912,7 +2912,7 @@ static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata, /* If we're painting with a texture, sample the texture color and alpha. */ float tex_alpha = 1.0; if (data->vpd->is_texbrush) { - /* Note: we may want to paint alpha as vertex color alpha. */ + /* NOTE: we may want to paint alpha as vertex color alpha. */ tex_alpha = tex_color_alpha_ubyte( data, data->vpd->vertexcosnos[v_index].co, &color_final); } diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c index 96d22fe4a21..9f023dd6e63 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c @@ -149,7 +149,7 @@ static bool vertex_paint_from_weight(Object *ob) /* TODO: respect selection. */ /* TODO: Do we want to take weights from evaluated mesh instead? 2.7x was not doing it anyway. */ mp = me->mpoly; - vgroup_active = ob->actdef - 1; + vgroup_active = me->vertex_group_active_index - 1; for (int i = 0; i < me->totpoly; i++, mp++) { MLoopCol *lcol = &me->mloopcol[mp->loopstart]; uint j = 0; 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 0fafd3589fe..cb8dc838422 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -183,7 +183,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even ED_view3d_viewcontext_init(C, &vc, depsgraph); me = BKE_mesh_from_object(vc.obact); - if (me && me->dvert && vc.v3d && vc.rv3d && (vc.obact->actdef != 0)) { + if (me && me->dvert && vc.v3d && vc.rv3d && (me->vertex_group_active_index != 0)) { const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; int v_idx_best = -1; uint index; @@ -213,9 +213,9 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even if (v_idx_best != -1) { /* should always be valid */ ToolSettings *ts = vc.scene->toolsettings; Brush *brush = BKE_paint_brush(&ts->wpaint->paint); - const int vgroup_active = vc.obact->actdef - 1; + const int vgroup_active = me->vertex_group_active_index - 1; float vgroup_weight = BKE_defvert_find_weight(&me->dvert[v_idx_best], vgroup_active); - const int defbase_tot = BLI_listbase_count(&vc.obact->defbase); + const int defbase_tot = BLI_listbase_count(&me->vertex_group_names); bool use_lock_relative = ts->wpaint_lock_relative; bool *defbase_locked = NULL, *defbase_unlocked = NULL; @@ -331,8 +331,8 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, ED_view3d_viewcontext_init(C, &vc, depsgraph); me = BKE_mesh_from_object(vc.obact); - if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) { - const int defbase_tot = BLI_listbase_count(&vc.obact->defbase); + if (me && me->dvert && vc.v3d && vc.rv3d && me->vertex_group_names.first) { + const int defbase_tot = BLI_listbase_count(&me->vertex_group_names); const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups"); bool found = false; @@ -372,7 +372,7 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, int totitem = 0; int i = 0; bDeformGroup *dg; - for (dg = vc.obact->defbase.first; dg && i < defbase_tot; i++, dg = dg->next) { + for (dg = me->vertex_group_names.first; dg && i < defbase_tot; i++, dg = dg->next) { if (groups[i]) { item_tmp.identifier = item_tmp.name = dg->name; item_tmp.value = i; @@ -401,14 +401,14 @@ static int weight_sample_group_exec(bContext *C, wmOperator *op) ED_view3d_viewcontext_init(C, &vc, depsgraph); BLI_assert(type + 1 >= 0); - vc.obact->actdef = type + 1; + BKE_object_defgroup_active_index_set(vc.obact, type + 1); DEG_id_tag_update(&vc.obact->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, vc.obact); return OPERATOR_FINISHED; } -/* TODO, we could make this a menu into OBJECT_OT_vertex_group_set_active +/* TODO: we could make this a menu into OBJECT_OT_vertex_group_set_active * rather than its own operator */ void PAINT_OT_weight_sample_group(wmOperatorType *ot) { @@ -458,7 +458,7 @@ static bool weight_paint_set(Object *ob, float paintweight) return false; } - vgroup_active = ob->actdef - 1; + vgroup_active = BKE_object_defgroup_active_index_get(ob) - 1; /* if mirror painting, find the other group */ if (ME_USING_MIRROR_X_VERTEX_GROUPS(me)) { @@ -540,7 +540,7 @@ static int weight_paint_set_exec(bContext *C, wmOperator *op) } if (weight_paint_set(obact, vgroup_weight)) { - ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */ + ED_region_tag_redraw(CTX_wm_region(C)); /* XXX: should redraw all 3D views. */ return OPERATOR_FINISHED; } return OPERATOR_CANCELLED; @@ -791,7 +791,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) wpaint_prev_create( &((WPGradient_vertStoreBase *)gesture->user_data.data)->wpp, me->dvert, me->totvert); - /* on init only, convert face -> vert sel */ + /* On initialization only, convert face -> vert sel. */ if (me->editflag & ME_EDIT_PAINT_FACE_SEL) { BKE_mesh_flush_select_from_polys(me); } @@ -815,7 +815,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) data.sco_start = sco_start; data.sco_end = sco_end; data.sco_line_div = 1.0f / len_v2v2(sco_start, sco_end); - data.def_nr = ob->actdef - 1; + data.def_nr = BKE_object_defgroup_active_index_get(ob) - 1; data.use_select = (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0; data.vert_cache = vert_cache; data.vert_visit = NULL; @@ -863,7 +863,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) } if (scene->toolsettings->auto_normalize) { - const int vgroup_num = BLI_listbase_count(&ob->defbase); + const int vgroup_num = BLI_listbase_count(&me->vertex_group_names); bool *vgroup_validmap = BKE_object_defgroup_validmap_get(ob, vgroup_num); if (vgroup_validmap != NULL) { MDeformVert *dvert = me->dvert; @@ -891,7 +891,7 @@ static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, const wmEve if (ret & OPERATOR_RUNNING_MODAL) { struct ARegion *region = CTX_wm_region(C); if (region->regiontype == RGN_TYPE_WINDOW) { - /* TODO, hardcoded, extend WM_gesture_straightline_ */ + /* TODO: hard-coded, extend `WM_gesture_straightline_*`. */ if (event->type == LEFTMOUSE && event->val == KM_PRESS) { wmGesture *gesture = op->customdata; gesture->is_active = true; diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c index d6a118bbd59..19ffa0c952d 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c @@ -79,8 +79,10 @@ bool ED_wpaint_ensure_data(bContext *C, WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); } + const ListBase *defbase = BKE_object_defgroup_list(ob); + /* this happens on a Bone select, when no vgroup existed yet */ - if (ob->actdef <= 0) { + if (me->vertex_group_active_index <= 0) { Object *modob; if ((modob = BKE_modifiers_is_deformed_by_armature(ob))) { Bone *actbone = ((bArmature *)modob->data)->act_bone; @@ -94,32 +96,33 @@ bool ED_wpaint_ensure_data(bContext *C, DEG_relations_tag_update(CTX_data_main(C)); } else { - int actdef = 1 + BLI_findindex(&ob->defbase, dg); + + int actdef = 1 + BLI_findindex(defbase, dg); BLI_assert(actdef >= 0); - ob->actdef = actdef; + me->vertex_group_active_index = actdef; } } } } } - if (BLI_listbase_is_empty(&ob->defbase)) { + if (BLI_listbase_is_empty(defbase)) { BKE_object_defgroup_add(ob); DEG_relations_tag_update(CTX_data_main(C)); } /* ensure we don't try paint onto an invalid group */ - if (ob->actdef <= 0) { + if (me->vertex_group_active_index <= 0) { BKE_report(reports, RPT_WARNING, "No active vertex group for painting, aborting"); return false; } if (vgroup_index) { - vgroup_index->active = ob->actdef - 1; + vgroup_index->active = me->vertex_group_active_index - 1; } if (flag & WPAINT_ENSURE_MIRROR) { if (ME_USING_MIRROR_X_VERTEX_GROUPS(me)) { - int mirror = ED_wpaint_mirror_vgroup_ensure(ob, ob->actdef - 1); + int mirror = ED_wpaint_mirror_vgroup_ensure(ob, me->vertex_group_active_index - 1); if (vgroup_index) { vgroup_index->mirror = mirror; } @@ -133,7 +136,8 @@ bool ED_wpaint_ensure_data(bContext *C, /* mirror_vgroup is set to -1 when invalid */ int ED_wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active) { - bDeformGroup *defgroup = BLI_findlink(&ob->defbase, vgroup_active); + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *defgroup = BLI_findlink(defbase, vgroup_active); if (defgroup) { int mirrdef; @@ -143,7 +147,7 @@ int ED_wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active) mirrdef = BKE_object_defgroup_name_index(ob, name_flip); if (mirrdef == -1) { if (BKE_object_defgroup_new(ob, name_flip)) { - mirrdef = BLI_listbase_count(&ob->defbase) - 1; + mirrdef = BLI_listbase_count(defbase) - 1; } } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 2e1dd928f96..83388c1aef2 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1146,10 +1146,9 @@ void SCULPT_floodfill_add_active( 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); + v = SCULPT_nearest_vertex_get(sd, ob, location, radius, false); } if (v != -1) { @@ -1854,7 +1853,7 @@ static void flip_v3(float v[3], const ePaintSymmetryFlags symm) flip_v3_v3(v, v, symm); } -static void flip_qt(float quat[3], const ePaintSymmetryFlags symm) +static void flip_qt(float quat[4], const ePaintSymmetryFlags symm) { flip_qt_qt(quat, quat, symm); } @@ -2395,7 +2394,7 @@ static float brush_strength(const Sculpt *sd, case BRUSH_MASK_SMOOTH: return alpha * pressure * feather; } - BLI_assert(!"Not supposed to happen"); + BLI_assert_msg(0, "Not supposed to happen"); return 0.0f; case SCULPT_TOOL_CREASE: @@ -3317,7 +3316,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) mul_v3_v3(offset, ss->cache->scale); mul_v3_fl(offset, bstrength); - /* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise + /* XXX: this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise * initialize before threads so they can do curve mapping. */ BKE_curvemapping_init(brush->curve); @@ -3396,7 +3395,7 @@ static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to mul_v3_v3(offset, ss->cache->scale); mul_v3_fl(offset, bstrength); - /* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise + /* XXX: this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise * initialize before threads so they can do curve mapping. */ BKE_curvemapping_init(brush->curve); @@ -4196,7 +4195,7 @@ void SCULPT_flip_v3_by_symm_area(float v[3], } } -void SCULPT_flip_quat_by_symm_area(float quat[3], +void SCULPT_flip_quat_by_symm_area(float quat[4], const ePaintSymmetryFlags symm, const ePaintSymmetryAreas symmarea, const float pivot[3]) @@ -5792,7 +5791,7 @@ void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]) BKE_keyblock_update_from_vertcos(ob, kb, vertCos); } -/* Note: we do the topology update before any brush actions to avoid +/* NOTE: we do the topology update before any brush actions to avoid * issues with the proxies. The size of the proxy can't change, so * topology must be updated first. */ static void sculpt_topology_update(Sculpt *sd, @@ -6363,7 +6362,7 @@ void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used) MEM_SAFE_FREE(nodes); /* Modifiers could depend on mesh normals, so we should update them. - * Note, then if sculpting happens on locked key, normals should be re-calculate after applying + * NOTE: then if sculpting happens on locked key, normals should be re-calculate after applying * coords from key-block on base mesh. */ BKE_mesh_calc_normals(me); } @@ -7875,7 +7874,7 @@ static bool over_mesh(bContext *C, struct wmOperator *UNUSED(op), float x, float static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2]) { /* Don't start the stroke until mouse goes over the mesh. - * note: mouse will only be null when re-executing the saved stroke. + * NOTE: mouse will only be null when re-executing the saved stroke. * We have exception for 'exec' strokes since they may not set 'mouse', * only 'location', see: T52195. */ if (((op->flag & OP_IS_INVOKE) == 0) || (mouse == NULL) || diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c index 5f5fb51d75f..35f48400fe2 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.c +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c @@ -209,7 +209,7 @@ static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *au Brush *brush = BKE_paint_brush(&sd->paint); if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { - BLI_assert(!"Topology masking: pmap missing"); + BLI_assert_msg(0, "Topology masking: pmap missing"); return NULL; } @@ -248,7 +248,7 @@ static float *sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *a } if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { - BLI_assert(!"Face Sets automasking: pmap missing"); + BLI_assert_msg(0, "Face Sets automasking: pmap missing"); return NULL; } @@ -273,7 +273,7 @@ float *SCULPT_boundary_automasking_init(Object *ob, SculptSession *ss = ob->sculpt; if (!ss->pmap) { - BLI_assert(!"Boundary Edges masking: pmap missing"); + BLI_assert_msg(0, "Boundary Edges masking: pmap missing"); return NULL; } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 087cb6dd94a..696c3332a2b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -278,7 +278,7 @@ void SCULPT_flip_v3_by_symm_area(float v[3], const ePaintSymmetryFlags symm, const ePaintSymmetryAreas symmarea, const float pivot[3]); -void SCULPT_flip_quat_by_symm_area(float quat[3], +void SCULPT_flip_quat_by_symm_area(float quat[4], const ePaintSymmetryFlags symm, const ePaintSymmetryAreas symmarea, const float pivot[3]); @@ -623,7 +623,7 @@ typedef struct SculptUndoNode { SculptUndoType type; - char idname[MAX_ID_NAME]; /* name instead of pointer*/ + char idname[MAX_ID_NAME]; /* Name instead of pointer. */ void *node; /* only during push, not valid afterwards! */ float (*co)[3]; @@ -704,7 +704,7 @@ typedef struct SculptThreadedTaskData { /* Data specific to some callbacks. */ - /* Note: even if only one or two of those are used at a time, + /* NOTE: even if only one or two of those are used at a time, * keeping them separated, names help figuring out * what it is, and memory overhead is ridiculous anyway. */ float flippedbstrength; @@ -977,7 +977,7 @@ typedef struct StrokeCache { /* Symmetry index between 0 and 7 bit combo 0 is Brush only; * 1 is X mirror; 2 is Y mirror; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */ int symmetry; - int mirror_symmetry_pass; /* the symmetry pass we are currently on between 0 and 7*/ + int mirror_symmetry_pass; /* The symmetry pass we are currently on between 0 and 7. */ float true_view_normal[3]; float view_normal[3]; diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 61984610a5a..eabbfe43e03 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -367,7 +367,7 @@ void SCULPT_smooth(Sculpt *sd, last = max_iterations * (bstrength - count * fract); if (type == PBVH_FACES && !ss->pmap) { - BLI_assert(!"sculpt smooth: pmap missing"); + BLI_assert_msg(0, "sculpt smooth: pmap missing"); return; } diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index b6205db6f45..501a1e53276 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -766,7 +766,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase case SCULPT_UNDO_DYNTOPO_BEGIN: case SCULPT_UNDO_DYNTOPO_END: case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: - BLI_assert(!"Dynamic topology should've already been handled"); + BLI_assert_msg(0, "Dynamic topology should've already been handled"); break; } } @@ -1065,7 +1065,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt case SCULPT_UNDO_DYNTOPO_BEGIN: case SCULPT_UNDO_DYNTOPO_END: case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: - BLI_assert(!"Dynamic topology should've already been handled"); + BLI_assert_msg(0, "Dynamic topology should've already been handled"); case SCULPT_UNDO_GEOMETRY: case SCULPT_UNDO_FACE_SETS: break; @@ -1189,9 +1189,7 @@ static SculptUndoNode *sculpt_undo_geometry_push(Object *object, SculptUndoType static SculptUndoNode *sculpt_undo_face_sets_push(Object *ob, SculptUndoType type) { UndoSculpt *usculpt = sculpt_undo_get_nodes(); - SculptUndoNode *unode = usculpt->nodes.first; - - unode = MEM_callocN(sizeof(*unode), __func__); + SculptUndoNode *unode = MEM_callocN(sizeof(*unode), __func__); BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname)); unode->type = type; @@ -1357,7 +1355,7 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType case SCULPT_UNDO_DYNTOPO_BEGIN: case SCULPT_UNDO_DYNTOPO_END: case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: - BLI_assert(!"Dynamic topology should've already been handled"); + BLI_assert_msg(0, "Dynamic topology should've already been handled"); case SCULPT_UNDO_GEOMETRY: case SCULPT_UNDO_FACE_SETS: break; @@ -1434,7 +1432,7 @@ void SCULPT_undo_push_end_ex(const bool use_nested_undo) typedef struct SculptUndoStep { UndoStep step; - /* Note: will split out into list for multi-object-sculpt-mode. */ + /* NOTE: will split out into list for multi-object-sculpt-mode. */ UndoSculpt data; } SculptUndoStep; @@ -1551,7 +1549,7 @@ static void sculpt_undosys_step_decode( ED_object_mode_generic_exit(bmain, depsgraph, scene, ob); /* Sculpt needs evaluated state. - * Note: needs to be done here, as #ED_object_mode_generic_exit will usually invalidate + * NOTE: needs to be done here, as #ED_object_mode_generic_exit will usually invalidate * (some) evaluated data. */ BKE_scene_graph_evaluated_ensure(depsgraph, bmain); @@ -1610,7 +1608,7 @@ void ED_sculpt_undosys_type(UndoType *ut) ut->step_decode = sculpt_undosys_step_decode; ut->step_free = sculpt_undosys_step_free; - ut->flags = 0; + ut->flags = UNDOTYPE_FLAG_DECODE_ACTIVE_STEP; ut->step_size = sizeof(SculptUndoStep); } diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 219a8303674..771e0e1e47b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -92,7 +92,7 @@ typedef struct UVInitialStroke { /* Initial Selection,for grab brushes for instance */ UVInitialStrokeElement *initialSelection; - /* total initially selected UVs*/ + /* Total initially selected UV's. */ int totalInitialSelected; /* initial mouse coordinates */ @@ -101,9 +101,9 @@ typedef struct UVInitialStroke { /* custom data for uv smoothing brush */ typedef struct UvSculptData { - /* Contains the first of each set of coincident uvs. + /* Contains the first of each set of coincident UV's. * These will be used to perform smoothing on and propagate the changes - * to their coincident uvs */ + * to their coincident UV's */ UvAdjacencyElement *uv; /* ...Is what it says */ @@ -121,7 +121,7 @@ typedef struct UvSculptData { /* timer to be used for airbrush-type brush */ wmTimer *timer; - /* to determine quickly adjacent uvs */ + /* to determine quickly adjacent UV's */ UvElementMap *elementMap; /* uvsmooth Paint for fast reference */ @@ -505,7 +505,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm bool do_island_optimization = !(ts->uv_sculpt_settings & UV_SCULPT_ALL_ISLANDS); int island_index = 0; - /* Holds, for each UvElement in elementMap, a pointer to its unique uv.*/ + /* Holds, for each UvElement in elementMap, a pointer to its unique UV. */ int *uniqueUv; data->tool = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_SMOOTH) ? UV_SCULPT_TOOL_RELAX : @@ -550,7 +550,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm island_index = element->island; } - /* Count 'unique' uvs */ + /* Count 'unique' UV's */ for (i = 0; i < data->elementMap->totalUVs; i++) { if (data->elementMap->buf[i].separate && (!do_island_optimization || data->elementMap->buf[i].island == island_index)) { @@ -603,7 +603,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm data->uv[counter].flag = 0; data->uv[counter].uv = luv->uv; } - /* pointer arithmetic to the rescue, as always :)*/ + /* Pointer arithmetic to the rescue, as always :). */ uniqueUv[element - data->elementMap->buf] = counter; } } @@ -627,8 +627,8 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm offset2 = uniqueUv[itmp2]; edges[counter].flag = 0; - /* using an order policy, sort uvs according to address space. This avoids - * Having two different UvEdges with the same uvs on different positions */ + /* Using an order policy, sort UV's according to address space. + * This avoids having two different UvEdges with the same UV's on different positions. */ if (offset1 < offset2) { edges[counter].uv1 = offset1; edges[counter].uv2 = offset2; @@ -674,7 +674,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm BLI_ghash_free(edgeHash, NULL, NULL); MEM_freeN(edges); - /* transfer boundary edge property to uvs */ + /* transfer boundary edge property to UV's */ if (ts->uv_sculpt_settings & UV_SCULPT_LOCK_BORDERS) { for (i = 0; i < data->totalUvEdges; i++) { if (!data->uvedges[i].flag) { diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index efa714e315d..d69c7ab8d48 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -723,7 +723,7 @@ static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime) return NULL; } -/* Switch NLA Strips/Actions */ +/* Switch NLA Strips/Actions. */ static void action_layer_switch_strip( AnimData *adt, NlaTrack *old_track, NlaStrip *old_strip, NlaTrack *nlt, NlaStrip *strip) { @@ -813,7 +813,7 @@ static int action_layer_next_exec(bContext *C, wmOperator *op) NlaTrack *act_track; Scene *scene = CTX_data_scene(C); - float ctime = BKE_scene_frame_get(scene); + float ctime = BKE_scene_ctime_get(scene); /* Get active track */ act_track = BKE_nlatrack_find_tweaked(adt); @@ -925,7 +925,7 @@ static int action_layer_prev_exec(bContext *C, wmOperator *op) NlaTrack *nlt; Scene *scene = CTX_data_scene(C); - float ctime = BKE_scene_frame_get(scene); + float ctime = BKE_scene_ctime_get(scene); /* Sanity Check */ if (adt == NULL) { diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 5036f22fd0e..ce07b9c5fad 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -83,7 +83,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region) /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */ UI_view2d_sync(NULL, ac->area, v2d, V2D_LOCK_COPY); - /* loop through channels, and set up drawing depending on their type */ + /* Loop through channels, and set up drawing depending on their type. */ { /* first pass: just the standard GL-drawing for backdrop + text */ size_t channel_index = 0; float ymax = ACHANNEL_FIRST_TOP(ac); @@ -263,7 +263,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax); } else if (ac->datatype == ANIMCONT_MASK) { - /* TODO --- this is a copy of gpencil */ + /* TODO: this is a copy of gpencil. */ /* frames less than one get less saturated background */ uchar *color = sel ? col1 : col2; immUniformColor4ubv(color); diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index fea62f0d9c2..6f4e295cbb2 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -163,7 +163,7 @@ void ACTION_OT_markers_make_local(wmOperatorType *ot) /* *************************** Calculate Range ************************** */ -/* Get the min/max keyframes*/ +/* Get the min/max keyframes. */ static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const short onlySel) { ListBase anim_data = {NULL, NULL}; @@ -576,7 +576,7 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op) } } else if (ac.datatype == ANIMCONT_MASK) { - /* FIXME... */ + /* FIXME: support this case. */ BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for mask mode"); return OPERATOR_CANCELLED; } @@ -629,7 +629,7 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op) } } else if (ac.datatype == ANIMCONT_MASK) { - /* FIXME... */ + /* FIXME: support this case. */ BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for grease pencil or mask mode"); @@ -1137,7 +1137,7 @@ void ACTION_OT_clean(wmOperatorType *ot) /* ******************** Sample Keyframes Operator *********************** */ -/* Evaluates the curves between each selected keyframe on each frame, and keys the value */ +/* Evaluates the curves between each selected keyframe on each frame, and keys the value. */ static void sample_action_keys(bAnimContext *ac) { ListBase anim_data = {NULL, NULL}; @@ -1149,7 +1149,7 @@ static void sample_action_keys(bAnimContext *ac) ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* loop through filtered data and add keys between selected keyframes on every frame */ + /* Loop through filtered data and add keys between selected keyframes on every frame. */ for (ale = anim_data.first; ale; ale = ale->next) { sample_fcurve((FCurve *)ale->key_data); @@ -1454,7 +1454,7 @@ static void sethandles_action_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Loop through setting flags for handles - * Note: we do not supply KeyframeEditData to the looper yet. + * NOTE: we do not supply KeyframeEditData to the looper yet. * Currently that's not necessary here. */ for (ale = anim_data.first; ale; ale = ale->next) { @@ -1537,7 +1537,7 @@ static void setkeytype_action_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Loop through setting BezTriple interpolation - * Note: we do not supply KeyframeEditData to the looper yet. + * NOTE: we do not supply KeyframeEditData to the looper yet. * Currently that's not necessary here. */ for (ale = anim_data.first; ale; ale = ale->next) { diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 98e39520e99..0d5b197ae93 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -470,7 +470,7 @@ static void box_select_action(bAnimContext *ac, const rcti rect, short mode, sho filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* get beztriple editing/validation funcs */ + /* Get beztriple editing/validation funcs. */ sel_data.select_cb = ANIM_editkeyframes_select(selectmode); if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) { @@ -708,7 +708,7 @@ static void region_select_action_keys( filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* get beztriple editing/validation funcs */ + /* Get beztriple editing/validation funcs. */ sel_data.select_cb = ANIM_editkeyframes_select(selectmode); sel_data.ok_cb = ANIM_editkeyframes_ok(mode); @@ -933,8 +933,8 @@ static const EnumPropertyItem prop_column_select_types[] = { /* ------------------- */ /* Selects all visible keyframes between the specified markers */ -/* TODO, this is almost an _exact_ duplicate of a function of the same name in graph_select.c - * should de-duplicate - campbell */ +/* TODO(campbell): this is almost an _exact_ duplicate of a function of the same name in + * graph_select.c should de-duplicate. */ static void markers_selectkeys_between(bAnimContext *ac) { ListBase anim_data = {NULL, NULL}; @@ -1497,7 +1497,7 @@ void ACTION_OT_select_leftright(wmOperatorType *ot) ot->idname = "ACTION_OT_select_leftright"; ot->description = "Select keyframes to the left or the right of the current frame"; - /* api callbacks */ + /* api callbacks */ ot->invoke = actkeys_select_leftright_invoke; ot->exec = actkeys_select_leftright_exec; ot->poll = ED_operator_action_active; @@ -1840,7 +1840,7 @@ static int actkeys_clickselect_exec(bContext *C, wmOperator *op) mval[0] = RNA_int_get(op->ptr, "mouse_x"); mval[1] = RNA_int_get(op->ptr, "mouse_y"); - /* select keyframe(s) based upon mouse position*/ + /* Select keyframe(s) based upon mouse position. */ ret_value = mouse_action_keys( &ac, mval, selectmode, deselect_all, column, channel, wait_to_deselect_others); @@ -1872,12 +1872,13 @@ void ACTION_OT_clickselect(wmOperatorType *ot) /* properties */ WM_operator_properties_generic_select(ot); + /* Key-map: Enable with `Shift`. */ prop = RNA_def_boolean( ot->srna, "extend", 0, "Extend Select", - "Toggle keyframe selection instead of leaving newly selected keyframes only"); /* SHIFTKEY */ + "Toggle keyframe selection instead of leaving newly selected keyframes only"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, @@ -1887,20 +1888,21 @@ void ACTION_OT_clickselect(wmOperatorType *ot) "Deselect all when nothing under the cursor"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + /* Key-map: Enable with `Alt`. */ prop = RNA_def_boolean( ot->srna, "column", 0, "Column Select", - "Select all keyframes that occur on the same frame as the one under the mouse"); /* ALTKEY */ + "Select all keyframes that occur on the same frame as the one under the mouse"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean( - ot->srna, - "channel", - 0, - "Only Channel", - "Select all the keyframes in the channel under the mouse"); /* CTRLKEY + ALTKEY */ + /* Key-map: Enable with `Ctrl-Alt`. */ + prop = RNA_def_boolean(ot->srna, + "channel", + 0, + "Only Channel", + "Select all the keyframes in the channel under the mouse"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index f6af2f79890..28482faf6e3 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -153,6 +153,8 @@ static SpaceLink *action_duplicate(SpaceLink *sl) { SpaceAction *sactionn = MEM_dupallocN(sl); + memset(&sactionn->runtime, 0x0, sizeof(sactionn->runtime)); + /* clear or remove stuff from old */ return (SpaceLink *)sactionn; @@ -528,7 +530,7 @@ static void action_listener(const wmSpaceTypeListenerParams *params) } break; case NC_ANIMATION: - /* for NLA tweakmode enter/exit, need complete refresh */ + /* For NLA tweak-mode enter/exit, need complete refresh. */ if (wmn->data == ND_NLA_ACTCHANGE) { saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC; ED_area_tag_refresh(area); diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt index c71e5e49d8d..b5f6874fcfc 100644 --- a/source/blender/editors/space_buttons/CMakeLists.txt +++ b/source/blender/editors/space_buttons/CMakeLists.txt @@ -50,7 +50,7 @@ if(WITH_FREESTYLE) endif() if(WITH_EXPERIMENTAL_FEATURES) - add_definitions(-DWITH_GEOMETRY_NODES) + add_definitions(-DWITH_SIMULATION_DATABLOCK) add_definitions(-DWITH_POINT_CLOUD) add_definitions(-DWITH_HAIR_NODES) endif() diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 1699e704a4d..70b715e0119 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -126,7 +126,7 @@ static bool buttons_context_path_view_layer(ButsContextPath *path, wmWindow *win return false; } -/* note: this function can return true without adding a world to the path +/* NOTE: this function can return true without adding a world to the path * so the buttons stay visible, but be sure to check the ID type if a ID_WO */ static bool buttons_context_path_world(ButsContextPath *path) { @@ -154,7 +154,9 @@ static bool buttons_context_path_world(ButsContextPath *path) return false; } -static bool buttons_context_path_collection(ButsContextPath *path, wmWindow *window) +static bool buttons_context_path_collection(const bContext *C, + ButsContextPath *path, + wmWindow *window) { PointerRNA *ptr = &path->ptr[path->len - 1]; @@ -162,10 +164,19 @@ static bool buttons_context_path_collection(ButsContextPath *path, wmWindow *win if (RNA_struct_is_a(ptr->type, &RNA_Collection)) { return true; } + + Scene *scene = CTX_data_scene(C); + /* if we have a view layer, use the view layer's active collection */ if (buttons_context_path_view_layer(path, window)) { ViewLayer *view_layer = path->ptr[path->len - 1].data; Collection *c = view_layer->active_collection->collection; + + /* Do not show collection tab for master collection. */ + if (c == scene->master_collection) { + return false; + } + if (c) { RNA_id_pointer_create(&c->id, &path->ptr[path->len]); path->len++; @@ -600,7 +611,7 @@ static bool buttons_context_path( found = buttons_context_path_world(path); break; case BCONTEXT_COLLECTION: /* This is for Line Art collection flags */ - found = buttons_context_path_collection(path, window); + found = buttons_context_path_collection(C, path, window); break; case BCONTEXT_TOOL: found = true; @@ -975,7 +986,8 @@ int /*eContextResult*/ buttons_context(const bContext *C, if (matnr < 0) { matnr = 0; } - CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, &ob->mat[matnr]); + /* Keep aligned with rna_Object_material_slots_get. */ + CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, POINTER_FROM_INT(matnr + 1)); } } @@ -1219,7 +1231,7 @@ static void buttons_panel_context_draw(const bContext *C, Panel *panel) continue; } - /* Add icon and name .*/ + /* Add icon and name. */ int icon = RNA_struct_ui_icon(ptr->type); char namebuf[128]; char *name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL); @@ -1272,7 +1284,7 @@ ID *buttons_context_id_path(const bContext *C) for (int i = path->len - 1; i >= 0; i--) { PointerRNA *ptr = &path->ptr[i]; - /* pin particle settings instead of system, since only settings are an idblock*/ + /* Pin particle settings instead of system, since only settings are an idblock. */ if (sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) { if (ptr->type == &RNA_ParticleSystem && ptr->data) { ParticleSystem *psys = ptr->data; @@ -1280,7 +1292,7 @@ ID *buttons_context_id_path(const bContext *C) } } - /* There is no valid image ID panel, Image Empty objects need this workaround.*/ + /* There is no valid image ID panel, Image Empty objects need this workaround. */ if (sbuts->mainb == BCONTEXT_DATA && sbuts->flag & SB_PIN_CONTEXT) { if (ptr->type == &RNA_Image && ptr->data) { continue; diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 97e3cb750c1..f1debcef5a9 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -451,7 +451,7 @@ static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg) /* set user as active */ if (user->node) { - ED_node_set_active(CTX_data_main(C), user->ntree, user->node, NULL); + ED_node_set_active(CTX_data_main(C), NULL, user->ntree, user->node, NULL); ct->texture = NULL; /* Not totally sure if we should also change selection? */ diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 9db8f7efbb2..57a7fe894b0 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -202,11 +202,11 @@ int ED_buttons_tabs_list(SpaceProperties *sbuts, short *context_tabs_array) context_tabs_array[length] = BCONTEXT_WORLD; length++; } - if (length != 0) { - context_tabs_array[length] = -1; - length++; - } if (sbuts->pathflag & (1 << BCONTEXT_COLLECTION)) { + if (length != 0) { + context_tabs_array[length] = -1; + length++; + } context_tabs_array[length] = BCONTEXT_COLLECTION; length++; } diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index d555238e949..7379891543b 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -809,12 +809,12 @@ void uiTemplateMovieclipInformation(uiLayout *layout, char str[1024]; size_t ofs = 0; - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, TIP_("%d x %d"), width, height); + ofs += BLI_snprintf_rlen(str + ofs, sizeof(str) - ofs, TIP_("%d x %d"), width, height); if (ibuf) { if (ibuf->rect_float) { if (ibuf->channels != 4) { - ofs += BLI_snprintf( + ofs += BLI_snprintf_rlen( str + ofs, sizeof(str) - ofs, TIP_(", %d float channel(s)"), ibuf->channels); } else if (ibuf->planes == R_IMF_PLANES_RGBA) { @@ -837,7 +837,7 @@ void uiTemplateMovieclipInformation(uiLayout *layout, short frs_sec; float frs_sec_base; if (IMB_anim_get_fps(clip->anim, &frs_sec, &frs_sec_base, true)) { - ofs += BLI_snprintf( + ofs += BLI_snprintf_rlen( str + ofs, sizeof(str) - ofs, TIP_(", %.2f fps"), (float)frs_sec / frs_sec_base); } } diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 2da13646a8b..67b4fd61d38 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -1025,7 +1025,7 @@ static void prefetch_startjob(void *pjv, short *stop, short *do_update, float *p progress); } else { - BLI_assert(!"Unknown movie clip source when prefetching frames"); + BLI_assert_msg(0, "Unknown movie clip source when prefetching frames"); } } diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 0c54a042a1a..f5e4c4d55d9 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -1235,10 +1235,8 @@ static void do_movie_proxy(void *pjv, float *progress) { ProxyJob *pj = pjv; - Scene *scene = pj->scene; MovieClip *clip = pj->clip; struct MovieDistortion *distortion = NULL; - int cfra, sfra = SFRA, efra = EFRA; if (pj->index_context) { IMB_anim_index_rebuild(pj->index_context, stop, do_update, progress); @@ -1252,8 +1250,8 @@ static void do_movie_proxy(void *pjv, return; } - sfra = 1; - efra = clip->len; + const int sfra = 1; + const int efra = clip->len; if (build_undistort_count) { int threads = BLI_system_thread_count(); @@ -1265,7 +1263,7 @@ static void do_movie_proxy(void *pjv, BKE_tracking_distortion_set_threads(distortion, threads); } - for (cfra = sfra; cfra <= efra; cfra++) { + for (int cfra = sfra; cfra <= efra; cfra++) { BKE_movieclip_build_proxy_frame( clip, pj->clip_flag, distortion, cfra, build_undistort_sizes, build_undistort_count, 1); diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index dbf733413e5..7194e78e940 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -398,7 +398,7 @@ void clip_delete_plane_track(bContext *C, MovieClip *clip, MovieTrackingPlaneTra DEG_id_tag_update(&clip->id, 0); } -/* Calculate space clip offset to be centered at the given point. */ +/* 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) { diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index e0a524a79c1..326c221a2e3 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1214,7 +1214,7 @@ static void clip_header_region_listener(const wmRegionListenerParams *params) switch (wmn->data) { /* for proportional editmode only */ case ND_TOOLSETTINGS: - /* TODO - should do this when in mask mode only but no data available */ + /* TODO: should do this when in mask mode only but no data available. */ // if (sc->mode == SC_MODE_MASKEDIT) { ED_region_tag_redraw(region); diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index bcac4d94bf0..ff62bcf0cfa 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -52,7 +52,9 @@ #include "clip_intern.h" #include "tracking_ops_intern.h" -/********************** add marker operator *********************/ +/* -------------------------------------------------------------------- */ +/** \name Add Marker Operator + * \{ */ static bool add_marker(const bContext *C, float x, float y) { @@ -147,7 +149,11 @@ void CLIP_OT_add_marker(wmOperatorType *ot) 1.0f); } -/********************** add marker operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Marker Operator + * \{ */ static int add_marker_at_click_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { @@ -212,7 +218,11 @@ void CLIP_OT_add_marker_at_click(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; } -/********************** delete track operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Track Operator + * \{ */ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -265,7 +275,11 @@ void CLIP_OT_delete_track(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** delete marker operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Marker Operator + * \{ */ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -334,7 +348,11 @@ void CLIP_OT_delete_marker(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** slide marker operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Slide Marker Operator + * \{ */ enum { SLIDE_ACTION_POS = 0, @@ -1000,7 +1018,11 @@ void CLIP_OT_slide_marker(wmOperatorType *ot) FLT_MAX); } -/********************** clear track operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Track Operator + * \{ */ static int clear_track_path_exec(bContext *C, wmOperator *op) { @@ -1071,7 +1093,11 @@ void CLIP_OT_clear_track_path(wmOperatorType *ot) "Clear active track only instead of all selected tracks"); } -/********************** disable markers operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Disable Markers Operator + * \{ */ enum { MARKER_OP_DISABLE = 0, @@ -1137,7 +1163,11 @@ void CLIP_OT_disable_markers(wmOperatorType *ot) RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Disable action to execute"); } -/********************** set principal center operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Principal Center Operator + * \{ */ static int set_center_principal_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1174,7 +1204,11 @@ void CLIP_OT_set_center_principal(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** hide tracks operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide Tracks Operator + * \{ */ static int hide_tracks_exec(bContext *C, wmOperator *op) { @@ -1241,7 +1275,11 @@ void CLIP_OT_hide_tracks(wmOperatorType *ot) RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected tracks"); } -/********************** hide tracks clear operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide Tracks Clear Operator + * \{ */ static int hide_tracks_clear_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1284,7 +1322,11 @@ void CLIP_OT_hide_tracks_clear(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** frame jump operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Frame Jump Operator + * \{ */ static bool frame_jump_poll(bContext *C) { @@ -1379,7 +1421,11 @@ void CLIP_OT_frame_jump(wmOperatorType *ot) RNA_def_enum(ot->srna, "position", position_items, 0, "Position", "Position to jump to"); } -/********************** join tracks operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Join Tracks Operator + * \{ */ static int join_tracks_exec(bContext *C, wmOperator *op) { @@ -1475,7 +1521,11 @@ void CLIP_OT_join_tracks(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** Average tracks operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Average Tracks Operator + * \{ */ static int average_tracks_exec(bContext *C, wmOperator *op) { @@ -1566,7 +1616,11 @@ void CLIP_OT_average_tracks(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/********************** lock tracks operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Lock Tracks Operator + * \{ */ enum { TRACK_ACTION_LOCK = 0, @@ -1628,7 +1682,11 @@ void CLIP_OT_lock_tracks(wmOperatorType *ot) RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Lock action to execute"); } -/********************** set keyframe operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Keyframe Operator + * \{ */ enum { SOLVER_KEYFRAME_A = 0, @@ -1680,7 +1738,11 @@ void CLIP_OT_set_solver_keyframe(wmOperatorType *ot) RNA_def_enum(ot->srna, "keyframe", keyframe_items, 0, "Keyframe", "Keyframe to set"); } -/********************** track copy color operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Track Copy Color Operator + * \{ */ static int track_copy_color_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1725,7 +1787,11 @@ void CLIP_OT_track_copy_color(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** clean tracks operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clean Tracks Operator + * \{ */ static bool is_track_clean(MovieTrackingTrack *track, int frames, int del) { @@ -1963,7 +2029,11 @@ void CLIP_OT_clean_tracks(wmOperatorType *ot) RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Cleanup action to execute"); } -/********************** add tracking object *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Tracking Object + * \{ */ static int tracking_object_new_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1994,7 +2064,11 @@ void CLIP_OT_tracking_object_new(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** remove tracking object *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Remove Tracking Object + * \{ */ static int tracking_object_remove_exec(bContext *C, wmOperator *op) { @@ -2033,7 +2107,11 @@ void CLIP_OT_tracking_object_remove(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** copy tracks to clipboard operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy Tracks to Clipboard Operator + * \{ */ static int copy_tracks_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -2064,7 +2142,11 @@ void CLIP_OT_copy_tracks(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER; } -/********************* paste tracks from clipboard operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Paste Tracks From Clipboard Operator + * \{ */ static bool paste_tracks_poll(bContext *C) { @@ -2106,7 +2188,11 @@ void CLIP_OT_paste_tracks(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** Insert track keyframe operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Insert Track Keyframe Operator + * \{ */ static void keyframe_set_flag(bContext *C, bool set) { @@ -2181,7 +2267,11 @@ void CLIP_OT_keyframe_insert(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** Delete track keyframe operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Track Keyframe Operator + * \{ */ static int keyframe_delete_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -2203,3 +2293,5 @@ void CLIP_OT_keyframe_delete(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +/** \} */ diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index 05595e0b393..bdb7c622cd2 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -415,7 +415,7 @@ static int console_insert_exec(bContext *C, wmOperator *op) static int console_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - /* Note, the "text" property is always set from key-map, + /* NOTE: the "text" property is always set from key-map, * so we can't use #RNA_struct_property_is_set, check the length instead. */ if (!RNA_string_length(op->ptr, "text")) { /* if alt/ctrl/super are pressed pass through except for utf8 character event @@ -747,7 +747,7 @@ static int console_clear_exec(bContext *C, wmOperator *op) const bool scrollback = RNA_boolean_get(op->ptr, "scrollback"); const bool history = RNA_boolean_get(op->ptr, "history"); - /*ConsoleLine *ci = */ console_history_verify(C); + /* ConsoleLine *ci = */ console_history_verify(C); if (scrollback) { /* Last item in history. */ while (sc->scrollback.first) { @@ -790,7 +790,7 @@ static int console_history_cycle_exec(bContext *C, wmOperator *op) SpaceConsole *sc = CTX_wm_space_console(C); ARegion *region = CTX_wm_region(C); - /* TODO - stupid, just prevents crashes when no command line */ + /* TODO: stupid, just prevents crashes when no command line. */ ConsoleLine *ci = console_history_verify(C); const bool reverse = RNA_boolean_get(op->ptr, "reverse"); /* assumes down, reverse is up */ int prev_len = ci->len; @@ -1109,7 +1109,7 @@ typedef struct SetConsoleCursor { int sel_init; } SetConsoleCursor; -/* TODO, cursor placement without selection */ +/* TODO: cursor placement without selection. */ static void console_cursor_set_to_pos( SpaceConsole *sc, ARegion *region, SetConsoleCursor *scu, const int mval[2], int UNUSED(sel)) { diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index 56a6204b385..3029eed1017 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -107,7 +107,7 @@ static SpaceLink *console_duplicate(SpaceLink *sl) /* clear or remove stuff from old */ - /* TODO - duplicate?, then we also need to duplicate the py namespace */ + /* TODO: duplicate?, then we also need to duplicate the py namespace. */ BLI_listbase_clear(&sconsolen->scrollback); BLI_listbase_clear(&sconsolen->history); diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index c1dcf2e56d3..faa4b3cc9cc 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -25,6 +25,8 @@ #include <math.h> #include <string.h> +#include "MEM_guardedalloc.h" + #include "BLI_alloca.h" #include "BLI_blenlib.h" #include "BLI_fileops_types.h" @@ -108,7 +110,7 @@ void ED_file_path_button(bScreen *screen, UI_but_func_complete_set(but, autocomplete_directory, NULL); UI_but_funcN_set(but, file_directory_enter_handle, NULL, but); - /* TODO, directory editing is non-functional while a library is loaded + /* TODO: directory editing is non-functional while a library is loaded * until this is properly supported just disable it. */ if (sfile && sfile->files && filelist_lib(sfile->files)) { UI_but_flag_enable(but, UI_BUT_DISABLED); @@ -142,7 +144,8 @@ static void draw_tile(int sx, int sy, int width, int height, int colorid, int sh color); } -static void file_draw_icon(uiBlock *block, +static void file_draw_icon(const SpaceFile *sfile, + uiBlock *block, const FileDirEntry *file, const char *path, int sx, @@ -164,23 +167,28 @@ static void file_draw_icon(uiBlock *block, const float a2 = dimmed ? 0.3f : 0.0f; but = uiDefIconBut( block, UI_BTYPE_LABEL, 0, icon, x, y, width, height, NULL, 0.0f, 0.0f, a1, a2, NULL); - UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path)); + UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path), MEM_freeN); if (drag) { - /* TODO duplicated from file_draw_preview(). */ + /* TODO: duplicated from file_draw_preview(). */ ID *id; if ((id = filelist_file_get_id(file))) { UI_but_drag_set_id(but, id); } - else if (file->typeflag & FILE_TYPE_ASSET) { + else if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS && + (file->typeflag & FILE_TYPE_ASSET) != 0) { ImBuf *preview_image = filelist_file_getimage(file); char blend_path[FILE_MAX_LIBEXTRA]; if (BLO_library_path_explode(path, blend_path, NULL, NULL)) { + const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile); + BLI_assert(asset_params != NULL); + UI_but_drag_set_asset(but, file->name, BLI_strdup(blend_path), file->blentype, + asset_params->import_type, icon, preview_image, UI_DPI_FAC); @@ -299,7 +307,8 @@ void file_calc_previews(const bContext *C, ARegion *region) UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height); } -static void file_draw_preview(uiBlock *block, +static void file_draw_preview(const SpaceFile *sfile, + uiBlock *block, const FileDirEntry *file, const char *path, int sx, @@ -323,6 +332,7 @@ static void file_draw_preview(uiBlock *block, int ex, ey; bool show_outline = !is_icon && (file->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_BLENDER)); + const bool is_offline = (file->attributes & FILE_ATTR_OFFLINE); BLI_assert(imb != NULL); @@ -390,7 +400,7 @@ static void file_draw_preview(uiBlock *block, imb->x, imb->y, GPU_RGBA8, - false, + true, imb->rect, scale, scale, @@ -419,14 +429,14 @@ static void file_draw_preview(uiBlock *block, icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false); } - if (is_link) { - /* Arrow icon to indicate it is a shortcut, link, or alias. */ + if (is_link || is_offline) { + /* Icon at bottom to indicate it is a shortcut, link, alias, or offline. */ float icon_x, icon_y; icon_x = xco + (2.0f * UI_DPI_FAC); icon_y = yco + (2.0f * UI_DPI_FAC); - const int arrow = ICON_LOOP_FORWARDS; + const int arrow = is_link ? ICON_LOOP_FORWARDS : ICON_URL; if (!is_icon) { - /* Arrow at very bottom-left if preview style. */ + /* At very bottom-left if preview style. */ const uchar dark[4] = {0, 0, 0, 255}; const uchar light[4] = {255, 255, 255, 255}; UI_icon_draw_ex(icon_x + 1, icon_y - 1, arrow, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false); @@ -481,11 +491,22 @@ static void file_draw_preview(uiBlock *block, UI_but_drag_set_id(but, id); } /* path is no more static, cannot give it directly to but... */ - else if (file->typeflag & FILE_TYPE_ASSET) { + else if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS && + (file->typeflag & FILE_TYPE_ASSET) != 0) { char blend_path[FILE_MAX_LIBEXTRA]; + if (BLO_library_path_explode(path, blend_path, NULL, NULL)) { - UI_but_drag_set_asset( - but, file->name, BLI_strdup(blend_path), file->blentype, icon, imb, scale); + const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile); + BLI_assert(asset_params != NULL); + + UI_but_drag_set_asset(but, + file->name, + BLI_strdup(blend_path), + file->blentype, + asset_params->import_type, + icon, + imb, + scale); } } else { @@ -502,6 +523,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) char orgname[FILE_MAX + 12]; char filename[FILE_MAX + 12]; wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); ARegion *region = CTX_wm_region(C); FileSelectParams *params = ED_fileselect_get_active_params(sfile); @@ -521,17 +543,15 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) else { /* If rename is successful, scroll to newly renamed entry. */ BLI_strncpy(params->renamefile, filename, sizeof(params->renamefile)); - params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING; - - if (sfile->smoothscroll_timer != NULL) { - WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); - } - sfile->smoothscroll_timer = WM_event_add_timer(wm, CTX_wm_window(C), TIMER1, 1.0 / 1000.0); - sfile->scroll_offset = 0; + file_params_invoke_rename_postscroll(wm, win, sfile); } /* to make sure we show what is on disk */ - ED_fileselect_clear(wm, CTX_data_scene(C), sfile); + ED_fileselect_clear(wm, sfile); + } + else { + /* Renaming failed, reset the name for further renaming handling. */ + BLI_strncpy(params->renamefile, oldname, sizeof(params->renamefile)); } ED_region_tag_redraw(region); @@ -706,40 +726,45 @@ static void draw_columnheader_columns(const FileSelectParams *params, /** * Updates the stat string stored in file->entry if necessary. */ -static const char *filelist_get_details_column_string(FileAttributeColumnType column, - const FileDirEntry *file, - const bool small_size, - const bool update_stat_strings) +static const char *filelist_get_details_column_string( + FileAttributeColumnType column, + /* Generated string will be cached in the file, so non-const. */ + FileDirEntry *file, + const bool small_size, + const bool update_stat_strings) { switch (column) { case COLUMN_DATETIME: if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) { - if ((file->entry->datetime_str[0] == '\0') || update_stat_strings) { + if ((file->draw_data.datetime_str[0] == '\0') || update_stat_strings) { char date[FILELIST_DIRENTRY_DATE_LEN], time[FILELIST_DIRENTRY_TIME_LEN]; bool is_today, is_yesterday; BLI_filelist_entry_datetime_to_string( - NULL, file->entry->time, small_size, time, date, &is_today, &is_yesterday); + NULL, file->time, small_size, time, date, &is_today, &is_yesterday); if (is_today || is_yesterday) { BLI_strncpy(date, is_today ? N_("Today") : N_("Yesterday"), sizeof(date)); } - BLI_snprintf( - file->entry->datetime_str, sizeof(file->entry->datetime_str), "%s %s", date, time); + BLI_snprintf(file->draw_data.datetime_str, + sizeof(file->draw_data.datetime_str), + "%s %s", + date, + time); } - return file->entry->datetime_str; + return file->draw_data.datetime_str; } break; case COLUMN_SIZE: if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) || !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) { - if ((file->entry->size_str[0] == '\0') || update_stat_strings) { + if ((file->draw_data.size_str[0] == '\0') || update_stat_strings) { BLI_filelist_entry_size_to_string( - NULL, file->entry->size, small_size, file->entry->size_str); + NULL, file->size, small_size, file->draw_data.size_str); } - return file->entry->size_str; + return file->draw_data.size_str; } break; default: @@ -751,7 +776,7 @@ static const char *filelist_get_details_column_string(FileAttributeColumnType co static void draw_details_columns(const FileSelectParams *params, const FileLayout *layout, - const FileDirEntry *file, + FileDirEntry *file, const int pos_x, const int pos_y, const uchar text_col[4]) @@ -792,6 +817,8 @@ static void draw_details_columns(const FileSelectParams *params, void file_draw_list(const bContext *C, ARegion *region) { + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileLayout *layout = ED_fileselect_get_layout(sfile, region); @@ -862,12 +889,12 @@ void file_draw_list(const bContext *C, ARegion *region) // printf("%s: preview task: %d\n", __func__, previews_running); if (previews_running && !sfile->previews_timer) { sfile->previews_timer = WM_event_add_timer_notifier( - CTX_wm_manager(C), CTX_wm_window(C), NC_SPACE | ND_SPACE_FILE_PREVIEW, 0.01); + wm, win, NC_SPACE | ND_SPACE_FILE_PREVIEW, 0.01); } if (!previews_running && sfile->previews_timer) { /* Preview is not running, no need to keep generating update events! */ // printf("%s: Inactive preview task, sleeping!\n", __func__); - WM_event_remove_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C), sfile->previews_timer); + WM_event_remove_timer_notifier(wm, win, sfile->previews_timer); sfile->previews_timer = NULL; } } @@ -924,7 +951,8 @@ void file_draw_list(const bContext *C, ARegion *region) is_icon = 1; } - file_draw_preview(block, + file_draw_preview(sfile, + block, file, path, sx, @@ -939,7 +967,8 @@ void file_draw_list(const bContext *C, ARegion *region) is_link); } else { - file_draw_icon(block, + file_draw_icon(sfile, + block, file, path, sx, @@ -976,8 +1005,19 @@ void file_draw_list(const bContext *C, ARegion *region) UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* allow non utf8 names */ UI_but_flag_disable(but, UI_BUT_UNDO); if (false == UI_but_active_only(C, region, block, but)) { - file_selflag = filelist_entry_select_set( - sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL); + /* Note that this is the only place where we can also handle a cancelled renaming. */ + + file_params_rename_end(wm, win, sfile, file); + + /* After the rename button is removed, we need to make sure the view is redrawn once more, + * in case selection changed. Usually UI code would trigger that redraw, but the rename + * operator may have been called from a different region. + * Tagging regions for redrawing while drawing is rightfully prevented. However, this + * active button removing basically introduces handling logic to drawing code. So a + * notifier should be an acceptable workaround. */ + WM_event_add_notifier_ex(wm, win, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + + file_selflag = filelist_entry_select_get(sfile->files, file, CHECK_ALL); } } diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index f1d0197b9ae..0bbed65671c 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -62,6 +62,7 @@ void FILE_OT_bookmark_cleanup(struct wmOperatorType *ot); void FILE_OT_bookmark_move(struct wmOperatorType *ot); void FILE_OT_reset_recent(wmOperatorType *ot); void FILE_OT_hidedot(struct wmOperatorType *ot); +void FILE_OT_associate_blend(struct wmOperatorType *ot); void FILE_OT_execute(struct wmOperatorType *ot); void FILE_OT_mouse_execute(struct wmOperatorType *ot); void FILE_OT_cancel(struct wmOperatorType *ot); @@ -108,10 +109,22 @@ FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d, float file_string_width(const char *str); float file_font_pointsize(void); +void file_select_deselect_all(SpaceFile *sfile, uint flag); int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file); int autocomplete_directory(struct bContext *C, char *str, void *arg_v); int autocomplete_file(struct bContext *C, char *str, void *arg_v); +void file_params_smoothscroll_timer_clear(struct wmWindowManager *wm, + struct wmWindow *win, + SpaceFile *sfile); +void file_params_renamefile_clear(struct FileSelectParams *params); +void file_params_invoke_rename_postscroll(struct wmWindowManager *wm, + struct wmWindow *win, + SpaceFile *sfile); +void file_params_rename_end(struct wmWindowManager *wm, + struct wmWindow *win, + SpaceFile *sfile, + struct FileDirEntry *rename_file); void file_params_renamefile_activate(struct SpaceFile *sfile, struct FileSelectParams *params); typedef void *onReloadFnData; diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 61f3c046550..995383d9d0e 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -86,7 +86,7 @@ static FileSelection find_file_mouse_rect(SpaceFile *sfile, BLI_rctf_rcti_copy(&rect_region_fl, rect_region); - /* Okay, manipulating v2d rects here is hacky... */ + /* Okay, manipulating v2d rects here is hacky... */ v2d->mask.ymax -= sfile->layout->offset_top; v2d->cur.ymax -= sfile->layout->offset_top; UI_view2d_region_to_view_rctf(v2d, &rect_region_fl, &rect_view_fl); @@ -104,15 +104,6 @@ static FileSelection find_file_mouse_rect(SpaceFile *sfile, return sel; } -static void file_deselect_all(SpaceFile *sfile, uint flag) -{ - FileSelection sel; - sel.first = 0; - sel.last = filelist_files_ensure(sfile->files) - 1; - - filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL); -} - typedef enum FileSelect { FILE_SELECT_NOTHING = 0, FILE_SELECT_DIR = 1, @@ -239,7 +230,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen) } /** - * \warning: loops over all files so better use cautiously + * \warning Loops over all files so better use cautiously. */ static bool file_is_any_selected(struct FileList *files) { @@ -444,7 +435,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve if ((sel.first != params->sel_first) || (sel.last != params->sel_last)) { int idx; - file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); + file_select_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); filelist_entries_select_index_range_set( sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); @@ -472,7 +463,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve params->highlight_file = -1; params->sel_first = params->sel_last = -1; fileselect_file_set(sfile, params->active_file); - file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); + file_select_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); } @@ -491,7 +482,7 @@ static int file_box_select_exec(bContext *C, wmOperator *op) const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); const bool select = (sel_op != SEL_OP_SUB); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - file_deselect_all(sfile, FILE_SEL_SELECTED); + file_select_deselect_all(sfile, FILE_SEL_SELECTED); } ED_fileselect_layout_isect_rect(sfile->layout, ®ion->v2d, &rect, &rect); @@ -573,7 +564,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) if ((idx >= 0) && (idx < numfiles)) { /* single select, deselect all selected first */ if (!extend) { - file_deselect_all(sfile, FILE_SEL_SELECTED); + file_select_deselect_all(sfile, FILE_SEL_SELECTED); } } } @@ -588,7 +579,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (ret == FILE_SELECT_NOTHING) { if (deselect_all) { - file_deselect_all(sfile, FILE_SEL_SELECTED); + file_select_deselect_all(sfile, FILE_SEL_SELECTED); } } else if (ret == FILE_SELECT_DIR) { @@ -721,7 +712,7 @@ static bool file_walk_select_selection_set(wmWindow *win, } else { /* deselect all first */ - file_deselect_all(sfile, FILE_SEL_SELECTED); + file_select_deselect_all(sfile, FILE_SEL_SELECTED); /* highlight file under mouse pos */ params->highlight_file = -1; @@ -1023,7 +1014,7 @@ void FILE_OT_view_selected(wmOperatorType *ot) /* Note we could get rid of this one, but it's used by some addon so... * Does not hurt keeping it around for now. */ -/* TODO disallow bookmark editing in assets mode? */ +/* TODO: disallow bookmark editing in assets mode? */ static int bookmark_select_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -1677,7 +1668,7 @@ void file_draw_check_ex(bContext *C, ScrArea *area) if (op->type->check(C, op)) { file_operator_to_sfile(bmain, sfile, op); - /* redraw, else the changed settings wont get updated */ + /* redraw, else the changed settings won't get updated */ ED_area_tag_redraw(area); } } @@ -1744,7 +1735,7 @@ static bool file_execute(bContext *C, SpaceFile *sfile) /* directory change */ if (file && (file->typeflag & FILE_TYPE_DIR)) { if (!file->relpath) { - return OPERATOR_CANCELLED; + return false; } if (FILENAME_IS_PARENT(file->relpath)) { @@ -1783,7 +1774,7 @@ static bool file_execute(bContext *C, SpaceFile *sfile) WM_event_fileselect_event(CTX_wm_manager(C), op, EVT_FILESELECT_EXEC); } - return OPERATOR_FINISHED; + return true; } static int file_exec(bContext *C, wmOperator *UNUSED(op)) @@ -1882,7 +1873,7 @@ static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused)) SpaceFile *sfile = CTX_wm_space_file(C); struct FSMenu *fsmenu = ED_fsmenu_get(); - ED_fileselect_clear(wm, CTX_data_scene(C), sfile); + ED_fileselect_clear(wm, sfile); /* refresh system directory menu */ fsmenu_refresh_system_category(fsmenu); @@ -2059,13 +2050,15 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w } } + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + /* if we are not editing, we are done */ if (edit_idx == -1) { /* Do not invalidate timer if filerename is still pending, * we might still be building the filelist and yet have to find edited entry. */ if (params->rename_flag == 0) { - WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); - sfile->smoothscroll_timer = NULL; + file_params_smoothscroll_timer_clear(wm, win, sfile); } return OPERATOR_PASS_THROUGH; } @@ -2073,8 +2066,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w /* we need the correct area for scrolling */ region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); if (!region || region->regiontype != RGN_TYPE_WINDOW) { - WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); - sfile->smoothscroll_timer = NULL; + file_params_smoothscroll_timer_clear(wm, win, sfile); return OPERATOR_PASS_THROUGH; } @@ -2093,7 +2085,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w sfile->layout, (int)region->v2d.cur.xmin, (int)-region->v2d.cur.ymax); const int last_visible_item = first_visible_item + numfiles_layout + 1; - /* Note: the special case for vertical layout is because filename is at the bottom of items then, + /* NOTE: the special case for vertical layout is because filename is at the bottom of items then, * so we artificially move current row back one step, to ensure we show bottom of * active item rather than its top (important in case visible height is low). */ const int middle_offset = max_ii( @@ -2131,13 +2123,11 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w (max_middle_offset - middle_offset < items_block_size)); if (is_ready && (is_centered || is_full_start || is_full_end)) { - WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); - sfile->smoothscroll_timer = NULL; + file_params_smoothscroll_timer_clear(wm, win, sfile); /* Post-scroll (after rename has been validated by user) is done, * rename process is totally finished, cleanup. */ if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE) != 0) { - params->renamefile[0] = '\0'; - params->rename_flag = 0; + file_params_renamefile_clear(params); } return OPERATOR_FINISHED; } @@ -2263,23 +2253,24 @@ void FILE_OT_filepath_drop(wmOperatorType *ot) * \{ */ /** - * Create a new, non-existing folder name, returns 1 if successful, 0 if name couldn't be created. + * Create a new, non-existing folder name, returns true if successful, + * false if name couldn't be created. * The actual name is returned in 'name', 'folder' contains the complete path, * including the new folder name. */ -static int new_folder_path(const char *parent, char *folder, char *name) +static bool new_folder_path(const char *parent, char folder[FILE_MAX], char name[FILE_MAXFILE]) { int i = 1; int len = 0; BLI_strncpy(name, "New Folder", FILE_MAXFILE); - BLI_join_dirfile(folder, FILE_MAX, parent, name); /* XXX, not real length */ + BLI_join_dirfile(folder, FILE_MAX, parent, name); /* check whether folder with the name already exists, in this case * add number to the name. Check length of generated name to avoid * crazy case of huge number of folders each named 'New Folder (x)' */ while (BLI_exists(folder) && (len < FILE_MAXFILE)) { len = BLI_snprintf(name, FILE_MAXFILE, "New Folder(%d)", i); - BLI_join_dirfile(folder, FILE_MAX, parent, name); /* XXX, not real length */ + BLI_join_dirfile(folder, FILE_MAX, parent, name); i++; } @@ -2345,21 +2336,20 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + eFileSel_Params_RenameFlag rename_flag = params->rename_flag; + /* If we don't enter the directory directly, remember file to jump into editing. */ if (do_diropen == false) { + BLI_assert(params->rename_id == NULL || !"File rename handling should immediately clear rename_id when done, because otherwise it will keep taking precedence over renamefile."); BLI_strncpy(params->renamefile, name, FILE_MAXFILE); - params->rename_flag = FILE_PARAMS_RENAME_PENDING; + rename_flag = FILE_PARAMS_RENAME_PENDING; } - /* Set timer to smoothly view newly generated file. */ - if (sfile->smoothscroll_timer != NULL) { - WM_event_remove_timer(wm, CTX_wm_window(C), sfile->smoothscroll_timer); - } - sfile->smoothscroll_timer = WM_event_add_timer(wm, CTX_wm_window(C), TIMER1, 1.0 / 1000.0); - sfile->scroll_offset = 0; + file_params_invoke_rename_postscroll(wm, CTX_wm_window(C), sfile); + params->rename_flag = rename_flag; /* reload dir to make sure we're seeing what's in the directory */ - ED_fileselect_clear(wm, CTX_data_scene(C), sfile); + ED_fileselect_clear(wm, sfile); if (do_diropen) { BLI_strncpy(params->dir, path, sizeof(params->dir)); @@ -2399,7 +2389,7 @@ void FILE_OT_directory_new(struct wmOperatorType *ot) /** \name Refresh File List Operator * \{ */ -/* TODO This should go to BLI_path_utils. */ +/* TODO: This should go to BLI_path_utils. */ static void file_expand_directory(bContext *C) { Main *bmain = CTX_data_main(C); @@ -2440,7 +2430,7 @@ static void file_expand_directory(bContext *C) } } -/* TODO check we still need this, it's annoying to have OS-specific code here... :/ */ +/* TODO: check we still need this, it's annoying to have OS-specific code here... :/. */ #if defined(WIN32) static bool can_create_dir(const char *dir) { @@ -2610,7 +2600,7 @@ static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused)) if (params) { params->flag ^= FILE_HIDE_DOT; - ED_fileselect_clear(wm, CTX_data_scene(C), sfile); + ED_fileselect_clear(wm, sfile); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } @@ -2632,6 +2622,43 @@ void FILE_OT_hidedot(struct wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Associate File Type Operator (Windows only) + * \{ */ + +static int associate_blend_exec(bContext *UNUSED(C), wmOperator *op) +{ +#ifdef WIN32 + WM_cursor_wait(true); + if (BLI_windows_register_blend_extension(true)) { + BKE_report(op->reports, RPT_INFO, "File association registered"); + WM_cursor_wait(false); + return OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, RPT_ERROR, "Unable to register file association"); + WM_cursor_wait(false); + return OPERATOR_CANCELLED; + } +#else + BKE_report(op->reports, RPT_WARNING, "Operator Not supported"); + return OPERATOR_CANCELLED; +#endif +} + +void FILE_OT_associate_blend(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Register File Association"; + ot->description = "Use this installation for .blend files and to display thumbnails"; + ot->idname = "FILE_OT_associate_blend"; + + /* api callbacks */ + ot->exec = associate_blend_exec; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Increment Filename Operator * \{ */ @@ -2766,6 +2793,11 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +static bool file_rename_poll(bContext *C) +{ + return ED_operator_file_active(C) && !ED_fileselect_is_asset_browser(CTX_wm_space_file(C)); +} + void FILE_OT_rename(struct wmOperatorType *ot) { /* identifiers */ @@ -2776,7 +2808,7 @@ void FILE_OT_rename(struct wmOperatorType *ot) /* api callbacks */ ot->invoke = file_rename_invoke; ot->exec = file_rename_exec; - ot->poll = ED_operator_file_active; + ot->poll = file_rename_poll; } /** \} */ @@ -2870,7 +2902,7 @@ static int file_delete_exec(bContext *C, wmOperator *op) } } - ED_fileselect_clear(wm, CTX_data_scene(C), sfile); + ED_fileselect_clear(wm, sfile); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c index afa85d183d8..7032d55b331 100644 --- a/source/blender/editors/space_file/file_panels.c +++ b/source/blender/editors/space_file/file_panels.c @@ -72,7 +72,7 @@ static void file_panel_operator(const bContext *C, Panel *panel) UI_block_func_set(uiLayoutGetBlock(panel->layout), file_draw_check_cb, NULL, NULL); - /* Hack: temporary hide.*/ + /* Hack: temporary hide. */ const char *hide[] = {"filepath", "files", "directory", "filename"}; for (int i = 0; i < ARRAY_SIZE(hide); i++) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, hide[i]); @@ -84,7 +84,7 @@ static void file_panel_operator(const bContext *C, Panel *panel) uiTemplateOperatorPropertyButs( C, panel->layout, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_EMPTY); - /* Hack: temporary hide.*/ + /* Hack: temporary hide. */ for (int i = 0; i < ARRAY_SIZE(hide); i++) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, hide[i]); if (prop) { diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index ca16563a7e2..0e15538e03b 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -263,8 +263,7 @@ ListBase folder_history_list_duplicate(ListBase *listbase) typedef struct FileListInternEntry { struct FileListInternEntry *next, *prev; - /** ASSET_UUID_LENGTH */ - char uuid[16]; + FileUID uid; /** eFileSel_File_Types */ int typeflag; @@ -306,7 +305,7 @@ typedef struct FileListIntern { ListBase entries; FileListInternEntry **filtered; - char curr_uuid[16]; /* Used to generate uuid during internal listing. */ + FileUID curr_uid; /* Used to generate UID during internal listing. */ } FileListIntern; #define FILELIST_ENTRYCACHESIZE_DEFAULT 1024 /* Keep it a power of two! */ @@ -315,7 +314,7 @@ typedef struct FileListEntryCache { int flags; - /* This one gathers all entries from both block and misc caches. Used for easy bulk-freing. */ + /* This one gathers all entries from both block and misc caches. Used for easy bulk-freeing. */ ListBase cached_entries; /* Block cache: all entries between start and end index. @@ -324,13 +323,13 @@ typedef struct FileListEntryCache { int block_start_index, block_end_index, block_center_index, block_cursor; /* Misc cache: random indices, FIFO behavior. - * Note: Not 100% sure we actually need that, time will say. */ + * NOTE: Not 100% sure we actually need that, time will say. */ int misc_cursor; int *misc_entries_indices; GHash *misc_entries; - /* Allows to quickly get a cached entry from its UUID. */ - GHash *uuids; + /* Allows to quickly get a cached entry from its UID. */ + GHash *uids; /* Previews handling. */ TaskPool *previews_pool; @@ -785,12 +784,12 @@ static bool is_filtered_hidden(const char *filename, const FileListInternEntry *file) { if ((filename[0] == '.') && (filename[1] == '\0')) { - return true; /* Ignore . */ + return true; /* Ignore. */ } if (filter->flags & FLF_HIDE_PARENT) { if (filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') { - return true; /* Ignore .. */ + return true; /* Ignore. */ } } @@ -1191,7 +1190,7 @@ static int filelist_geticon_ex(const FileDirEntry *file, if (FILENAME_IS_PARENT(file->relpath)) { return is_main ? ICON_FILE_PARENT : ICON_NONE; } - if (typeflag & FILE_TYPE_APPLICATIONBUNDLE) { + if (typeflag & FILE_TYPE_BUNDLE) { return ICON_UGLYPACKAGE; } if (typeflag & FILE_TYPE_BLENDER) { @@ -1383,40 +1382,6 @@ static void filelist_entry_clear(FileDirEntry *entry) BKE_icon_delete(entry->preview_icon_id); entry->preview_icon_id = 0; } - /* For now, consider FileDirEntryRevision::poin as not owned here, - * so no need to do anything about it */ - - if (!BLI_listbase_is_empty(&entry->variants)) { - FileDirEntryVariant *var; - - for (var = entry->variants.first; var; var = var->next) { - if (var->name) { - MEM_freeN(var->name); - } - if (var->description) { - MEM_freeN(var->description); - } - - if (!BLI_listbase_is_empty(&var->revisions)) { - FileDirEntryRevision *rev; - - for (rev = var->revisions.first; rev; rev = rev->next) { - if (rev->comment) { - MEM_freeN(rev->comment); - } - } - - BLI_freelistN(&var->revisions); - } - } - - /* TODO: tags! */ - - BLI_freelistN(&entry->variants); - } - else if (entry->entry) { - MEM_freeN(entry->entry); - } } static void filelist_entry_free(FileDirEntry *entry) @@ -1601,6 +1566,11 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE); + if (!entry->preview_icon_id && (entry->attributes & FILE_ATTR_OFFLINE)) { + entry->flags |= FILE_ENTRY_INVALID_PREVIEW; + return; + } + if (entry->preview_icon_id) { return; } @@ -1657,9 +1627,8 @@ static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size) copy_vn_i(cache->misc_entries_indices, cache_size, -1); cache->misc_cursor = 0; - /* XXX This assumes uint is 32 bits and uuid is 128 bits (char[16]), be careful! */ - cache->uuids = BLI_ghash_new_ex( - BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__, cache_size * 2); + cache->uids = BLI_ghash_new_ex( + BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__, cache_size * 2); cache->size = cache_size; cache->flags = FLC_IS_INIT; @@ -1683,7 +1652,7 @@ static void filelist_cache_free(FileListEntryCache *cache) BLI_ghash_free(cache->misc_entries, NULL, NULL); MEM_freeN(cache->misc_entries_indices); - BLI_ghash_free(cache->uuids, NULL, NULL); + BLI_ghash_free(cache->uids, NULL, NULL); for (entry = cache->cached_entries.first; entry; entry = entry_next) { entry_next = entry->next; @@ -1716,7 +1685,7 @@ static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size) } copy_vn_i(cache->misc_entries_indices, new_size, -1); - BLI_ghash_clear_ex(cache->uuids, NULL, NULL, new_size * 2); + BLI_ghash_clear_ex(cache->uids, NULL, NULL, new_size * 2); cache->size = new_size; @@ -1733,8 +1702,7 @@ FileList *filelist_new(short type) filelist_cache_init(&p->filelist_cache, FILELIST_ENTRYCACHESIZE_DEFAULT); - p->selection_state = BLI_ghash_new( - BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__); + p->selection_state = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); p->filelist.nbr_entries = FILEDIR_NBR_ENTRIES_UNSET; filelist_settype(p, type); @@ -1793,7 +1761,7 @@ void filelist_clear_ex(struct FileList *filelist, const bool do_cache, const boo filelist_direntryarr_free(&filelist->filelist); if (do_selection && filelist->selection_state) { - BLI_ghash_clear(filelist->selection_state, MEM_freeN, NULL); + BLI_ghash_clear(filelist->selection_state, NULL, NULL); } } @@ -1814,7 +1782,7 @@ void filelist_free(struct FileList *filelist) filelist_cache_free(&filelist->filelist_cache); if (filelist->selection_state) { - BLI_ghash_free(filelist->selection_state, MEM_freeN, NULL); + BLI_ghash_free(filelist->selection_state, NULL, NULL); filelist->selection_state = NULL; } @@ -1952,16 +1920,12 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in FileListInternEntry *entry = filelist->filelist_intern.filtered[index]; FileListEntryCache *cache = &filelist->filelist_cache; FileDirEntry *ret; - FileDirEntryRevision *rev; ret = MEM_callocN(sizeof(*ret), __func__); - rev = MEM_callocN(sizeof(*rev), __func__); - - rev->size = (uint64_t)entry->st.st_size; - rev->time = (int64_t)entry->st.st_mtime; + ret->size = (uint64_t)entry->st.st_size; + ret->time = (int64_t)entry->st.st_mtime; - ret->entry = rev; ret->relpath = BLI_strdup(entry->relpath); if (entry->free_name) { ret->name = BLI_strdup(entry->name); @@ -1971,7 +1935,7 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in ret->name = entry->name; } ret->description = BLI_strdupcat(filelist->filelist.root, entry->relpath); - memcpy(ret->uuid, entry->uuid, sizeof(ret->uuid)); + ret->uid = entry->uid; ret->blentype = entry->blentype; ret->typeflag = entry->typeflag; ret->attributes = entry->attributes; @@ -2029,11 +1993,11 @@ FileDirEntry *filelist_file_ex(struct FileList *filelist, const int index, const ret = filelist_file_create_entry(filelist, index); old_index = cache->misc_entries_indices[cache->misc_cursor]; if ((old = BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(old_index), NULL))) { - BLI_ghash_remove(cache->uuids, old->uuid, NULL, NULL); + BLI_ghash_remove(cache->uids, POINTER_FROM_UINT(old->uid), NULL, NULL); filelist_file_release_entry(filelist, old); } BLI_ghash_insert(cache->misc_entries, POINTER_FROM_INT(index), ret); - BLI_ghash_insert(cache->uuids, ret->uuid, ret); + BLI_ghash_insert(cache->uids, POINTER_FROM_UINT(ret->uid), ret); cache->misc_entries_indices[cache->misc_cursor] = index; cache->misc_cursor = (cache->misc_cursor + 1) % cache_size; @@ -2052,19 +2016,21 @@ FileDirEntry *filelist_file(struct FileList *filelist, int index) return filelist_file_ex(filelist, index, true); } -int filelist_file_findpath(struct FileList *filelist, const char *filename) +/** + * Find a file from a file name, or more precisely, its file-list relative path, inside the + * filtered items. \return The index of the found file or -1. + */ +int filelist_file_find_path(struct FileList *filelist, const char *filename) { - int fidx = -1; - if (filelist->filelist.nbr_entries_filtered == FILEDIR_NBR_ENTRIES_UNSET) { - return fidx; + return -1; } - /* XXX TODO Cache could probably use a ghash on paths too? Not really urgent though. - * This is only used to find again renamed entry, - * annoying but looks hairy to get rid of it currently. */ + /* XXX TODO: Cache could probably use a ghash on paths too? Not really urgent though. + * This is only used to find again renamed entry, + * annoying but looks hairy to get rid of it currently. */ - for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) { + for (int fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) { FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx]; if (STREQ(entry->relpath, filename)) { return fidx; @@ -2075,38 +2041,53 @@ int filelist_file_findpath(struct FileList *filelist, const char *filename) } /** - * Get the ID a file represents (if any). For #FILE_MAIN, #FILE_MAIN_ASSET. + * Find a file representing \a id. + * \return The index of the found file or -1. */ -ID *filelist_file_get_id(const FileDirEntry *file) -{ - return file->id; -} - -FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4]) +int filelist_file_find_id(const FileList *filelist, const ID *id) { if (filelist->filelist.nbr_entries_filtered == FILEDIR_NBR_ENTRIES_UNSET) { - return NULL; + return -1; } - if (filelist->filelist_cache.uuids) { - FileDirEntry *entry = BLI_ghash_lookup(filelist->filelist_cache.uuids, uuid); - if (entry) { - return entry; + for (int fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) { + FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx]; + if (entry->local_data.id == id) { + return fidx; } } - { - int fidx; + return -1; +} - for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) { - FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx]; - if (memcmp(entry->uuid, uuid, sizeof(entry->uuid)) == 0) { - return filelist_file(filelist, fidx); - } - } - } +/** + * Get the ID a file represents (if any). For #FILE_MAIN, #FILE_MAIN_ASSET. + */ +ID *filelist_file_get_id(const FileDirEntry *file) +{ + return file->id; +} - return NULL; +#define FILE_UID_UNSET 0 + +static FileUID filelist_uid_generate(FileList *filelist) +{ + /* Using an atomic operation to avoid having to lock thread... + * Note that we do not really need this here currently, since there is a single listing thread, + * but better remain consistent about threading! */ + return atomic_add_and_fetch_uint32(&filelist->filelist_intern.curr_uid, 1); +} + +bool filelist_uid_is_set(const FileUID uid) +{ + FileUID unset_uid; + filelist_uid_unset(&unset_uid); + return unset_uid != uid; +} + +void filelist_uid_unset(FileUID *r_uid) +{ + *r_uid = FILE_UID_UNSET; } void filelist_file_cache_slidingwindow_set(FileList *filelist, size_t window_size) @@ -2142,7 +2123,7 @@ static bool filelist_file_cache_block_create(FileList *filelist, /* That entry might have already been requested and stored in misc cache... */ if ((entry = BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(idx), NULL)) == NULL) { entry = filelist_file_create_entry(filelist, idx); - BLI_ghash_insert(cache->uuids, entry->uuid, entry); + BLI_ghash_insert(cache->uids, POINTER_FROM_UINT(entry->uid), entry); } cache->block_entries[cursor] = entry; } @@ -2168,7 +2149,7 @@ static void filelist_file_cache_block_release(struct FileList *filelist, __func__, cursor /*, cache->block_entries[cursor], cache->block_entries[cursor]->relpath*/); #endif - BLI_ghash_remove(cache->uuids, entry->uuid, NULL, NULL); + BLI_ghash_remove(cache->uids, POINTER_FROM_UINT(entry->uid), NULL, NULL); filelist_file_release_entry(filelist, entry); #ifndef NDEBUG cache->block_entries[cursor] = NULL; @@ -2300,7 +2281,7 @@ bool filelist_file_cache_block(struct FileList *filelist, const int index) if (start_index < cache->block_start_index) { /* Add (request) needed entries before already cached ones. */ - /* Note: We need some index black magic to wrap around (cycle) + /* NOTE: We need some index black magic to wrap around (cycle) * inside our cache_size array... */ int size1 = cache->block_start_index - start_index; int size2 = 0; @@ -2332,7 +2313,7 @@ bool filelist_file_cache_block(struct FileList *filelist, const int index) // printf("\tstart-extended...\n"); if (end_index > cache->block_end_index) { /* Add (request) needed entries after already cached ones. */ - /* Note: We need some index black magic to wrap around (cycle) + /* NOTE: We need some index black magic to wrap around (cycle) * inside our cache_size array... */ int size1 = end_index - cache->block_end_index; int size2 = 0; @@ -2514,9 +2495,16 @@ int ED_path_extension_type(const char *path) if (file_is_blend_backup(path)) { return FILE_TYPE_BLENDER_BACKUP; } - if (BLI_path_extension_check(path, ".app")) { - return FILE_TYPE_APPLICATIONBUNDLE; +#ifdef __APPLE__ + if (BLI_path_extension_check_n(path, + /* Application bundle */ + ".app", + /* Safari in-progress/paused download */ + ".download", + NULL)) { + return FILE_TYPE_BUNDLE; } +#endif if (BLI_path_extension_check(path, ".py")) { return FILE_TYPE_PYSCRIPT; } @@ -2623,7 +2611,7 @@ uint filelist_entry_select_set(const FileList *filelist, FileCheckType check) { /* Default NULL pointer if not found is fine here! */ - void **es_p = BLI_ghash_lookup_p(filelist->selection_state, entry->uuid); + void **es_p = BLI_ghash_lookup_p(filelist->selection_state, POINTER_FROM_UINT(entry->uid)); uint entry_flag = es_p ? POINTER_AS_UINT(*es_p) : 0; const uint org_entry_flag = entry_flag; @@ -2651,13 +2639,12 @@ uint filelist_entry_select_set(const FileList *filelist, *es_p = POINTER_FROM_UINT(entry_flag); } else { - BLI_ghash_remove(filelist->selection_state, entry->uuid, MEM_freeN, NULL); + BLI_ghash_remove(filelist->selection_state, POINTER_FROM_UINT(entry->uid), NULL, NULL); } } else if (entry_flag) { - void *key = MEM_mallocN(sizeof(entry->uuid), __func__); - memcpy(key, entry->uuid, sizeof(entry->uuid)); - BLI_ghash_insert(filelist->selection_state, key, POINTER_FROM_UINT(entry_flag)); + BLI_ghash_insert( + filelist->selection_state, POINTER_FROM_UINT(entry->uid), POINTER_FROM_UINT(entry_flag)); } } @@ -2695,7 +2682,8 @@ uint filelist_entry_select_get(FileList *filelist, FileDirEntry *entry, FileChec if (((check == CHECK_ALL)) || ((check == CHECK_DIRS) && (entry->typeflag & FILE_TYPE_DIR)) || ((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR))) { /* Default NULL pointer if not found is fine here! */ - return POINTER_AS_UINT(BLI_ghash_lookup(filelist->selection_state, entry->uuid)); + return POINTER_AS_UINT( + BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(entry->uid))); } return 0; @@ -2720,7 +2708,7 @@ bool filelist_entry_is_selected(FileList *filelist, const int index) /* BLI_ghash_lookup returns NULL if not found, which gets mapped to 0, which gets mapped to * "not selected". */ const uint selection_state = POINTER_AS_UINT( - BLI_ghash_lookup(filelist->selection_state, intern_entry->uuid)); + BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(intern_entry->uid))); return selection_state != 0; } @@ -2810,7 +2798,7 @@ static int filelist_readjob_list_dir(const char *root, entry->attributes = BLI_file_attributes(full_path); if (S_ISDIR(files[i].s.st_mode) #ifdef __APPLE__ - && !(ED_path_extension_type(full_path) & FILE_TYPE_APPLICATIONBUNDLE) + && !(ED_path_extension_type(full_path) & FILE_TYPE_BUNDLE) #endif ) { entry->typeflag = FILE_TYPE_DIR; @@ -2889,7 +2877,8 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const } /* there we go */ - libfiledata = BLO_blendhandle_from_file(dir, NULL); + BlendFileReadReport bf_reports = {.reports = NULL}; + libfiledata = BLO_blendhandle_from_file(dir, &bf_reports); if (libfiledata == NULL) { return nbr_entries; } @@ -2954,7 +2943,7 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist) ListBase *lb; int a, fake, idcode, ok, totlib, totbl; - // filelist->type = FILE_MAIN; /* XXX TODO: add modes to filebrowser */ + // filelist->type = FILE_MAIN; /* XXX TODO: add modes to file-browser */ BLI_assert(filelist->filelist.entries == NULL); @@ -3060,7 +3049,7 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist) files->entry->relpath = BLI_strdup(relname); } // files->type |= S_IFREG; -# if 0 /* XXX TODO show the selection status of the objects */ +# if 0 /* XXX TODO: show the selection status of the objects. */ if (!filelist->has_func) { /* F4 DATA BROWSE */ if (idcode == ID_OB) { if ( ((Object *)id)->flag & SELECT) { @@ -3189,14 +3178,7 @@ static void filelist_readjob_do(const bool do_lib, for (entry = entries.first; entry; entry = entry->next) { BLI_join_dirfile(dir, sizeof(dir), rel_subdir, entry->relpath); - /* Generate our entry uuid. Abusing uuid as an uint32, shall be more than enough here, - * things would crash way before we overflow that counter! - * Using an atomic operation to avoid having to lock thread... - * Note that we do not really need this here currently, - * since there is a single listing thread, but better - * remain consistent about threading! */ - *((uint32_t *)entry->uuid) = atomic_add_and_fetch_uint32( - (uint32_t *)filelist->filelist_intern.curr_uuid, 1); + entry->uid = filelist_uid_generate(filelist); /* Only thing we change in direntry here, so we need to free it first. */ MEM_freeN(entry->relpath); @@ -3321,8 +3303,7 @@ static void filelist_readjob_main_assets(Main *current_main, 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( - (uint32_t *)filelist->filelist_intern.curr_uuid, 1); + entry->uid = filelist_uid_generate(filelist); entry->local_data.preview_image = BKE_asset_metadata_preview_get_from_id(id_iter->asset_data, id_iter); entry->local_data.id = id_iter; @@ -3368,9 +3349,7 @@ static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update flrj->tmp_filelist->filelist_intern.filtered = NULL; BLI_listbase_clear(&flrj->tmp_filelist->filelist_intern.entries); - memset(flrj->tmp_filelist->filelist_intern.curr_uuid, - 0, - sizeof(flrj->tmp_filelist->filelist_intern.curr_uuid)); + filelist_uid_unset(&flrj->tmp_filelist->filelist_intern.curr_uid); flrj->tmp_filelist->libfiledata = NULL; memset(&flrj->tmp_filelist->filelist_cache, 0, sizeof(flrj->tmp_filelist->filelist_cache)); @@ -3410,7 +3389,7 @@ static void filelist_readjob_update(void *flrjv) BLI_mutex_unlock(&flrj->lock); if (new_nbr_entries) { - /* Do not clear selection cache, we can assume already 'selected' uuids are still valid! */ + /* Do not clear selection cache, we can assume already 'selected' UIDs are still valid! */ filelist_clear_ex(flrj->filelist, true, false); flrj->filelist->flags |= (FL_NEED_SORTING | FL_NEED_FILTERING); @@ -3492,7 +3471,7 @@ void filelist_readjob_start(FileList *filelist, const bContext *C) /* setup job */ wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), - CTX_data_scene(C), + filelist, "Listing Dirs...", WM_JOB_PROGRESS, WM_JOB_TYPE_FILESEL_READDIR); @@ -3508,12 +3487,12 @@ void filelist_readjob_start(FileList *filelist, const bContext *C) WM_jobs_start(CTX_wm_manager(C), wm_job); } -void filelist_readjob_stop(wmWindowManager *wm, Scene *owner_scene) +void filelist_readjob_stop(FileList *filelist, wmWindowManager *wm) { - WM_jobs_kill_type(wm, owner_scene, WM_JOB_TYPE_FILESEL_READDIR); + WM_jobs_kill_type(wm, filelist, WM_JOB_TYPE_FILESEL_READDIR); } -int filelist_readjob_running(wmWindowManager *wm, Scene *owner_scene) +int filelist_readjob_running(FileList *filelist, wmWindowManager *wm) { - return WM_jobs_test(wm, owner_scene, WM_JOB_TYPE_FILESEL_READDIR); + return WM_jobs_test(wm, filelist, WM_JOB_TYPE_FILESEL_READDIR); } diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index 9eb70dd8437..0aace74e621 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -35,6 +35,8 @@ struct wmWindowManager; struct FileDirEntry; +typedef uint32_t FileUID; + typedef enum FileSelType { FILE_SEL_REMOVE = 0, FILE_SEL_ADD = 1, @@ -95,9 +97,11 @@ int filelist_needs_reading(struct FileList *filelist); FileDirEntry *filelist_file(struct FileList *filelist, int index); FileDirEntry *filelist_file_ex(struct FileList *filelist, int index, bool use_request); -int filelist_file_findpath(struct FileList *filelist, const char *file); +int filelist_file_find_path(struct FileList *filelist, const char *file); +int filelist_file_find_id(const struct FileList *filelist, const struct ID *id); struct ID *filelist_file_get_id(const struct FileDirEntry *file); -FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4]); +bool filelist_uid_is_set(const FileUID uid); +void filelist_uid_unset(FileUID *r_uid); void filelist_file_cache_slidingwindow_set(struct FileList *filelist, size_t window_size); bool filelist_file_cache_block(struct FileList *filelist, const int index); @@ -141,8 +145,8 @@ bool filelist_islibrary(struct FileList *filelist, char *dir, char **r_group); void filelist_freelib(struct FileList *filelist); void filelist_readjob_start(struct FileList *filelist, const struct bContext *C); -void filelist_readjob_stop(struct wmWindowManager *wm, struct Scene *owner_scene); -int filelist_readjob_running(struct wmWindowManager *wm, struct Scene *owner_scene); +void filelist_readjob_stop(struct FileList *filelist, struct wmWindowManager *wm); +int filelist_readjob_running(struct FileList *filelist, struct wmWindowManager *wm); bool filelist_cache_previews_update(struct FileList *filelist); void filelist_cache_previews_set(struct FileList *filelist, const bool use_previews); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 038b9c11bca..7ab93df81d2 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -120,12 +120,13 @@ static void fileselect_ensure_updated_asset_params(SpaceFile *sfile) asset_params->base_params.details_flags = U_default.file_space_data.details_flags; asset_params->asset_library.type = FILE_ASSET_LIBRARY_LOCAL; asset_params->asset_library.custom_library_index = -1; + asset_params->import_type = FILE_ASSET_IMPORT_APPEND; } FileSelectParams *base_params = &asset_params->base_params; base_params->file[0] = '\0'; base_params->filter_glob[0] = '\0'; - /* TODO this way of using filters to form categories is notably slower than specifying a + /* TODO: this way of using filters to form categories is notably slower than specifying a * "group" to read. That's because all types are read and filtering is applied afterwards. Would * be nice if we could lazy-read individual groups. */ base_params->flag |= U_default.file_space_data.flag | FILE_ASSETS_ONLY | FILE_FILTER; @@ -377,7 +378,7 @@ FileSelectParams *ED_fileselect_ensure_active_params(SpaceFile *sfile) return &sfile->asset_params->base_params; } - BLI_assert(!"Invalid browse mode set in file space."); + BLI_assert_msg(0, "Invalid browse mode set in file space."); return NULL; } @@ -398,7 +399,7 @@ FileSelectParams *ED_fileselect_get_active_params(const SpaceFile *sfile) return (FileSelectParams *)sfile->asset_params; } - BLI_assert(!"Invalid browse mode set in file space."); + BLI_assert_msg(0, "Invalid browse mode set in file space."); return NULL; } @@ -1046,7 +1047,7 @@ FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, ARegion *region) * Support updating the directory even when this isn't the active space * needed so RNA properties update function isn't context sensitive, see T70255. */ -void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area) +void ED_file_change_dir_ex(bContext *C, ScrArea *area) { /* May happen when manipulating non-active spaces. */ if (UNLIKELY(area->spacetype != SPACE_FILE)) { @@ -1056,10 +1057,7 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area) FileSelectParams *params = ED_fileselect_get_active_params(sfile); if (params) { wmWindowManager *wm = CTX_wm_manager(C); - Scene *scene = WM_windows_scene_get_from_screen(wm, screen); - if (LIKELY(scene != NULL)) { - ED_fileselect_clear(wm, scene, sfile); - } + ED_fileselect_clear(wm, sfile); /* Clear search string, it is very rare to want to keep that filter while changing dir, * and usually very annoying to keep it actually! */ @@ -1084,9 +1082,17 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area) void ED_file_change_dir(bContext *C) { - bScreen *screen = CTX_wm_screen(C); ScrArea *area = CTX_wm_area(C); - ED_file_change_dir_ex(C, screen, area); + ED_file_change_dir_ex(C, area); +} + +void file_select_deselect_all(SpaceFile *sfile, uint flag) +{ + FileSelection sel; + sel.first = 0; + sel.last = filelist_files_ensure(sfile->files) - 1; + + filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL); } int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file) @@ -1182,11 +1188,11 @@ int autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v)) return match; } -void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfile) +void ED_fileselect_clear(wmWindowManager *wm, SpaceFile *sfile) { /* only NULL in rare cases - T29734. */ if (sfile->files) { - filelist_readjob_stop(wm, owner_scene); + filelist_readjob_stop(sfile->files, wm); filelist_freelib(sfile->files); filelist_clear(sfile->files); } @@ -1196,7 +1202,7 @@ void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfi WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL); } -void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfile) +void ED_fileselect_exit(wmWindowManager *wm, SpaceFile *sfile) { if (!sfile) { return; @@ -1223,13 +1229,72 @@ void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfil folder_history_list_free(sfile); if (sfile->files) { - ED_fileselect_clear(wm, owner_scene, sfile); + ED_fileselect_clear(wm, sfile); filelist_free(sfile->files); MEM_freeN(sfile->files); sfile->files = NULL; } } +void file_params_smoothscroll_timer_clear(wmWindowManager *wm, wmWindow *win, SpaceFile *sfile) +{ + WM_event_remove_timer(wm, win, sfile->smoothscroll_timer); + sfile->smoothscroll_timer = NULL; +} + +/** + * Set the renaming-state to #FILE_PARAMS_RENAME_POSTSCROLL_PENDING and trigger the smooth-scroll + * timer. To be used right after a file was renamed. + * Note that the caller is responsible for setting the correct rename-file info + * (#FileSelectParams.renamefile or #FileSelectParams.rename_id). + */ +void file_params_invoke_rename_postscroll(wmWindowManager *wm, wmWindow *win, SpaceFile *sfile) +{ + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + + params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING; + + if (sfile->smoothscroll_timer != NULL) { + file_params_smoothscroll_timer_clear(wm, win, sfile); + } + sfile->smoothscroll_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 1000.0); + sfile->scroll_offset = 0; +} + +/** + * To be executed whenever renaming ends (successfully or not). + */ +void file_params_rename_end(wmWindowManager *wm, + wmWindow *win, + SpaceFile *sfile, + FileDirEntry *rename_file) +{ + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + + filelist_entry_select_set( + sfile->files, rename_file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL); + + /* Ensure smooth-scroll timer is active, even if not needed, because that way rename state is + * handled properly. */ + file_params_invoke_rename_postscroll(wm, win, sfile); + /* Also always activate the rename file, even if renaming was cancelled. */ + file_params_renamefile_activate(sfile, params); +} + +void file_params_renamefile_clear(FileSelectParams *params) +{ + params->renamefile[0] = '\0'; + params->rename_id = NULL; + params->rename_flag = 0; +} + +static int file_params_find_renamed(const FileSelectParams *params, struct FileList *filelist) +{ + /* Find the file either through the local ID/asset it represents or its relative path. */ + return (params->rename_id != NULL) ? filelist_file_find_id(filelist, params->rename_id) : + filelist_file_find_path(filelist, params->renamefile); +} + /** * Helper used by both main update code, and smooth-scroll timer, * to try to enable rename editing from #FileSelectParams.renamefile name. @@ -1243,28 +1308,33 @@ void file_params_renamefile_activate(SpaceFile *sfile, FileSelectParams *params) return; } - BLI_assert(params->renamefile[0] != '\0'); + BLI_assert(params->renamefile[0] != '\0' || params->rename_id != NULL); - const int idx = filelist_file_findpath(sfile->files, params->renamefile); + const int idx = file_params_find_renamed(params, sfile->files); if (idx >= 0) { FileDirEntry *file = filelist_file(sfile->files, idx); BLI_assert(file != NULL); + params->active_file = idx; + filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL); + if ((params->rename_flag & FILE_PARAMS_RENAME_PENDING) != 0) { filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL); params->rename_flag = FILE_PARAMS_RENAME_ACTIVE; } else if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_PENDING) != 0) { - filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL); - params->renamefile[0] = '\0'; + file_select_deselect_all(sfile, FILE_SEL_SELECTED); + filelist_entry_select_set( + sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED | FILE_SEL_HIGHLIGHTED, CHECK_ALL); + params->active_file = idx; + file_params_renamefile_clear(params); params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE; } } /* File listing is now async, only reset renaming if matching entry is not found * when file listing is not done. */ else if (filelist_is_ready(sfile->files)) { - params->renamefile[0] = '\0'; - params->rename_flag = 0; + file_params_renamefile_clear(params); } } diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 12bc0a68ca6..05d484d8e2e 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -32,6 +32,7 @@ #include "BKE_appdir.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_main.h" #include "BKE_screen.h" #include "RNA_access.h" @@ -206,7 +207,7 @@ static void file_exit(wmWindowManager *wm, ScrArea *area) sfile->previews_timer = NULL; } - ED_fileselect_exit(wm, NULL, sfile); + ED_fileselect_exit(wm, sfile); } static SpaceLink *file_duplicate(SpaceLink *sl) @@ -360,7 +361,7 @@ static void file_refresh(const bContext *C, ScrArea *area) sfile->recentnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_RECENT, params->dir); if (filelist_needs_force_reset(sfile->files)) { - filelist_readjob_stop(wm, CTX_data_scene(C)); + filelist_readjob_stop(sfile->files, wm); filelist_clear(sfile->files); } @@ -429,10 +430,10 @@ static void file_reset_filelist_showing_main_data(ScrArea *area, SpaceFile *sfil } } -static void file_listener(const wmSpaceTypeListenerParams *params) +static void file_listener(const wmSpaceTypeListenerParams *listener_params) { - ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; + ScrArea *area = listener_params->area; + wmNotifier *wmn = listener_params->notifier; SpaceFile *sfile = (SpaceFile *)area->spacedata.first; /* context changes */ @@ -469,10 +470,19 @@ static void file_listener(const wmSpaceTypeListenerParams *params) break; case NC_ID: { switch (wmn->action) { - case NA_RENAME: + case NA_RENAME: { + const ID *active_file_id = ED_fileselect_active_asset_get(sfile); + /* If a renamed ID is active in the file browser, update scrolling to keep it in view. */ + if (active_file_id && (wmn->reference == active_file_id)) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + params->rename_id = active_file_id; + file_params_invoke_rename_postscroll(G_MAIN->wm.first, listener_params->window, sfile); + } + /* Force list to update sorting (with a full reset for now). */ file_reset_filelist_showing_main_data(area, sfile); break; + } } break; } @@ -508,10 +518,10 @@ 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(const wmRegionListenerParams *params) +static void file_main_region_listener(const wmRegionListenerParams *listener_params) { - ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + ARegion *region = listener_params->region; + wmNotifier *wmn = listener_params->notifier; /* context changes */ switch (wmn->category) { @@ -675,6 +685,7 @@ static void file_operatortypes(void) WM_operatortype_append(FILE_OT_bookmark_move); WM_operatortype_append(FILE_OT_reset_recent); WM_operatortype_append(FILE_OT_hidedot); + WM_operatortype_append(FILE_OT_associate_blend); WM_operatortype_append(FILE_OT_filenum); WM_operatortype_append(FILE_OT_directory_new); WM_operatortype_append(FILE_OT_delete); @@ -715,14 +726,14 @@ static void file_tools_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void file_tools_region_listener(const wmRegionListenerParams *UNUSED(params)) +static void file_tools_region_listener(const wmRegionListenerParams *UNUSED(listener_params)) { } -static void file_tool_props_region_listener(const wmRegionListenerParams *params) +static void file_tool_props_region_listener(const wmRegionListenerParams *listener_params) { - const wmNotifier *wmn = params->notifier; - ARegion *region = params->region; + const wmNotifier *wmn = listener_params->notifier; + ARegion *region = listener_params->region; switch (wmn->category) { case NC_ID: @@ -788,10 +799,10 @@ static void file_execution_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void file_ui_region_listener(const wmRegionListenerParams *params) +static void file_ui_region_listener(const wmRegionListenerParams *listener_params) { - ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + ARegion *region = listener_params->region; + wmNotifier *wmn = listener_params->notifier; /* context changes */ switch (wmn->category) { diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index d88bf8750c2..ec5f443e2dc 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -1337,8 +1337,8 @@ static void do_graph_region_modifier_buttons(bContext *C, void *UNUSED(arg), int { switch (event) { case B_FMODIFIER_REDRAW: /* XXX this should send depsgraph updates too */ - WM_event_add_notifier( - C, NC_ANIMATION, NULL); /* XXX need a notifier specially for F-Modifiers */ + /* XXX: need a notifier specially for F-Modifiers */ + WM_event_add_notifier(C, NC_ANIMATION, NULL); break; } } diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index c5358cdfa5b..56592cbbd1b 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -414,7 +414,7 @@ static bool draw_fcurve_handles_check(SpaceGraph *sipo, FCurve *fcu) } /* draw lines for F-Curve handles only (this is only done in EditMode) - * note: draw_fcurve_handles_check must be checked before running this. */ + * NOTE: draw_fcurve_handles_check must be checked before running this. */ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu) { int sel, b; @@ -1251,7 +1251,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) float x = driver->curval; float y = fcu->curval * unitfac; - /* only draw indicators if the point is in range*/ + /* Only draw indicators if the point is in range. */ if (x >= v2d->cur.xmin) { float co[2]; @@ -1428,7 +1428,7 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region) height = ACHANNEL_TOT_HEIGHT(ac, items); v2d->tot.ymin = -height; - /* loop through channels, and set up drawing depending on their type */ + /* Loop through channels, and set up drawing depending on their type. */ { /* first pass: just the standard GL-drawing for backdrop + text */ size_t channel_index = 0; float ymax = ACHANNEL_FIRST_TOP(ac); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index a2e812a4ed1..6f1b0bb0d7d 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -1481,7 +1481,7 @@ static void setipo_graph_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Loop through setting BezTriple interpolation - * Note: we do not supply KeyframeEditData to the looper yet. + * NOTE: we do not supply KeyframeEditData to the looper yet. * Currently that's not necessary here. */ for (ale = anim_data.first; ale; ale = ale->next) { @@ -1558,7 +1558,7 @@ static void seteasing_graph_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Loop through setting BezTriple easing. - * Note: we do not supply KeyframeEditData to the looper yet. + * NOTE: we do not supply KeyframeEditData to the looper yet. * Currently that's not necessary here. */ for (ale = anim_data.first; ale; ale = ale->next) { @@ -1636,7 +1636,7 @@ static void sethandles_graph_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Loop through setting flags for handles. - * Note: we do not supply KeyframeEditData to the looper yet. + * NOTE: we do not supply KeyframeEditData to the looper yet. * Currently that's not necessary here. */ for (ale = anim_data.first; ale; ale = ale->next) { @@ -3007,7 +3007,7 @@ static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op) WM_report(RPT_INFO, "No drivers deleted"); } - /* Successful or not?*/ + /* Successful or not? */ if (!ok) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 4ab4ef518fb..1421be41124 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -167,7 +167,7 @@ static void nearest_fcurve_vert_store(ListBase *matches, } } else if (fpt) { - /* TODO... */ + /* TODO: support #FPoint. */ } } @@ -257,7 +257,7 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L } } else if (fcu->fpt) { - /* TODO; do this for samples too */ + /* TODO: do this for samples too. */ } /* un-apply NLA mapping from all the keyframes */ @@ -512,16 +512,19 @@ static rctf initialize_box_select_coords(const bAnimContext *ac, const rctf *rec return rectf; } -static ListBase initialize_box_select_anim_data(const SpaceGraph *sipo, bAnimContext *ac) +static int initialize_animdata_selection_filter(const SpaceGraph *sipo) { - ListBase anim_data = {NULL, NULL}; - int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); if (sipo->flag & SIPO_SELCUVERTSONLY) { filter |= ANIMFILTER_FOREDIT | ANIMFILTER_SELEDIT; } - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + return filter; +} +static ListBase initialize_box_select_anim_data(const int filter, bAnimContext *ac) +{ + ListBase anim_data = {NULL, NULL}; + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); return anim_data; } @@ -573,8 +576,11 @@ static void initialize_box_select_key_editing_data(const SpaceGraph *sipo, * which means that they may be inadvertently moved as well. However, incl_handles overrides * this, and allow handles to be considered independently too. * Also, for convenience, handles should get same status as keyframe (if it was within bounds). + * + * This function returns true if there was any change in the selection of a key (selecting or + * deselecting any key returns true, otherwise it returns false). */ -static void box_select_graphkeys(bAnimContext *ac, +static bool box_select_graphkeys(bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, @@ -583,20 +589,24 @@ static void box_select_graphkeys(bAnimContext *ac, { const rctf rectf = initialize_box_select_coords(ac, rectf_view); SpaceGraph *sipo = (SpaceGraph *)ac->sl; - ListBase anim_data = initialize_box_select_anim_data(sipo, ac); + const int filter = initialize_animdata_selection_filter(sipo); + ListBase anim_data = initialize_box_select_anim_data(filter, ac); rctf scaled_rectf; KeyframeEditData ked; int mapping_flag; initialize_box_select_key_editing_data( sipo, incl_handles, mode, ac, data, &scaled_rectf, &ked, &mapping_flag); - /* Get beztriple editing/validation funcs. */ + /* Get beztriple editing/validation funcs. */ const KeyframeEditFunc select_cb = ANIM_editkeyframes_select(selectmode); const KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(mode); /* Try selecting the keyframes. */ bAnimListElem *ale = NULL; + /* This variable will be set to true if any key is selected or deselected. */ + bool any_key_selection_changed = false; + /* First loop over data, doing box select. try selecting keys only. */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); @@ -634,7 +644,7 @@ static void box_select_graphkeys(bAnimContext *ac, if (ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, ok_cb, NULL)) { /* select keyframes that are in the appropriate places */ ANIM_fcurve_keyframes_loop(&ked, fcu, ok_cb, select_cb, NULL); - + any_key_selection_changed = true; /* Only change selection of channel when the visibility of keyframes * doesn't depend on this. */ if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) { @@ -653,6 +663,143 @@ static void box_select_graphkeys(bAnimContext *ac, /* Cleanup. */ ANIM_animdata_freelist(&anim_data); + + return any_key_selection_changed; +} + +/* This function is used to set all the keyframes of a given curve as selectable + * by the "select_cb" function inside of "box_select_graphcurves". + */ +static short ok_bezier_always_ok(KeyframeEditData *UNUSED(ked), BezTriple *UNUSED(bezt)) +{ + return KEYFRAME_OK_KEY | KEYFRAME_OK_H1 | KEYFRAME_OK_H2; +} + +#define ABOVE 1 +#define INSIDE 0 +#define BELOW -1 +static int rectf_curve_zone_y( + FCurve *fcu, const rctf *rectf, const float offset, const float unit_scale, const float eval_x) +{ + const float fcurve_y = (evaluate_fcurve(fcu, eval_x) + offset) * unit_scale; + return fcurve_y < rectf->ymin ? BELOW : fcurve_y <= rectf->ymax ? INSIDE : ABOVE; +} + +/* Checks whether the given rectangle intersects the given fcurve's calculated curve (i.e. not + * only keyframes, but also all the interpolated values). This is done by sampling the curve at + * different points between the xmin and the xmax of the rectangle. + */ +static bool rectf_curve_intersection( + const float offset, const float unit_scale, const rctf *rectf, AnimData *adt, FCurve *fcu) +{ + /* 30 sampling points. This worked well in tests. */ + int num_steps = 30; + + /* Remap the range at which to evaluate the fcurves. This enables us to avoid remapping + * the keys themselves. */ + const float mapped_max = BKE_nla_tweakedit_remap(adt, rectf->xmax, NLATIME_CONVERT_UNMAP); + const float mapped_min = BKE_nla_tweakedit_remap(adt, rectf->xmin, NLATIME_CONVERT_UNMAP); + const float eval_step = (mapped_max - mapped_min) / num_steps; + + /* Sample points on the given fcurve in the interval defined by the + * mapped_min and mapped_max of the selected rectangle. + * For each point, check if it is inside of the selection box. If it is, then select + * all the keyframes of the curve, the curve, and stop the loop. + */ + struct { + float eval_x; + int zone; + } cur, prev; + + prev.eval_x = mapped_min; + prev.zone = rectf_curve_zone_y(fcu, rectf, offset, unit_scale, prev.eval_x); + if (prev.zone == INSIDE) { + return true; + } + + while (num_steps--) { + cur.eval_x = prev.eval_x + eval_step; + cur.zone = rectf_curve_zone_y(fcu, rectf, offset, unit_scale, cur.eval_x); + if (cur.zone != prev.zone) { + return true; + } + + prev = cur; + } + return false; +} +#undef ABOVE +#undef INSIDE +#undef BELOW + +/* Perform a box selection of the curves themselves. This means this function tries + * to select a curve by sampling it at various points instead of trying to select the + * keyframes directly. + * The selection actions done to a curve are actually done on all the keyframes of the curve. + * NOTE: This function is only called if no keyframe is in the selection area. + */ +static void box_select_graphcurves(bAnimContext *ac, + const rctf *rectf_view, + const short mode, + const short selectmode, + const bool incl_handles, + void *data) +{ + const SpaceGraph *sipo = (SpaceGraph *)ac->sl; + const int filter = initialize_animdata_selection_filter(sipo); + ListBase anim_data = initialize_box_select_anim_data(filter, ac); + rctf scaled_rectf; + KeyframeEditData ked; + int mapping_flag; + initialize_box_select_key_editing_data( + sipo, incl_handles, mode, ac, data, &scaled_rectf, &ked, &mapping_flag); + + FCurve *last_selected_curve = NULL; + + /* Go through all the curves and try selecting them. This function is only called + * if no keyframe is in the selection area, so we only have to check if the curve + * intersects the area in order to check if the selection/deselection must happen. + */ + + LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) { + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + FCurve *fcu = (FCurve *)ale->key_data; + float offset; + const float unit_scale = ANIM_unit_mapping_get_factor( + ac->scene, ale->id, fcu, mapping_flag, &offset); + + const rctf rectf = initialize_box_select_coords(ac, rectf_view); + + /* scaled_rectf is declared at the top of the block because it is required by the + * initialize_box_select_key_editing_data function (which does + * data_xxx->rectf_scaled = scaled_rectf). The below assignment therefore modifies the + * data we use to iterate over the curves (ked). + */ + scaled_rectf.xmin = rectf.xmin; + scaled_rectf.xmax = rectf.xmax; + scaled_rectf.ymin = rectf.ymin / unit_scale - offset; + scaled_rectf.ymax = rectf.ymax / unit_scale - offset; + + const KeyframeEditFunc select_cb = ANIM_editkeyframes_select(selectmode); + if (rectf_curve_intersection(offset, unit_scale, &rectf, adt, fcu)) { + if ((selectmode & SELECT_ADD) || (selectmode & SELECT_REPLACE)) { + fcu->flag |= FCURVE_SELECTED; + last_selected_curve = fcu; + } + else { + fcu->flag &= ~FCURVE_SELECTED; + } + ANIM_fcurve_keyframes_loop(&ked, fcu, ok_bezier_always_ok, select_cb, NULL); + } + } + + /* Make sure that one of the selected curves is active in the end. */ + if (last_selected_curve != NULL) { + ANIM_set_active_channel( + ac, ac->data, ac->datatype, filter, last_selected_curve, ANIMTYPE_FCURVE); + } + + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ @@ -726,7 +873,12 @@ static int graphkeys_box_select_exec(bContext *C, wmOperator *op) BLI_rctf_rcti_copy(&rect_fl, &rect); /* Apply box_select action. */ - box_select_graphkeys(&ac, &rect_fl, mode, selectmode, incl_handles, NULL); + const bool any_key_selection_changed = box_select_graphkeys( + &ac, &rect_fl, mode, selectmode, incl_handles, NULL); + const bool use_curve_selection = RNA_boolean_get(op->ptr, "use_curve_selection"); + if (use_curve_selection && !any_key_selection_changed) { + box_select_graphcurves(&ac, &rect_fl, mode, selectmode, incl_handles, NULL); + } /* Send notifier that keyframe selection has changed. */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); @@ -767,6 +919,14 @@ void GRAPH_OT_select_box(wmOperatorType *ot) ot->srna, "tweak", 0, "Tweak", "Operator has been activated using a tweak event"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, + "use_curve_selection", + 1, + "Select Curves", + "Allow selecting all the keyframes of a curve by selecting the calculated fcurve"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + WM_operator_properties_gesture_box(ot); WM_operator_properties_select_operation_simple(ot); } @@ -815,7 +975,13 @@ static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op) BLI_rctf_rcti_copy(&rect_fl, &rect); /* Apply box_select action. */ - box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso); + const bool any_key_selection_changed = box_select_graphkeys( + &ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso); + const bool use_curve_selection = RNA_boolean_get(op->ptr, "use_curve_selection"); + if (use_curve_selection && !any_key_selection_changed) { + box_select_graphcurves( + &ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso); + } MEM_freeN((void *)data_lasso.mcoords); @@ -845,6 +1011,13 @@ void GRAPH_OT_select_lasso(wmOperatorType *ot) /* Properties. */ WM_operator_properties_gesture_lasso(ot); WM_operator_properties_select_operation_simple(ot); + PropertyRNA *prop = RNA_def_boolean( + ot->srna, + "use_curve_selection", + 1, + "Select Curves", + "Allow selecting all the keyframes of a curve by selecting the curve itself"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ------------------- */ @@ -894,7 +1067,12 @@ static int graph_circle_select_exec(bContext *C, wmOperator *op) } /* Apply box_select action. */ - box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data); + const bool any_key_selection_changed = box_select_graphkeys( + &ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data); + const bool use_curve_selection = RNA_boolean_get(op->ptr, "use_curve_selection"); + if (use_curve_selection && !any_key_selection_changed) { + box_select_graphcurves(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data); + } /* Send notifier that keyframe selection has changed. */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); @@ -920,6 +1098,13 @@ void GRAPH_OT_select_circle(wmOperatorType *ot) /* properties */ WM_operator_properties_gesture_circle(ot); WM_operator_properties_select_operation_simple(ot); + PropertyRNA *prop = RNA_def_boolean( + ot->srna, + "use_curve_selection", + 1, + "Select Curves", + "Allow selecting all the keyframes of a curve by selecting the curve itself"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ******************** Column Select Operator **************************** */ @@ -946,8 +1131,8 @@ static const EnumPropertyItem prop_column_select_types[] = { /* ------------------- */ /* Selects all visible keyframes between the specified markers */ -/* TODO, this is almost an _exact_ duplicate of a function of the same name in action_select.c - * should de-duplicate - campbell */ +/* TODO(campbell): this is almost an _exact_ duplicate of a function of the same name in + * action_select.c should de-duplicate. */ static void markers_selectkeys_between(bAnimContext *ac) { ListBase anim_data = {NULL, NULL}; @@ -1426,7 +1611,7 @@ void GRAPH_OT_select_leftright(wmOperatorType *ot) ot->idname = "GRAPH_OT_select_leftright"; ot->description = "Select keyframes to the left or the right of the current frame"; - /* api callbacks */ + /* api callbacks */ ot->invoke = graphkeys_select_leftright_invoke; ot->exec = graphkeys_select_leftright_exec; ot->poll = graphop_visible_keyframes_poll; @@ -1496,10 +1681,8 @@ static int mouse_graph_keys(bAnimContext *ac, /* deselect all other keyframes (+ F-Curves too) */ deselect_graph_keys(ac, 0, SELECT_SUBTRACT, true); - /* deselect other channels too, but only only do this if - * selection of channel when the visibility of keyframes - * doesn't depend on this - */ + /* Deselect other channels too, but only do this if selection of channel + * when the visibility of keyframes doesn't depend on this. */ if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) { ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_CLEAR); } @@ -1638,7 +1821,6 @@ static int graphkeys_mselect_column(bAnimContext *ac, KeyframeEditFunc select_cb, ok_cb; KeyframeEditData ked; tNearestVertInfo *nvi; - float selx = (float)ac->scene->r.cfra; /* find the beztriple that we're selecting, and the handle that was clicked on */ nvi = find_nearest_fcurve_vert(ac, mval); @@ -1650,7 +1832,7 @@ static int graphkeys_mselect_column(bAnimContext *ac, /* get frame number on which elements should be selected */ /* TODO: should we restrict to integer frames only? */ - selx = nvi->frame; + const float selx = nvi->frame; if (select_mode != SELECT_REPLACE) { /* Doesn't need to deselect anything -> Pass. */ @@ -1774,12 +1956,14 @@ void GRAPH_OT_clickselect(wmOperatorType *ot) /* properties */ WM_operator_properties_generic_select(ot); + + /* Key-map: Enable with `Shift`. */ prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Toggle keyframe selection instead of leaving newly selected " - "keyframes only"); /* SHIFTKEY */ + "keyframes only"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, @@ -1789,19 +1973,18 @@ void GRAPH_OT_clickselect(wmOperatorType *ot) "Deselect all when nothing under the cursor"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + /* Key-map: Enable with `Alt`. */ prop = RNA_def_boolean(ot->srna, "column", 0, "Column Select", "Select all keyframes that occur on the same frame as the one under " - "the mouse"); /* ALTKEY */ + "the mouse"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, - "curves", - 0, - "Only Curves", - "Select all the keyframes in the curve"); /* CTRLKEY + ALTKEY */ + /* Key-map: Enable with `Ctrl-Atl`. */ + prop = RNA_def_boolean( + ot->srna, "curves", 0, "Only Curves", "Select all the keyframes in the curve"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/space_graph/graph_slider_ops.c b/source/blender/editors/space_graph/graph_slider_ops.c index 4174e1c63ae..10629caa8b0 100644 --- a/source/blender/editors/space_graph/graph_slider_ops.c +++ b/source/blender/editors/space_graph/graph_slider_ops.c @@ -50,7 +50,7 @@ /* ******************** GRAPH SLIDER OPERATORS ************************* */ /* This file contains a collection of operators to modify keyframes in the graph editor. All * operators are modal and use a slider that allows the user to define a percentage to modify the - * operator.*/ + * operator. */ /* ******************** Decimate Keyframes Operator ************************* */ @@ -91,7 +91,7 @@ typedef struct tDecimateGraphOp { /** A 0-1 value for determining how much we should decimate. */ PropertyRNA *percentage_prop; - /** The original bezt curve data (used for restoring fcurves).*/ + /** The original bezt curve data (used for restoring fcurves). */ ListBase bezt_arr_list; NumInput num; @@ -318,7 +318,7 @@ static int graphkeys_decimate_modal(bContext *C, wmOperator *op, const wmEvent * /* This assumes that we are in "DECIM_RATIO" mode. This is because the error margin is very hard * and finicky to control with this modal mouse grab method. Therefore, it is expected that the * error margin mode is not adjusted by the modal operator but instead tweaked via the redo - * panel.*/ + * panel. */ tDecimateGraphOp *dgo = op->customdata; const bool has_numinput = hasNumInput(&dgo->num); diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index cde0dab3503..31c53cde62c 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -51,7 +51,7 @@ /* *************************** Calculate Range ************************** */ /* Get the min/max keyframes. */ -/* Note: it should return total boundbox, filter for selection only can be argument... */ +/* NOTE: it should return total boundbox, filter for selection only can be argument... */ void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, @@ -137,7 +137,7 @@ void get_graph_keyframe_extents(bAnimContext *ac, } } - /* Ensure that the extents are not too extreme that view implodes...*/ + /* Ensure that the extents are not too extreme that view implodes. */ if (foundBounds) { if ((xmin && xmax) && (fabsf(*xmax - *xmin) < 0.001f)) { *xmin -= 0.0005f; @@ -269,7 +269,7 @@ static int graphkeys_viewall(bContext *C, BLI_rctf_scale(&cur_new, 1.1f); /* Take regions into account, that could block the view. - * Marker region is supposed to be larger than the scroll-bar, so prioritize it.*/ + * Marker region is supposed to be larger than the scroll-bar, so prioritize it. */ float pad_top = UI_TIME_SCRUB_MARGIN_Y; float pad_bottom = BLI_listbase_is_empty(ED_context_get_markers(C)) ? V2D_SCROLL_HANDLE_HEIGHT : UI_MARKER_MARGIN_Y; diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 9f01773eadf..49966e880d3 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -172,6 +172,8 @@ static SpaceLink *graph_duplicate(SpaceLink *sl) { SpaceGraph *sipon = MEM_dupallocN(sl); + memset(&sipon->runtime, 0x0, sizeof(sipon->runtime)); + /* clear or remove stuff from old */ BLI_duplicatelist(&sipon->runtime.ghost_curves, &((SpaceGraph *)sl)->runtime.ghost_curves); sipon->ads = MEM_dupallocN(sipon->ads); @@ -227,7 +229,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *region) graph_draw_curves(&ac, sipo, region, 0); graph_draw_curves(&ac, sipo, region, 1); - /* XXX the slow way to set tot rect... but for nice sliders needed (ton) */ + /* XXX(ton): the slow way to set tot rect... but for nice sliders needed. */ get_graph_keyframe_extents( &ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax, false, true); /* extra offset so that these items are visible */ @@ -586,7 +588,7 @@ static void graph_listener(const wmSpaceTypeListenerParams *params) ED_area_tag_refresh(area); break; case ND_TRANSFORM: - break; /*do nothing*/ + break; /* Do nothing. */ default: /* just redrawing the view will do */ ED_area_tag_redraw(area); @@ -757,7 +759,7 @@ static void graph_refresh(const bContext *C, ScrArea *area) break; } - case SIPO_MODE_DRIVERS: /* drivers only */ + case SIPO_MODE_DRIVERS: /* Drivers only. */ { break; } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 6fb64de7e85..50b0ea75052 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -511,7 +511,7 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt return false; } - /* note, this looks reversed, but matches menu direction */ + /* NOTE: this looks reversed, but matches menu direction. */ if (direction == -1) { RenderPass *rp; int rp_index = iuser->pass + 1; @@ -1218,11 +1218,12 @@ void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *i const int len = MAX_IMAGE_INFO_LEN; int ofs = 0; - ofs += BLI_snprintf(str + ofs, len - ofs, TIP_("%d x %d, "), ibuf->x, ibuf->y); + ofs += BLI_snprintf_rlen(str + ofs, len - ofs, TIP_("%d x %d, "), ibuf->x, ibuf->y); if (ibuf->rect_float) { if (ibuf->channels != 4) { - ofs += BLI_snprintf(str + ofs, len - ofs, TIP_("%d float channel(s)"), ibuf->channels); + ofs += BLI_snprintf_rlen( + str + ofs, len - ofs, TIP_("%d float channel(s)"), ibuf->channels); } else if (ibuf->planes == R_IMF_PLANES_RGBA) { ofs += BLI_strncpy_rlen(str + ofs, TIP_(" RGBA float"), len - ofs); diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index c26f92c5463..169dafcb8d0 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -51,7 +51,7 @@ #include "WM_api.h" #include "WM_types.h" -/* note; image_panel_properties() uses pointer to sima->image directly */ +/* NOTE: image_panel_properties() uses pointer to sima->image directly. */ Image *ED_space_image(SpaceImage *sima) { return sima->image; @@ -64,8 +64,6 @@ void ED_space_image_set(Main *bmain, SpaceImage *sima, Object *obedit, Image *im sima->pin = true; } - /* change the space ima after because uvedit_face_visible_test uses the space ima - * to check if the face is displayed in UV-localview */ sima->image = ima; if (ima == NULL || ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE) { diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 6053253790a..6b9821745c7 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1311,7 +1311,6 @@ static int image_open_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); ImageUser *iuser = NULL; - ImageOpenData *iod = op->customdata; Image *ima = NULL; int frame_seq_len = 0; int frame_ofs = 1; @@ -1345,7 +1344,7 @@ static int image_open_exec(bContext *C, wmOperator *op) } /* hook into UI */ - iod = op->customdata; + ImageOpenData *iod = op->customdata; if (iod->pprop.prop) { /* when creating new ID blocks, use is already 1, but RNA @@ -1608,7 +1607,7 @@ static int image_replace_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "filepath", str); - /* we cant do much if the str is longer than FILE_MAX :/ */ + /* we can't do much if the str is longer than FILE_MAX :/ */ BLI_strncpy(sima->image->filepath, str, sizeof(sima->image->filepath)); if (sima->image->source == IMA_SRC_GENERATED) { @@ -2713,10 +2712,10 @@ static int image_flip_exec(bContext *C, wmOperator *op) 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"); + const bool use_flip_x = RNA_boolean_get(op->ptr, "use_flip_x"); + const bool use_flip_y = RNA_boolean_get(op->ptr, "use_flip_y"); - if (!flip_horizontal && !flip_vertical) { + if (!use_flip_x && !use_flip_y) { BKE_image_release_ibuf(ima, ibuf, NULL); return OPERATOR_FINISHED; } @@ -2735,11 +2734,12 @@ static int image_flip_exec(bContext *C, wmOperator *op) float *orig_float_pixels = MEM_dupallocN(float_pixels); for (int x = 0; x < size_x; x++) { + const int source_pixel_x = use_flip_x ? size_x - x - 1 : 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; + const int source_pixel_y = use_flip_y ? size_y - y - 1 : y; - float *source_pixel = &orig_float_pixels[4 * (source_pixel_x + source_pixel_y * size_x)]; + const 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); @@ -2755,11 +2755,12 @@ static int image_flip_exec(bContext *C, wmOperator *op) char *char_pixels = (char *)ibuf->rect; char *orig_char_pixels = MEM_dupallocN(char_pixels); for (int x = 0; x < size_x; x++) { + const int source_pixel_x = use_flip_x ? size_x - x - 1 : 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; + const int source_pixel_y = use_flip_y ? size_y - y - 1 : y; - char *source_pixel = &orig_char_pixels[4 * (source_pixel_x + source_pixel_y * size_x)]; + const 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); @@ -2805,10 +2806,9 @@ void IMAGE_OT_flip(wmOperatorType *ot) /* properties */ PropertyRNA *prop; prop = RNA_def_boolean( - ot->srna, "use_flip_horizontal", false, "Horizontal", "Flip the image horizontally"); + ot->srna, "use_flip_x", 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"); + prop = RNA_def_boolean(ot->srna, "use_flip_y", false, "Vertical", "Flip the image vertically"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); /* flags */ @@ -3871,7 +3871,7 @@ static void tile_fill_init(PointerRNA *ptr, Image *ima, ImageTile *tile) /* Acquire ibuf to get the default values. * If the specified tile has no ibuf, try acquiring the main tile instead - * (unless the specified tile already was the main tile).*/ + * (unless the specified tile already was the main tile). */ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); if (ibuf == NULL && (tile != NULL) && (tile->tile_number != 1001)) { ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c index feee268c6d3..cc6effd0f71 100644 --- a/source/blender/editors/space_image/image_undo.c +++ b/source/blender/editors/space_image/image_undo.c @@ -293,8 +293,9 @@ static void ptile_restore_runtime_list(ListBase *paint_tiles) SWAP(uint *, ptile->rect.uint, tmpibuf->rect); } - BKE_image_free_gputextures( - image); /* force OpenGL reload (maybe partial update will operate better?) */ + /* Force OpenGL reload (maybe partial update will operate better?) */ + BKE_image_free_gputextures(image); + if (ibuf->rect_float) { ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */ } @@ -1005,7 +1006,7 @@ void ED_image_undosys_type(UndoType *ut) * specific case, see `image_undosys_step_encode` code. We cannot specify * `UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE` though, as it can be called with a NULL context by * current code. */ - ut->flags = 0; + ut->flags = UNDOTYPE_FLAG_DECODE_ACTIVE_STEP; ut->step_size = sizeof(ImageUndoStep); } @@ -1040,7 +1041,7 @@ ListBase *ED_image_paint_tile_list_get(void) return &us->paint_tiles; } -/* restore painting image to previous state. Used for anchored and drag-dot style brushes*/ +/* Restore painting image to previous state. Used for anchored and drag-dot style brushes. */ void ED_image_undo_restore(UndoStep *us) { ListBase *paint_tiles = &((ImageUndoStep *)us)->paint_tiles; diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c index be3b60d581b..9524c2a1d8a 100644 --- a/source/blender/editors/space_info/info_draw.c +++ b/source/blender/editors/space_info/info_draw.c @@ -134,14 +134,12 @@ static void report_textview_end(TextViewContext *UNUSED(tvc)) static int report_textview_step(TextViewContext *tvc) { /* simple case, but no newline support */ - const Report *report = tvc->iter; - if (tvc->iter_char_begin <= 0) { tvc->iter = (void *)((Link *)tvc->iter)->prev; if (tvc->iter && report_textview_skip__internal(tvc)) { tvc->iter_tmp++; - report = tvc->iter; + const Report *report = tvc->iter; tvc->iter_char_end = report->len; /* reset start */ report_textview_init__internal(tvc); diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index aaf9852e212..94e53958524 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -564,12 +564,11 @@ void FILE_OT_find_missing_files(wmOperatorType *ot) /** \name Report Box Operator * \{ */ -/* Hard to decide whether to keep this as an operator, - * or turn it into a hardcoded ui control feature, - * handling TIMER events for all regions in interface_handlers.c +/* NOTE(matt): Hard to decide whether to keep this as an operator, + * or turn it into a hard_coded UI control feature, + * handling TIMER events for all regions in `interface_handlers.c`. * Not sure how good that is to be accessing UI data from - * inactive regions, so use this for now. --matt - */ + * inactive regions, so use this for now. */ #define INFO_TIMEOUT 5.0f #define ERROR_TIMEOUT 10.0f diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c index 7dd8382c8ef..1062b76b1df 100644 --- a/source/blender/editors/space_info/info_report.c +++ b/source/blender/editors/space_info/info_report.c @@ -102,7 +102,7 @@ int info_report_mask(const SpaceInfo *UNUSED(sinfo)) static int report_replay_exec(bContext *C, wmOperator *UNUSED(op)) { - /* TODO, get this working again! */ + /* TODO: get this working again! */ #if 0 SpaceInfo *sc = CTX_wm_space_info(C); ReportList *reports = CTX_wm_reports(C); @@ -360,7 +360,7 @@ void INFO_OT_report_delete(wmOperatorType *ot) ot->exec = report_delete_exec; /* flags */ - /*ot->flag = OPTYPE_REGISTER;*/ + // ot->flag = OPTYPE_REGISTER; /* properties */ } @@ -404,7 +404,7 @@ void INFO_OT_report_copy(wmOperatorType *ot) ot->exec = report_copy_exec; /* flags */ - /*ot->flag = OPTYPE_REGISTER;*/ + // ot->flag = OPTYPE_REGISTER; /* properties */ } diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 0bdfceb36b6..d7671a372c6 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -31,6 +31,7 @@ #include "DNA_mesh_types.h" #include "DNA_meta_types.h" #include "DNA_scene_types.h" +#include "DNA_space_types.h" #include "DNA_windowmanager_types.h" #include "BLF_api.h" @@ -63,6 +64,8 @@ #include "ED_info.h" +#include "WM_api.h" + #include "UI_resources.h" #include "GPU_capabilities.h" @@ -93,7 +96,7 @@ typedef struct SceneStatsFmt { char totgpstroke[MAX_INFO_NUM_LEN], totgppoint[MAX_INFO_NUM_LEN]; } SceneStatsFmt; -static bool stats_mesheval(Mesh *me_eval, bool is_selected, SceneStats *stats) +static bool stats_mesheval(const Mesh *me_eval, bool is_selected, SceneStats *stats) { if (me_eval == NULL) { return false; @@ -123,12 +126,19 @@ static bool stats_mesheval(Mesh *me_eval, bool is_selected, SceneStats *stats) return true; } -static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset) +static void stats_object(Object *ob, + const View3D *v3d_local, + SceneStats *stats, + GSet *objects_gset) { if ((ob->base_flag & BASE_VISIBLE_VIEWLAYER) == 0) { return; } + if (v3d_local && !BKE_object_is_visible_in_viewport(v3d_local, ob)) { + return; + } + const bool is_selected = (ob->base_flag & BASE_SELECTED) != 0; stats->totobj++; @@ -139,8 +149,8 @@ static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset) switch (ob->type) { case OB_MESH: { /* we assume evaluated mesh is already built, this strictly does stats now. */ - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); - if (!BLI_gset_add(objects_gset, me_eval)) { + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); + if (!BLI_gset_add(objects_gset, (void *)me_eval)) { break; } stats_mesheval(me_eval, is_selected, stats); @@ -155,8 +165,8 @@ static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset) case OB_SURF: case OB_CURVE: case OB_FONT: { - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); - if ((me_eval != NULL) && !BLI_gset_add(objects_gset, me_eval)) { + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); + if ((me_eval != NULL) && !BLI_gset_add(objects_gset, (void *)me_eval)) { break; } @@ -169,7 +179,7 @@ static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset) int totv = 0, totf = 0, tottri = 0; if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first) { - /* Note: We only get the same curve_cache for instances of the same curve/font/... + /* NOTE: We only get the same curve_cache for instances of the same curve/font/... * For simple linked duplicated objects, each has its own dispList. */ if (!BLI_gset_add(objects_gset, ob->runtime.curve_cache)) { break; @@ -334,7 +344,7 @@ static void stats_object_edit(Object *obedit, SceneStats *stats) } } -static void stats_object_pose(Object *ob, SceneStats *stats) +static void stats_object_pose(const Object *ob, SceneStats *stats) { if (ob->pose) { bArmature *arm = ob->data; @@ -351,16 +361,13 @@ static void stats_object_pose(Object *ob, SceneStats *stats) } } -static bool stats_is_object_dynamic_topology_sculpt(Object *ob) +static bool stats_is_object_dynamic_topology_sculpt(const Object *ob) { - if (ob == NULL) { - return false; - } - const eObjectMode object_mode = ob->mode; - return ((object_mode & OB_MODE_SCULPT) && ob->sculpt && ob->sculpt->bm); + BLI_assert(ob->mode & OB_MODE_SCULPT); + return (ob->sculpt && ob->sculpt->bm); } -static void stats_object_sculpt(Object *ob, SceneStats *stats) +static void stats_object_sculpt(const Object *ob, SceneStats *stats) { SculptSession *ss = ob->sculpt; @@ -386,81 +393,118 @@ static void stats_object_sculpt(Object *ob, SceneStats *stats) } /* Statistics displayed in info header. Called regularly on scene changes. */ -static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer) +static void stats_update(Depsgraph *depsgraph, + ViewLayer *view_layer, + View3D *v3d_local, + SceneStats *stats) { - SceneStats stats = {0}; - Object *ob = OBACT(view_layer); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + const Object *ob = OBACT(view_layer); + const Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + + memset(stats, 0x0, sizeof(*stats)); if (obedit) { - /* Edit Mode */ + /* Edit Mode. */ FOREACH_OBJECT_BEGIN (view_layer, ob_iter) { if (ob_iter->base_flag & BASE_VISIBLE_VIEWLAYER) { - if (ob_iter->mode == OB_MODE_EDIT) { - stats_object_edit(ob_iter, &stats); - stats.totobjsel++; + if (ob_iter->mode & OB_MODE_EDIT) { + stats_object_edit(ob_iter, stats); + stats->totobjsel++; } - stats.totobj++; + else { + /* Skip hidden objects in local view that are not in edit-mode, + * an exception for edit-mode, in most other modes these would be considered hidden. */ + if ((v3d_local && !BKE_object_is_visible_in_viewport(v3d_local, ob_iter))) { + continue; + } + } + stats->totobj++; } } FOREACH_OBJECT_END; } else if (ob && (ob->mode & OB_MODE_POSE)) { - /* Pose Mode */ - stats_object_pose(ob, &stats); + /* Pose Mode. */ + FOREACH_OBJECT_BEGIN (view_layer, ob_iter) { + if (ob_iter->base_flag & BASE_VISIBLE_VIEWLAYER) { + if (ob_iter->mode & OB_MODE_POSE) { + stats_object_pose(ob_iter, stats); + stats->totobjsel++; + } + else { + /* See comment for edit-mode. */ + if ((v3d_local && !BKE_object_is_visible_in_viewport(v3d_local, ob_iter))) { + continue; + } + } + stats->totobj++; + } + } + FOREACH_OBJECT_END; } - else if (stats_is_object_dynamic_topology_sculpt(ob)) { - /* Dynamic topology. Do not count all vertices, dynamic topology stats are initialized later as - * part of sculpt stats. */ + else if (ob && (ob->mode & OB_MODE_SCULPT)) { + /* Sculpt Mode. */ + if (stats_is_object_dynamic_topology_sculpt(ob)) { + /* Dynamic topology. Do not count all vertices, + * dynamic topology stats are initialized later as part of sculpt stats. */ + } + else { + /* When dynamic topology is not enabled both sculpt stats and scene stats are collected. */ + stats_object_sculpt(ob, stats); + } } else { - /* Objects */ + /* Objects. */ GSet *objects_gset = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob_iter) { - stats_object(ob_iter, &stats, objects_gset); + stats_object(ob_iter, v3d_local, stats, objects_gset); } DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END; BLI_gset_free(objects_gset, NULL); } - - if (ob && (ob->mode & OB_MODE_SCULPT)) { - /* Sculpt Mode. When dynamic topology is not enabled both sculpt stats and scene stats are - * collected. */ - stats_object_sculpt(ob, &stats); - } - - if (!view_layer->stats) { - view_layer->stats = MEM_callocN(sizeof(SceneStats), "SceneStats"); - } - - *(view_layer->stats) = stats; } -void ED_info_stats_clear(ViewLayer *view_layer) +void ED_info_stats_clear(wmWindowManager *wm, ViewLayer *view_layer) { if (view_layer->stats) { MEM_freeN(view_layer->stats); view_layer->stats = NULL; } + + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { + ViewLayer *view_layer_test = WM_window_get_active_view_layer(win); + if (view_layer != view_layer_test) { + continue; + } + const bScreen *screen = WM_window_get_active_screen(win); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + if (area->spacetype == SPACE_VIEW3D) { + View3D *v3d = area->spacedata.first; + if (v3d->localvd) { + MEM_SAFE_FREE(v3d->runtime.local_stats); + } + } + } + } } -static bool format_stats(Main *bmain, - Scene *scene, - ViewLayer *view_layer, - SceneStatsFmt *stats_fmt) +static bool format_stats( + Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d_local, SceneStatsFmt *stats_fmt) { /* Create stats if they don't already exist. */ - if (!view_layer->stats) { - /* Do not not access dependency graph if interface is marked as locked. */ + SceneStats **stats_p = (v3d_local) ? &v3d_local->runtime.local_stats : &view_layer->stats; + if (*stats_p == NULL) { + /* Don't access dependency graph if interface is marked as locked. */ wmWindowManager *wm = bmain->wm.first; if (wm->is_interface_locked) { return false; } Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer); - stats_update(depsgraph, view_layer); + *stats_p = MEM_mallocN(sizeof(SceneStats), __func__); + stats_update(depsgraph, view_layer, v3d_local, *stats_p); } - SceneStats *stats = view_layer->stats; + SceneStats *stats = *stats_p; /* Generate formatted numbers. */ #define SCENE_STATS_FMT_INT(_id) BLI_str_format_uint64_grouped(stats_fmt->_id, stats->_id) @@ -505,14 +549,14 @@ static void get_stats_string( LayerCollection *layer_collection = view_layer->active_collection; if (object_mode == OB_MODE_OBJECT) { - *ofs += BLI_snprintf(info + *ofs, - len - *ofs, - "%s | ", - BKE_collection_ui_name_get(layer_collection->collection)); + *ofs += BLI_snprintf_rlen(info + *ofs, + len - *ofs, + "%s | ", + BKE_collection_ui_name_get(layer_collection->collection)); } if (ob) { - *ofs += BLI_snprintf(info + *ofs, len - *ofs, "%s | ", ob->id.name + 2); + *ofs += BLI_snprintf_rlen(info + *ofs, len - *ofs, "%s | ", ob->id.name + 2); } if (obedit) { @@ -521,72 +565,72 @@ static void get_stats_string( } if (obedit->type == OB_MESH) { - *ofs += BLI_snprintf(info + *ofs, - len - *ofs, - TIP_("Verts:%s/%s | Edges:%s/%s | Faces:%s/%s | Tris:%s"), - stats_fmt->totvertsel, - stats_fmt->totvert, - stats_fmt->totedgesel, - stats_fmt->totedge, - stats_fmt->totfacesel, - stats_fmt->totface, - stats_fmt->tottri); + *ofs += BLI_snprintf_rlen(info + *ofs, + len - *ofs, + TIP_("Verts:%s/%s | Edges:%s/%s | Faces:%s/%s | Tris:%s"), + stats_fmt->totvertsel, + stats_fmt->totvert, + stats_fmt->totedgesel, + stats_fmt->totedge, + stats_fmt->totfacesel, + stats_fmt->totface, + stats_fmt->tottri); } else if (obedit->type == OB_ARMATURE) { - *ofs += BLI_snprintf(info + *ofs, - len - *ofs, - TIP_("Joints:%s/%s | Bones:%s/%s"), - stats_fmt->totvertsel, - stats_fmt->totvert, - stats_fmt->totbonesel, - stats_fmt->totbone); + *ofs += BLI_snprintf_rlen(info + *ofs, + len - *ofs, + TIP_("Joints:%s/%s | Bones:%s/%s"), + stats_fmt->totvertsel, + stats_fmt->totvert, + stats_fmt->totbonesel, + stats_fmt->totbone); } else { - *ofs += BLI_snprintf( + *ofs += BLI_snprintf_rlen( info + *ofs, len - *ofs, TIP_("Verts:%s/%s"), stats_fmt->totvertsel, stats_fmt->totvert); } } else if (ob && (object_mode & OB_MODE_POSE)) { - *ofs += BLI_snprintf( + *ofs += BLI_snprintf_rlen( info + *ofs, len - *ofs, TIP_("Bones:%s/%s"), stats_fmt->totbonesel, stats_fmt->totbone); } else if ((ob) && (ob->type == OB_GPENCIL)) { - *ofs += BLI_snprintf(info + *ofs, - len - *ofs, - TIP_("Layers:%s | Frames:%s | Strokes:%s | Points:%s"), - stats_fmt->totgplayer, - stats_fmt->totgpframe, - stats_fmt->totgpstroke, - stats_fmt->totgppoint); + *ofs += BLI_snprintf_rlen(info + *ofs, + len - *ofs, + TIP_("Layers:%s | Frames:%s | Strokes:%s | Points:%s"), + stats_fmt->totgplayer, + stats_fmt->totgpframe, + stats_fmt->totgpstroke, + stats_fmt->totgppoint); } else if (ob && (object_mode & OB_MODE_SCULPT)) { if (stats_is_object_dynamic_topology_sculpt(ob)) { - *ofs += BLI_snprintf(info + *ofs, - len - *ofs, - TIP_("Verts:%s | Tris:%s"), - stats_fmt->totvert, - stats_fmt->tottri); + *ofs += BLI_snprintf_rlen(info + *ofs, + len - *ofs, + TIP_("Verts:%s | Tris:%s"), + stats_fmt->totvert, + stats_fmt->tottri); } else { - *ofs += BLI_snprintf(info + *ofs, - len - *ofs, - TIP_("Verts:%s/%s | Faces:%s/%s"), - stats_fmt->totvertsculpt, - stats_fmt->totvert, - stats_fmt->totfacesculpt, - stats_fmt->totface); + *ofs += BLI_snprintf_rlen(info + *ofs, + len - *ofs, + TIP_("Verts:%s/%s | Faces:%s/%s"), + stats_fmt->totvertsculpt, + stats_fmt->totvert, + stats_fmt->totfacesculpt, + stats_fmt->totface); } } else { - *ofs += BLI_snprintf(info + *ofs, - len - *ofs, - TIP_("Verts:%s | Faces:%s | Tris:%s"), - stats_fmt->totvert, - stats_fmt->totface, - stats_fmt->tottri); + *ofs += BLI_snprintf_rlen(info + *ofs, + len - *ofs, + TIP_("Verts:%s | Faces:%s | Tris:%s"), + stats_fmt->totvert, + stats_fmt->totface, + stats_fmt->tottri); } - *ofs += BLI_snprintf( + *ofs += BLI_snprintf_rlen( info + *ofs, len - *ofs, TIP_(" | Objects:%s/%s"), stats_fmt->totobjsel, stats_fmt->totobj); } @@ -605,7 +649,7 @@ static const char *info_statusbar_string(Main *bmain, /* Scene statistics. */ if (statusbar_flag & STATUSBAR_SHOW_STATS) { SceneStatsFmt stats_fmt; - if (format_stats(bmain, scene, view_layer, &stats_fmt)) { + if (format_stats(bmain, scene, view_layer, NULL, &stats_fmt)) { get_stats_string(info + ofs, len, &ofs, view_layer, &stats_fmt); } } @@ -613,11 +657,11 @@ static const char *info_statusbar_string(Main *bmain, /* Memory status. */ if (statusbar_flag & STATUSBAR_SHOW_MEMORY) { if (info[0]) { - ofs += BLI_snprintf(info + ofs, len - ofs, " | "); + ofs += BLI_snprintf_rlen(info + ofs, len - ofs, " | "); } uintptr_t mem_in_use = MEM_get_memory_in_use(); BLI_str_format_byte_unit(formatted_mem, mem_in_use, false); - ofs += BLI_snprintf(info + ofs, len, TIP_("Memory: %s"), formatted_mem); + ofs += BLI_snprintf_rlen(info + ofs, len, TIP_("Memory: %s"), formatted_mem); } /* GPU VRAM status. */ @@ -627,27 +671,27 @@ static const char *info_statusbar_string(Main *bmain, float gpu_total_gb = gpu_tot_mem_kb / 1048576.0f; float gpu_free_gb = gpu_free_mem_kb / 1048576.0f; if (info[0]) { - ofs += BLI_snprintf(info + ofs, len - ofs, " | "); + ofs += BLI_snprintf_rlen(info + ofs, len - ofs, " | "); } if (gpu_free_mem_kb && gpu_tot_mem_kb) { - ofs += BLI_snprintf(info + ofs, - len - ofs, - TIP_("VRAM: %.1f/%.1f GiB"), - gpu_total_gb - gpu_free_gb, - gpu_total_gb); + ofs += BLI_snprintf_rlen(info + ofs, + len - ofs, + TIP_("VRAM: %.1f/%.1f GiB"), + gpu_total_gb - gpu_free_gb, + gpu_total_gb); } else { /* Can only show amount of GPU VRAM available. */ - ofs += BLI_snprintf(info + ofs, len - ofs, TIP_("VRAM: %.1f GiB Free"), gpu_free_gb); + ofs += BLI_snprintf_rlen(info + ofs, len - ofs, TIP_("VRAM: %.1f GiB Free"), gpu_free_gb); } } /* Blender version. */ if (statusbar_flag & STATUSBAR_SHOW_VERSION) { if (info[0]) { - ofs += BLI_snprintf(info + ofs, len - ofs, " | "); + ofs += BLI_snprintf_rlen(info + ofs, len - ofs, " | "); } - ofs += BLI_snprintf(info + ofs, len - ofs, TIP_("%s"), BKE_blender_version_string()); + ofs += BLI_snprintf_rlen(info + ofs, len - ofs, TIP_("%s"), BKE_blender_version_string()); } return info; @@ -682,18 +726,24 @@ static void stats_row(int col1, BLF_draw_default(col2, *y, 0.0f, values, sizeof(values)); } +/** + * \param v3d_local: Pass this argument to calculate view-port local statistics. + * Note that this must only be used for local-view, otherwise report specific statistics + * will be written into the global scene statistics giving incorrect results. + */ void ED_info_draw_stats( - Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height) + Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d_local, int x, int *y, int height) { + BLI_assert(v3d_local == NULL || v3d_local->localvd != NULL); SceneStatsFmt stats_fmt; - if (!format_stats(bmain, scene, view_layer, &stats_fmt)) { + if (!format_stats(bmain, scene, view_layer, v3d_local, &stats_fmt)) { return; } Object *ob = OBACT(view_layer); Object *obedit = OBEDIT_FROM_OBACT(ob); eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT; - const int font_id = BLF_default(); + const int font_id = BLF_set_default(); UI_FontThemeColor(font_id, TH_TEXT_HI); BLF_enable(font_id, BLF_SHADOW); @@ -747,8 +797,8 @@ void ED_info_draw_stats( } if (obedit) { + stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height); if (obedit->type == OB_MESH) { - stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height); stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height); stats_row(col1, labels[EDGES], col2, stats_fmt.totedgesel, stats_fmt.totedge, y, height); stats_row(col1, labels[FACES], col2, stats_fmt.totfacesel, stats_fmt.totface, y, height); @@ -763,6 +813,7 @@ void ED_info_draw_stats( } } else if (ob && (object_mode & OB_MODE_POSE)) { + stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height); stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height); } else if ((ob) && (ob->type == OB_GPENCIL)) { diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index aef59e89325..e656155fb13 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -353,7 +353,7 @@ int textview_draw(TextViewContext *tvc, tds.lheight = tvc->lheight; tds.row_vpadding = tvc->row_vpadding; tds.lofs = -BLF_descender(font_id); - /* Note, scroll bar must be already subtracted. */ + /* NOTE: scroll bar must be already subtracted. */ tds.columns = (tvc->draw_rect.xmax - tvc->draw_rect.xmin) / tds.cwidth; /* Avoid divide by zero on small windows. */ if (tds.columns < 1) { diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index f2cea23af76..0498964c549 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -288,14 +288,14 @@ static int mouse_nla_channels( /* button region... */ if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) { if (nlaedit_is_tweakmode_on(ac) == 0) { - /* 'push-down' action - only usable when not in TweakMode */ + /* 'push-down' action - only usable when not in tweak-mode */ /* TODO: make this use the operator instead of calling the function directly * however, calling the operator requires that we supply the args, * and that works with proper buttons only */ BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(ale->id)); } else { - /* when in tweakmode, this button becomes the toggle for mapped editing */ + /* When in tweak-mode, this button becomes the toggle for mapped editing. */ adt->flag ^= ADT_NLA_EDIT_NOMAP; } @@ -308,13 +308,13 @@ static int mouse_nla_channels( /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block * - this is useful when there's no clear divider, and makes more sense in * the case of users trying to use this to change actions - * - in tweakmode, clicking here gets us out of tweakmode, as changing selection - * while in tweakmode is really evil! + * - in tweak-mode, clicking here gets us out of tweak-mode, as changing selection + * while in tweak-mode is really evil! * - we disable "solo" flags too, to make it easier to work with stashed actions * with less trouble */ if (nlaedit_is_tweakmode_on(ac)) { - /* exit tweakmode immediately */ + /* Exit tweak-mode immediately. */ nlaedit_disable_tweakmode(ac, true); /* changes to NLA-Action occurred */ @@ -515,7 +515,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* 'push-down' action - only usable when not in TweakMode */ + /* 'push-down' action - only usable when not in Tweak-mode. */ BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(id)); struct Main *bmain = CTX_data_main(C); @@ -874,7 +874,7 @@ static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op)) /* operate on selected objects... */ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { /* ensure that object has AnimData... that's all */ - BKE_animdata_add_id(&ob->id); + BKE_animdata_ensure_id(&ob->id); } CTX_DATA_END; diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 7d4011e0812..f9fb386095d 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -127,8 +127,8 @@ static void nla_action_draw_keyframes( immRectf(pos_id, f1, ymin + 2, f2, ymax - 2); immUnbindProgram(); - /* count keys before drawing */ - /* Note: It's safe to cast DLRBT_Tree, as it's designed to degrade down to a ListBase */ + /* Count keys before drawing. */ + /* NOTE: It's safe to cast #DLRBT_Tree, as it's designed to degrade down to a #ListBase. */ uint key_len = BLI_listbase_count((ListBase *)&keys); if (key_len > 0) { @@ -734,7 +734,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region) int height = NLACHANNEL_TOT_HEIGHT(ac, items); v2d->tot.ymin = -height; - /* loop through channels, and set up drawing depending on their type */ + /* Loop through channels, and set up drawing depending on their type. */ float ymax = NLACHANNEL_FIRST_TOP(ac); for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla)) { @@ -894,7 +894,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *region) /* set blending again, as may not be set in previous step */ GPU_blend(GPU_BLEND_ALPHA); - /* loop through channels, and set up drawing depending on their type */ + /* Loop through channels, and set up drawing depending on their type. */ for (ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla), channel_index++) { float ymin = ymax - NLACHANNEL_HEIGHT(snla); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index dd381cc92fb..56efcd8571f 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -65,7 +65,7 @@ #include "UI_view2d.h" #include "nla_intern.h" /* own include */ -#include "nla_private.h" /* FIXME... maybe this shouldn't be included? */ +#include "nla_private.h" /* FIXME: maybe this shouldn't be included? */ /* -------------------------------------------------------------------- */ /** \name Public Utilities @@ -135,7 +135,7 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op) for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ale->data; - /* try entering tweakmode if valid */ + /* Try entering tweak-mode if valid. */ ok |= BKE_nla_tweakmode_enter(adt); /* mark the active track as being "solo"? */ @@ -154,9 +154,8 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op) ANIM_animdata_update(&ac, &anim_data); ANIM_animdata_freelist(&anim_data); - /* if we managed to enter tweakmode on at least one AnimData block, - * set the flag for this in the active scene and send notifiers - */ + /* If we managed to enter tweak-mode on at least one AnimData block, + * set the flag for this in the active scene and send notifiers. */ if (ac.scene && ok) { /* set editing flag */ ac.scene->flag |= SCE_NLA_EDIT_ON; @@ -206,7 +205,7 @@ void NLA_OT_tweakmode_enter(wmOperatorType *ot) /** \name Disable Tweak-Mode Operator * \{ */ -/* NLA Editor internal API function for exiting tweakmode */ +/* NLA Editor internal API function for exiting tweak-mode. */ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) { ListBase anim_data = {NULL, NULL}; @@ -232,7 +231,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) BKE_nlatrack_solo_toggle(adt, NULL); } - /* to be sure that we're doing everything right, just exit tweakmode... */ + /* To be sure that we're doing everything right, just exit tweak-mode. */ BKE_nla_tweakmode_exit(adt); ale->update |= ANIM_UPDATE_DEPS; @@ -242,7 +241,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) ANIM_animdata_update(ac, &anim_data); ANIM_animdata_freelist(&anim_data); - /* if we managed to enter tweakmode on at least one AnimData block, + /* if we managed to enter tweak-mode on at least one AnimData block, * set the flag for this in the active scene and send notifiers */ if (ac->scene) { @@ -257,7 +256,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) return true; } -/* exit tweakmode operator callback */ +/* Exit tweak-mode operator callback. */ static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op) { bAnimContext ac; @@ -1157,7 +1156,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op) NlaStrip *strip, *nstrip, *next; NlaTrack *track; - /* Note: We allow this operator in override context because it is almost always (from possible + /* NOTE: We allow this operator in override context because it is almost always (from possible * default user interactions) paired with the transform one, which will ensure that the new * strip ends up in a valid (local) track. */ @@ -1397,7 +1396,7 @@ static void nlaedit_split_strip_actclip( nstrip->start = splitframe; if ((splitaframe > strip->actstart) && (splitaframe < strip->actend)) { - /* only do this if we're splitting down the middle... */ + /* only do this if we're splitting down the middle... */ strip->actend = splitaframe; nstrip->actstart = splitaframe; } @@ -1412,7 +1411,7 @@ static void nlaedit_split_strip_actclip( /* split a given Meta strip */ static void nlaedit_split_strip_meta(NlaTrack *nlt, NlaStrip *strip) { - /* simply ungroup it for now... */ + /* simply ungroup it for now... */ BKE_nlastrips_clear_metastrip(&nlt->strips, strip); } @@ -1528,7 +1527,7 @@ static int nlaedit_toggle_mute_exec(bContext *C, wmOperator *UNUSED(op)) NlaTrack *nlt = (NlaTrack *)ale->data; NlaStrip *strip; - /* for every selected strip, toggle muting */ + /* For every selected strip, toggle muting. */ for (strip = nlt->strips.first; strip; strip = strip->next) { if (strip->flag & NLASTRIP_FLAG_SELECT) { /* just flip the mute flag for now */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 631dc2e550c..28f194877fa 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -39,17 +39,16 @@ /* ************************** poll callbacks for operators **********************************/ -/* tweakmode is NOT enabled */ +/* Tweak-mode is NOT enabled. */ bool nlaop_poll_tweakmode_off(bContext *C) { Scene *scene; /* for now, we check 2 things: * 1) active editor must be NLA - * 2) tweakmode is currently set as a 'per-scene' flag + * 2) tweak-mode is currently set as a 'per-scene' flag * so that it will affect entire NLA data-sets, - * but not all AnimData blocks will be in tweakmode for - * various reasons + * but not all AnimData blocks will be in tweak-mode for various reasons. */ if (ED_operator_nla_active(C) == 0) { return 0; @@ -63,17 +62,16 @@ bool nlaop_poll_tweakmode_off(bContext *C) return 1; } -/* tweakmode IS enabled */ +/* Tweak-mode IS enabled. */ bool nlaop_poll_tweakmode_on(bContext *C) { Scene *scene; /* for now, we check 2 things: * 1) active editor must be NLA - * 2) tweakmode is currently set as a 'per-scene' flag + * 2) tweak-mode is currently set as a 'per-scene' flag * so that it will affect entire NLA data-sets, - * but not all AnimData blocks will be in tweakmode for - * various reasons + * but not all AnimData blocks will be in tweak-mode for various reasons. */ if (ED_operator_nla_active(C) == 0) { return 0; @@ -87,7 +85,7 @@ bool nlaop_poll_tweakmode_on(bContext *C) return 1; } -/* is tweakmode enabled - for use in NLA operator code */ +/* is tweak-mode enabled - for use in NLA operator code */ bool nlaedit_is_tweakmode_on(bAnimContext *ac) { if (ac && ac->scene) { diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 87ad09fe2f9..246c3e0156a 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -453,7 +453,7 @@ static void nlaedit_select_leftright(bContext *C, Scene *scene = ac->scene; float xmin, xmax; - /* if currently in tweakmode, exit tweakmode first */ + /* if currently in tweak-mode, exit tweak-mode first */ if (scene->flag & SCE_NLA_EDIT_ON) { WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); } @@ -577,7 +577,7 @@ void NLA_OT_select_leftright(wmOperatorType *ot) ot->idname = "NLA_OT_select_leftright"; ot->description = "Select strips to the left or the right of the current frame"; - /* api callbacks */ + /* api callbacks */ ot->invoke = nlaedit_select_leftright_invoke; ot->exec = nlaedit_select_leftright_exec; ot->poll = ED_operator_nla_active; @@ -612,7 +612,7 @@ static int mouse_nla_strips(bContext *C, nlaedit_strip_at_region_position(ac, mval[0], mval[1], &ale, &strip); - /* if currently in tweakmode, exit tweakmode before changing selection states + /* if currently in tweak-mode, exit tweak-mode before changing selection states * now that we've found our target... */ if (scene->flag & SCE_NLA_EDIT_ON) { diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index bc043a4e665..80d3b43bf6b 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../compositor ../../depsgraph ../../draw + ../../functions ../../gpu ../../imbuf ../../makesdna @@ -37,20 +38,19 @@ set(INC set(SRC - drawnode.c - node_add.c - node_buttons.c + drawnode.cc + node_add.cc node_draw.cc - node_edit.c + node_edit.cc node_geometry_attribute_search.cc node_gizmo.c - node_group.c + node_group.cc node_ops.c - node_relationships.c - node_select.c - node_templates.c - node_toolbar.c - node_view.c + node_relationships.cc + node_select.cc + node_templates.cc + node_toolbar.cc + node_view.cc space_node.c node_intern.h @@ -78,4 +78,20 @@ if(WITH_OPENSUBDIV) add_definitions(-DWITH_OPENSUBDIV) endif() +if(WITH_TBB) + add_definitions(-DWITH_TBB) + if(WIN32) + # TBB includes Windows.h which will define min/max macros + # that will collide with the stl versions. + add_definitions(-DNOMINMAX) + endif() + list(APPEND INC_SYS + ${TBB_INCLUDE_DIRS} + ) + + list(APPEND LIB + ${TBB_LIBRARIES} + ) +endif() + blender_add_lib(bf_editor_space_node "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.cc index 6b4366b2966..243652da608 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.cc @@ -95,9 +95,9 @@ static void node_socket_button_label(bContext *UNUSED(C), static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; /* first output stores value */ - bNodeSocket *output = node->outputs.first; + bNodeSocket *output = (bNodeSocket *)node->outputs.first; PointerRNA sockptr; RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr); @@ -106,15 +106,15 @@ static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *p static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; /* first output stores value */ - bNodeSocket *output = node->outputs.first; + bNodeSocket *output = (bNodeSocket *)node->outputs.first; PointerRNA sockptr; uiLayout *col; RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr); col = uiLayoutColumn(layout, false); - uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0); + uiTemplateColorPicker(col, &sockptr, "default_value", true, false, false, false); uiItemR(col, &sockptr, "default_value", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); } @@ -129,14 +129,14 @@ static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA uiItemR(row, ptr, "use_alpha", DEFAULT_FLAGS, "", ICON_IMAGE_RGB_ALPHA); } - uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { #if 0 - /* XXX no context access here .. */ - bNode *node = ptr->data; + /* XXX no context access here. */ + bNode *node = (bNode*)ptr->data; CurveMapping *cumap = node->storage; if (cumap) { @@ -156,7 +156,7 @@ static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *pt static void node_buts_colorramp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiTemplateColorRamp(layout, ptr, "color_ramp", 0); + uiTemplateColorRamp(layout, ptr, "color_ramp", false); } static void node_buts_curvevec(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -179,8 +179,8 @@ void ED_node_sample_set(const float col[4]) static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - bNode *node = ptr->data; - CurveMapping *cumap = node->storage; + bNode *node = (bNode *)ptr->data; + CurveMapping *cumap = (CurveMapping *)node->storage; if (_sample_col[0] != SAMPLE_FLT_ISNONE) { cumap->flag |= CUMA_DRAW_SAMPLE; @@ -198,9 +198,9 @@ static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; /* first output stores normal */ - bNodeSocket *output = node->outputs.first; + bNodeSocket *output = (bNodeSocket *)node->outputs.first; PointerRNA sockptr; RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr); @@ -209,7 +209,7 @@ static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA * static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; short multi = (node->id && ((Tex *)node->id)->use_nodes && (node->type != CMP_NODE_TEXTURE) && (node->type != TEX_NODE_TEXTURE)); @@ -217,7 +217,7 @@ static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA uiItemR(layout, ptr, "texture", DEFAULT_FLAGS, "", ICON_NONE); if (multi) { - /* Number Drawing not optimal here, better have a list*/ + /* Number Drawing not optimal here, better have a list. */ uiItemR(layout, ptr, "node_output", DEFAULT_FLAGS, "", ICON_NONE); } } @@ -233,14 +233,14 @@ static void node_shader_buts_map_range(uiLayout *layout, bContext *UNUSED(C), Po if (!ELEM(RNA_enum_get(ptr, "interpolation_type"), NODE_MAP_RANGE_SMOOTHSTEP, NODE_MAP_RANGE_SMOOTHERSTEP)) { - uiItemR(layout, ptr, "clamp", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "clamp", DEFAULT_FLAGS, nullptr, ICON_NONE); } } static void node_buts_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_clamp", DEFAULT_FLAGS, nullptr, ICON_NONE); } static int node_resize_area_default(bNode *node, int x, int y) @@ -274,7 +274,7 @@ static int node_resize_area_default(bNode *node, int x, int y) static void node_draw_buttons_group(uiLayout *layout, bContext *C, PointerRNA *ptr) { uiTemplateIDBrowse( - layout, C, ptr, "node_tree", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, NULL); + layout, C, ptr, "node_tree", nullptr, nullptr, nullptr, UI_TEMPLATE_ID_FILTER_ALL, nullptr); } /* XXX Does a bounding box update by iterating over all children. @@ -311,7 +311,7 @@ static void node_draw_frame_prepare(const bContext *UNUSED(C), bNodeTree *ntree, /* first child initializes frame */ if (bbinit) { - bbinit = 0; + bbinit = false; rect = noderect; data->flag &= ~NODE_FRAME_RESIZEABLE; } @@ -418,9 +418,9 @@ static void node_draw_frame(const bContext *C, { /* skip if out of view */ - if (BLI_rctf_isect(&node->totr, ®ion->v2d.cur, NULL) == false) { + if (BLI_rctf_isect(&node->totr, ®ion->v2d.cur, nullptr) == false) { UI_block_end(C, node->block); - node->block = NULL; + node->block = nullptr; return; } @@ -462,7 +462,7 @@ static void node_draw_frame(const bContext *C, UI_block_end(C, node->block); UI_block_draw(C, node->block); - node->block = NULL; + node->block = nullptr; } static int node_resize_area_frame(bNode *node, int x, int y) @@ -497,7 +497,7 @@ static void node_buts_frame_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA { uiItemR(layout, ptr, "label_size", DEFAULT_FLAGS, IFACE_("Label Size"), ICON_NONE); uiItemR(layout, ptr, "shrink", DEFAULT_FLAGS, IFACE_("Shrink"), ICON_NONE); - uiItemR(layout, ptr, "text", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "text", DEFAULT_FLAGS, nullptr, ICON_NONE); } #define NODE_REROUTE_SIZE 8.0f @@ -511,11 +511,11 @@ static void node_draw_reroute_prepare(const bContext *UNUSED(C), node_to_view(node, 0.0f, 0.0f, &locx, &locy); /* reroute node has exactly one input and one output, both in the same place */ - bNodeSocket *nsock = node->outputs.first; + bNodeSocket *nsock = (bNodeSocket *)node->outputs.first; nsock->locx = locx; nsock->locy = locy; - nsock = node->inputs.first; + nsock = (bNodeSocket *)node->inputs.first; nsock->locx = locx; nsock->locy = locy; @@ -541,7 +541,7 @@ static void node_draw_reroute(const bContext *C, if (node->totr.xmax < region->v2d.cur.xmin || node->totr.xmin > region->v2d.cur.xmax || node->totr.ymax < region->v2d.cur.ymin || node->totr.ymin > region->v2d.cur.ymax) { UI_block_end(C, node->block); - node->block = NULL; + node->block = nullptr; return; } @@ -586,12 +586,12 @@ static void node_draw_reroute(const bContext *C, (int)(rct->ymax), (short)512, (short)NODE_DY, - NULL, + nullptr, 0, 0, 0, 0, - NULL); + nullptr); } /* only draw input socket. as they all are placed on the same position. @@ -601,7 +601,7 @@ static void node_draw_reroute(const bContext *C, UI_block_end(C, node->block); UI_block_draw(C, node->block); - node->block = NULL; + node->block = nullptr; } /* Special tweak area for reroute node. @@ -612,7 +612,7 @@ static int node_tweak_area_reroute(bNode *node, int x, int y) /* square of tweak radius */ const float tweak_radius_sq = square_f(24.0f); - bNodeSocket *sock = node->inputs.first; + bNodeSocket *sock = (bNodeSocket *)node->inputs.first; float dx = sock->locx - x; float dy = sock->locy - y; return (dx * dx + dy * dy <= tweak_radius_sq); @@ -662,28 +662,28 @@ static void node_buts_image_user(uiLayout *layout, /* don't use iuser->framenr directly * because it may not be updated if auto-refresh is off */ Scene *scene = CTX_data_scene(C); - ImageUser *iuser = iuserptr->data; + ImageUser *iuser = (ImageUser *)iuserptr->data; /* Image *ima = imaptr->data; */ /* UNUSED */ char numstr[32]; - const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL); + const int framenr = BKE_image_user_frame_get(iuser, CFRA, nullptr); BLI_snprintf(numstr, sizeof(numstr), IFACE_("Frame: %d"), framenr); uiItemL(layout, numstr, ICON_NONE); } if (ELEM(source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "frame_duration", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "frame_start", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "frame_offset", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "use_cyclic", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "use_auto_refresh", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "frame_duration", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "frame_start", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "frame_offset", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "use_cyclic", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "use_auto_refresh", DEFAULT_FLAGS, nullptr, ICON_NONE); } if (show_layer_selection && RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER && RNA_boolean_get(ptr, "has_layers")) { col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "layer", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "layer", DEFAULT_FLAGS, nullptr, ICON_NONE); } if (show_color_management) { @@ -693,7 +693,7 @@ static void node_buts_image_user(uiLayout *layout, uiItemR(split, &colorspace_settings_ptr, "name", DEFAULT_FLAGS, "", ICON_NONE); /* Avoid losing changes image is painted. */ - if (BKE_image_is_dirty(imaptr->data)) { + if (BKE_image_is_dirty((Image *)imaptr->data)) { uiLayoutSetEnabled(split, false); } } @@ -701,13 +701,13 @@ static void node_buts_image_user(uiLayout *layout, static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "vector_type", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "vector_type", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_shader_buts_vector_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "rotation_type", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, NULL, 0); + uiItemR(layout, ptr, "rotation_type", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, nullptr, 0); } static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -717,7 +717,7 @@ static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), Po static void node_shader_buts_vect_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "vector_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "vector_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); uiItemR(layout, ptr, "convert_from", DEFAULT_FLAGS, "", ICON_NONE); uiItemR(layout, ptr, "convert_to", DEFAULT_FLAGS, "", ICON_NONE); } @@ -730,7 +730,7 @@ static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), Po static void node_shader_buts_wireframe(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_pixel_size", DEFAULT_FLAGS, NULL, 0); + uiItemR(layout, ptr, "use_pixel_size", DEFAULT_FLAGS, nullptr, 0); } static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -745,10 +745,10 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA "image", "IMAGE_OT_new", "IMAGE_OT_open", - NULL, + nullptr, UI_TEMPLATE_ID_FILTER_ALL, false, - NULL); + nullptr); uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, "", ICON_NONE); uiItemR(layout, ptr, "projection", DEFAULT_FLAGS, "", ICON_NONE); @@ -758,7 +758,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA uiItemR(layout, ptr, "extension", DEFAULT_FLAGS, "", ICON_NONE); - /* note: image user properties used directly here, unlike compositor image node, + /* NOTE: image user properties used directly here, unlike compositor image node, * which redefines them in the node struct RNA to get proper updates. */ node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false, true); @@ -767,7 +767,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA static void node_shader_buts_tex_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user"); - uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0); + uiTemplateImage(layout, C, ptr, "image", &iuserptr, false, false); } static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -782,10 +782,10 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin "image", "IMAGE_OT_new", "IMAGE_OT_open", - NULL, + nullptr, UI_TEMPLATE_ID_FILTER_ALL, false, - NULL); + nullptr); uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, "", ICON_NONE); uiItemR(layout, ptr, "projection", DEFAULT_FLAGS, "", ICON_NONE); @@ -796,7 +796,7 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user"); - uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0); + uiTemplateImage(layout, C, ptr, "image", &iuserptr, false, false); uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, IFACE_("Interpolation"), ICON_NONE); uiItemR(layout, ptr, "projection", DEFAULT_FLAGS, IFACE_("Projection"), ICON_NONE); @@ -808,33 +808,33 @@ static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), Poin if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_PREETHAM) { uiItemR(layout, ptr, "sun_direction", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "turbidity", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "turbidity", DEFAULT_FLAGS, nullptr, ICON_NONE); } if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_HOSEK) { uiItemR(layout, ptr, "sun_direction", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "turbidity", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "ground_albedo", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "turbidity", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "ground_albedo", DEFAULT_FLAGS, nullptr, ICON_NONE); } if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NISHITA) { - uiItemR(layout, ptr, "sun_disc", DEFAULT_FLAGS, NULL, 0); + uiItemR(layout, ptr, "sun_disc", DEFAULT_FLAGS, nullptr, 0); uiLayout *col; if (RNA_boolean_get(ptr, "sun_disc")) { col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "sun_size", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "sun_intensity", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "sun_size", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "sun_intensity", DEFAULT_FLAGS, nullptr, ICON_NONE); } col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "sun_elevation", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "sun_rotation", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "sun_elevation", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "sun_rotation", DEFAULT_FLAGS, nullptr, ICON_NONE); - uiItemR(layout, ptr, "altitude", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "altitude", DEFAULT_FLAGS, nullptr, ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "air_density", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "dust_density", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "ozone_density", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "air_density", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "dust_density", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "ozone_density", DEFAULT_FLAGS, nullptr, ICON_NONE); } } @@ -845,7 +845,7 @@ static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), static void node_shader_buts_tex_magic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "turbulence_depth", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "turbulence_depth", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -901,32 +901,33 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - bNode *node = ptr->data; - NodeShaderTexPointDensity *shader_point_density = node->storage; + bNode *node = (bNode *)ptr->data; + NodeShaderTexPointDensity *shader_point_density = (NodeShaderTexPointDensity *)node->storage; Object *ob = (Object *)node->id; PointerRNA ob_ptr, obdata_ptr; RNA_id_pointer_create((ID *)ob, &ob_ptr); - RNA_id_pointer_create(ob ? (ID *)ob->data : NULL, &obdata_ptr); + RNA_id_pointer_create(ob ? (ID *)ob->data : nullptr, &obdata_ptr); - uiItemR(layout, ptr, "point_source", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(layout, ptr, "object", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "point_source", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); + uiItemR(layout, ptr, "object", DEFAULT_FLAGS, nullptr, ICON_NONE); if (node->id && shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) { PointerRNA dataptr; RNA_id_pointer_create((ID *)node->id, &dataptr); - uiItemPointerR(layout, ptr, "particle_system", &dataptr, "particle_systems", NULL, ICON_NONE); + uiItemPointerR( + layout, ptr, "particle_system", &dataptr, "particle_systems", nullptr, ICON_NONE); } - uiItemR(layout, ptr, "space", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "radius", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "resolution", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "space", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "radius", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "resolution", DEFAULT_FLAGS, nullptr, ICON_NONE); if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) { - uiItemR(layout, ptr, "particle_color_source", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "particle_color_source", DEFAULT_FLAGS, nullptr, ICON_NONE); } else { - uiItemR(layout, ptr, "vertex_color_source", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "vertex_color_source", DEFAULT_FLAGS, nullptr, ICON_NONE); if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTWEIGHT) { if (ob_ptr.data) { uiItemPointerR( @@ -944,18 +945,18 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout, static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "object", DEFAULT_FLAGS, NULL, 0); - uiItemR(layout, ptr, "from_instancer", DEFAULT_FLAGS, NULL, 0); + uiItemR(layout, ptr, "object", DEFAULT_FLAGS, nullptr, 0); + uiItemR(layout, ptr, "from_instancer", DEFAULT_FLAGS, nullptr, 0); } static void node_shader_buts_bump(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, NULL, 0); + uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, nullptr, 0); } static void node_shader_buts_uvmap(uiLayout *layout, bContext *C, PointerRNA *ptr) { - uiItemR(layout, ptr, "from_instancer", DEFAULT_FLAGS, NULL, 0); + uiItemR(layout, ptr, "from_instancer", DEFAULT_FLAGS, nullptr, 0); if (!RNA_boolean_get(ptr, "from_instancer")) { PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); @@ -989,7 +990,7 @@ static void node_shader_buts_vertex_color(uiLayout *layout, bContext *C, Pointer static void node_shader_buts_uvalongstroke(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_tips", DEFAULT_FLAGS, NULL, 0); + uiItemR(layout, ptr, "use_tips", DEFAULT_FLAGS, nullptr, 0); } static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -1036,7 +1037,7 @@ static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA * } } else { - uiItemR(row, ptr, "axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, 0); + uiItemR(row, ptr, "axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, 0); } } @@ -1083,7 +1084,7 @@ static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerR uiLayout *row; row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "mode", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "mode", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); row = uiLayoutRow(layout, true); @@ -1100,7 +1101,7 @@ static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), Point uiLayout *row; row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "mode", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "mode", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); row = uiLayoutRow(layout, true); @@ -1122,7 +1123,7 @@ static void node_shader_buts_script_ex(uiLayout *layout, bContext *C, PointerRNA #if 0 /* not implemented yet */ if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL) { - uiItemR(layout, ptr, "use_auto_update", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_auto_update", DEFAULT_FLAGS, nullptr, ICON_NONE); } #endif } @@ -1139,21 +1140,21 @@ static void node_buts_output_linestyle(uiLayout *layout, bContext *UNUSED(C), Po col = uiLayoutColumn(layout, false); row = uiLayoutRow(col, true); uiItemR(row, ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_shader_buts_bevel(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "samples", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "samples", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_shader_buts_ambient_occlusion(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "samples", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "inside", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "only_local", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "samples", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "inside", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "only_local", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_shader_buts_white_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1163,7 +1164,7 @@ static void node_shader_buts_white_noise(uiLayout *layout, bContext *UNUSED(C), static void node_shader_buts_output_aov(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "name", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "name", DEFAULT_FLAGS, nullptr, ICON_NONE); } /* only once called */ @@ -1348,17 +1349,17 @@ static void node_buts_image_views(uiLayout *layout, if (RNA_boolean_get(ptr, "has_views")) { if (RNA_enum_get(ptr, "view") == 0) { - uiItemR(col, ptr, "view", DEFAULT_FLAGS, NULL, ICON_CAMERA_STEREO); + uiItemR(col, ptr, "view", DEFAULT_FLAGS, nullptr, ICON_CAMERA_STEREO); } else { - uiItemR(col, ptr, "view", DEFAULT_FLAGS, NULL, ICON_SCENE); + uiItemR(col, ptr, "view", DEFAULT_FLAGS, nullptr, ICON_SCENE); } } } static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; PointerRNA iuserptr; RNA_pointer_create(ptr->owner_id, &RNA_ImageUser, node->storage, &iuserptr); @@ -1369,10 +1370,10 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA * "image", "IMAGE_OT_new", "IMAGE_OT_open", - NULL, + nullptr, UI_TEMPLATE_ID_FILTER_ALL, false, - NULL); + nullptr); if (!node->id) { return; } @@ -1386,20 +1387,29 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA * static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; PointerRNA iuserptr; RNA_pointer_create(ptr->owner_id, &RNA_ImageUser, node->storage, &iuserptr); uiLayoutSetContextPointer(layout, "image_user", &iuserptr); - uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 1); + uiTemplateImage(layout, C, ptr, "image", &iuserptr, false, true); } static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; uiLayout *col, *row; - uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "scene", + nullptr, + nullptr, + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); if (!node->id) { return; @@ -1423,7 +1433,7 @@ static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, Pointer PointerRNA op_ptr; uiItemFullO( - row, "RENDER_OT_render", "", ICON_RENDER_STILL, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + row, "RENDER_OT_render", "", ICON_RENDER_STILL, nullptr, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); RNA_string_set(&op_ptr, "layer", layer_name); RNA_string_set(&op_ptr, "scene", scene_name); } @@ -1438,19 +1448,19 @@ static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), Point uiItemR(col, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE); if (filter != R_FILTER_FAST_GAUSS) { - uiItemR(col, ptr, "use_variable_size", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_variable_size", DEFAULT_FLAGS, nullptr, ICON_NONE); if (!reference) { - uiItemR(col, ptr, "use_bokeh", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_bokeh", DEFAULT_FLAGS, nullptr, ICON_NONE); } - uiItemR(col, ptr, "use_gamma_correction", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_gamma_correction", DEFAULT_FLAGS, nullptr, ICON_NONE); } - uiItemR(col, ptr, "use_relative", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_relative", DEFAULT_FLAGS, nullptr, ICON_NONE); if (RNA_boolean_get(ptr, "use_relative")) { uiItemL(col, IFACE_("Aspect Correction"), ICON_NONE); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "aspect_correction", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "aspect_correction", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); col = uiLayoutColumn(layout, true); uiItemR(col, ptr, "factor_x", DEFAULT_FLAGS, IFACE_("X"), ICON_NONE); @@ -1461,15 +1471,15 @@ static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), Point uiItemR(col, ptr, "size_x", DEFAULT_FLAGS, IFACE_("X"), ICON_NONE); uiItemR(col, ptr, "size_y", DEFAULT_FLAGS, IFACE_("Y"), ICON_NONE); } - uiItemR(col, ptr, "use_extended_bounds", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_extended_bounds", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_dblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *col; - uiItemR(layout, ptr, "iterations", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "use_wrap", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "iterations", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "use_wrap", DEFAULT_FLAGS, nullptr, ICON_NONE); col = uiLayoutColumn(layout, true); uiItemL(col, IFACE_("Center:"), ICON_NONE); @@ -1479,13 +1489,13 @@ static void node_composit_buts_dblur(uiLayout *layout, bContext *UNUSED(C), Poin uiItemS(layout); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "distance", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "angle", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "distance", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "angle", DEFAULT_FLAGS, nullptr, ICON_NONE); uiItemS(layout); - uiItemR(layout, ptr, "spin", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "zoom", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "spin", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "zoom", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_bilateralblur(uiLayout *layout, @@ -1495,9 +1505,9 @@ static void node_composit_buts_bilateralblur(uiLayout *layout, uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "iterations", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "sigma_color", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "sigma_space", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "iterations", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "sigma_color", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "sigma_space", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -1507,27 +1517,36 @@ static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA col = uiLayoutColumn(layout, false); uiItemL(col, IFACE_("Bokeh Type:"), ICON_NONE); uiItemR(col, ptr, "bokeh", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(col, ptr, "angle", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "angle", DEFAULT_FLAGS, nullptr, ICON_NONE); - uiItemR(layout, ptr, "use_gamma_correction", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_gamma_correction", DEFAULT_FLAGS, nullptr, ICON_NONE); col = uiLayoutColumn(layout, false); uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer") == true); - uiItemR(col, ptr, "f_stop", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "f_stop", DEFAULT_FLAGS, nullptr, ICON_NONE); - uiItemR(layout, ptr, "blur_max", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "blur_max", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "threshold", DEFAULT_FLAGS, nullptr, ICON_NONE); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "use_preview", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_preview", DEFAULT_FLAGS, nullptr, ICON_NONE); - uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "scene", + nullptr, + nullptr, + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "use_zbuffer", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_zbuffer", DEFAULT_FLAGS, nullptr, ICON_NONE); sub = uiLayoutColumn(col, false); uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_zbuffer") == false); - uiItemR(sub, ptr, "z_scale", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(sub, ptr, "z_scale", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_antialiasing(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1536,9 +1555,9 @@ static void node_composit_buts_antialiasing(uiLayout *layout, bContext *UNUSED(C col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "contrast_limit", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "corner_rounding", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "threshold", 0, nullptr, ICON_NONE); + uiItemR(col, ptr, "contrast_limit", 0, nullptr, ICON_NONE); + uiItemR(col, ptr, "corner_rounding", 0, nullptr, ICON_NONE); } /* qdn: glare node */ @@ -1548,29 +1567,30 @@ static void node_composit_buts_glare(uiLayout *layout, bContext *UNUSED(C), Poin uiItemR(layout, ptr, "quality", DEFAULT_FLAGS, "", ICON_NONE); if (RNA_enum_get(ptr, "glare_type") != 1) { - uiItemR(layout, ptr, "iterations", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "iterations", DEFAULT_FLAGS, nullptr, ICON_NONE); if (RNA_enum_get(ptr, "glare_type") != 0) { - uiItemR(layout, ptr, "color_modulation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR( + layout, ptr, "color_modulation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); } } - uiItemR(layout, ptr, "mix", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "mix", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "threshold", DEFAULT_FLAGS, nullptr, ICON_NONE); if (RNA_enum_get(ptr, "glare_type") == 2) { - uiItemR(layout, ptr, "streaks", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "angle_offset", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "streaks", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "angle_offset", DEFAULT_FLAGS, nullptr, ICON_NONE); } if (RNA_enum_get(ptr, "glare_type") == 0 || RNA_enum_get(ptr, "glare_type") == 2) { - uiItemR(layout, ptr, "fade", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "fade", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); if (RNA_enum_get(ptr, "glare_type") == 0) { - uiItemR(layout, ptr, "use_rotate_45", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_rotate_45", DEFAULT_FLAGS, nullptr, ICON_NONE); } } if (RNA_enum_get(ptr, "glare_type") == 1) { - uiItemR(layout, ptr, "size", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "size", DEFAULT_FLAGS, nullptr, ICON_NONE); } } @@ -1581,15 +1601,15 @@ static void node_composit_buts_tonemap(uiLayout *layout, bContext *UNUSED(C), Po col = uiLayoutColumn(layout, false); uiItemR(col, ptr, "tonemap_type", DEFAULT_FLAGS, "", ICON_NONE); if (RNA_enum_get(ptr, "tonemap_type") == 0) { - uiItemR(col, ptr, "key", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "gamma", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "key", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "offset", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "gamma", DEFAULT_FLAGS, nullptr, ICON_NONE); } else { - uiItemR(col, ptr, "intensity", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "adaptation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "correction", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "intensity", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "adaptation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "correction", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); } } @@ -1598,12 +1618,12 @@ static void node_composit_buts_lensdist(uiLayout *layout, bContext *UNUSED(C), P uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "use_projector", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_projector", DEFAULT_FLAGS, nullptr, ICON_NONE); col = uiLayoutColumn(col, false); uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_projector") == false); - uiItemR(col, ptr, "use_jitter", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "use_fit", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_jitter", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "use_fit", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1611,7 +1631,7 @@ static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), Po uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "samples", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "samples", DEFAULT_FLAGS, nullptr, ICON_NONE); uiItemR(col, ptr, "factor", DEFAULT_FLAGS, IFACE_("Blur"), ICON_NONE); col = uiLayoutColumn(layout, true); @@ -1619,7 +1639,7 @@ static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), Po uiItemR(col, ptr, "speed_min", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE); uiItemR(col, ptr, "speed_max", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE); - uiItemR(layout, ptr, "use_curved", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_curved", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_filter(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1636,8 +1656,8 @@ static void node_composit_buts_crop(uiLayout *layout, bContext *UNUSED(C), Point { uiLayout *col; - uiItemR(layout, ptr, "use_crop_size", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "relative", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_crop_size", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "relative", DEFAULT_FLAGS, nullptr, ICON_NONE); col = uiLayoutColumn(layout, true); if (RNA_boolean_get(ptr, "relative")) { @@ -1660,8 +1680,8 @@ static void node_composit_buts_splitviewer(uiLayout *layout, bContext *UNUSED(C) col = uiLayoutColumn(layout, false); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(col, ptr, "factor", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); + uiItemR(col, ptr, "factor", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_double_edge_mask(uiLayout *layout, @@ -1683,7 +1703,7 @@ static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1691,17 +1711,17 @@ static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), uiLayout *sub, *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "size", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "offset", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "size", DEFAULT_FLAGS, nullptr, ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_min", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_min", DEFAULT_FLAGS, nullptr, ICON_NONE); sub = uiLayoutColumn(col, false); uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min")); uiItemR(sub, ptr, "min", DEFAULT_FLAGS, "", ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_max", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_max", DEFAULT_FLAGS, nullptr, ICON_NONE); sub = uiLayoutColumn(col, false); uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max")); uiItemR(sub, ptr, "max", DEFAULT_FLAGS, "", ICON_NONE); @@ -1712,8 +1732,8 @@ static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_premultiply", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "premul", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_premultiply", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "premul", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1721,27 +1741,27 @@ static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), P uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "use_antialias_z", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_alpha", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "use_antialias_z", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_dilateerode(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, nullptr, ICON_NONE); switch (RNA_enum_get(ptr, "mode")) { case CMP_NODE_DILATEERODE_DISTANCE_THRESH: - uiItemR(layout, ptr, "edge", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "edge", DEFAULT_FLAGS, nullptr, ICON_NONE); break; case CMP_NODE_DILATEERODE_DISTANCE_FEATHER: - uiItemR(layout, ptr, "falloff", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "falloff", DEFAULT_FLAGS, nullptr, ICON_NONE); break; } } static void node_composit_buts_inpaint(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1749,8 +1769,8 @@ static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "threshold_neighbor", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "threshold", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "threshold_neighbor", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1758,8 +1778,8 @@ static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "falloff", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "falloff", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); } static void node_composit_buts_distance_matte(uiLayout *layout, @@ -1772,10 +1792,10 @@ static void node_composit_buts_distance_matte(uiLayout *layout, uiItemL(layout, IFACE_("Color Space:"), ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); - uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "falloff", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "falloff", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); } static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1784,23 +1804,23 @@ static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C) uiItemL(layout, IFACE_("Despill Channel:"), ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "limit_method", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_method", DEFAULT_FLAGS, nullptr, ICON_NONE); if (RNA_enum_get(ptr, "limit_method") == 0) { uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "limit_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "limit_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); } - uiItemR(col, ptr, "ratio", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "use_unspill", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "ratio", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "use_unspill", DEFAULT_FLAGS, nullptr, ICON_NONE); if (RNA_boolean_get(ptr, "use_unspill") == true) { - uiItemR(col, ptr, "unspill_red", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "unspill_green", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "unspill_blue", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "unspill_red", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "unspill_green", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "unspill_blue", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); } } @@ -1809,13 +1829,15 @@ static void node_composit_buts_chroma_matte(uiLayout *layout, bContext *UNUSED(C uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "threshold", DEFAULT_FLAGS, nullptr, ICON_NONE); col = uiLayoutColumn(layout, true); - /*uiItemR(col, ptr, "lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); Removed for now */ - uiItemR(col, ptr, "gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - /*uiItemR(col, ptr, "shadow_adjust", UI_ITEM_R_SLIDER, NULL, ICON_NONE); Removed for now*/ + /* Removed for now. */ + // uiItemR(col, ptr, "lift", UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + /* Removed for now. */ + // uiItemR(col, ptr, "shadow_adjust", UI_ITEM_R_SLIDER, nullptr, ICON_NONE); } static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1823,9 +1845,9 @@ static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C) uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "color_hue", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "color_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "color_value", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "color_hue", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "color_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "color_value", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); } static void node_composit_buts_channel_matte(uiLayout *layout, @@ -1836,24 +1858,24 @@ static void node_composit_buts_channel_matte(uiLayout *layout, uiItemL(layout, IFACE_("Color Space:"), ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "color_space", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "color_space", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); col = uiLayoutColumn(layout, false); uiItemL(col, IFACE_("Key Channel:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "matte_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "matte_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "limit_method", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_method", DEFAULT_FLAGS, nullptr, ICON_NONE); if (RNA_enum_get(ptr, "limit_method") == 0) { uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "limit_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "limit_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); } - uiItemR(col, ptr, "limit_max", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "limit_min", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_max", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "limit_min", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); } static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1861,19 +1883,19 @@ static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "limit_max", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "limit_min", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_max", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(col, ptr, "limit_min", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); } static void node_composit_buts_map_uv(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "alpha", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "alpha", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "index", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "use_antialiasing", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "index", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "use_antialiasing", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1905,7 +1927,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi /* disable stereo output for multilayer, too much work for something that no one will use */ /* if someone asks for that we can implement it */ if (is_multiview) { - uiTemplateImageFormatViews(layout, &imfptr, NULL); + uiTemplateImageFormatViews(layout, &imfptr, nullptr); } uiItemS(layout); @@ -1926,7 +1948,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi "layer_slots", ptr, "active_input_index", - NULL, + nullptr, 0, 0, 0, @@ -1945,7 +1967,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi "file_slots", ptr, "active_input_index", - NULL, + nullptr, 0, 0, 0, @@ -1961,9 +1983,9 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi col = uiLayoutColumn(row, true); wmOperatorType *ot = WM_operatortype_find("NODE_OT_output_file_move_active_socket", false); - uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, nullptr, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); RNA_enum_set(&op_ptr, "direction", 1); - uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, nullptr, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); RNA_enum_set(&op_ptr, "direction", 2); if (active_input_ptr.data) { @@ -1977,10 +1999,10 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi "NODE_OT_output_file_remove_active_socket", "", ICON_X, - NULL, + nullptr, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY, - NULL); + nullptr); } else { col = uiLayoutColumn(layout, true); @@ -1992,23 +2014,23 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi "NODE_OT_output_file_remove_active_socket", "", ICON_X, - NULL, + nullptr, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY, - NULL); + nullptr); /* format details for individual files */ imfptr = RNA_pointer_get(&active_input_ptr, "format"); col = uiLayoutColumn(layout, true); uiItemL(col, IFACE_("Format:"), ICON_NONE); - uiItemR(col, &active_input_ptr, "use_node_format", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, &active_input_ptr, "use_node_format", DEFAULT_FLAGS, nullptr, ICON_NONE); const bool is_socket_exr = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_OPENEXR; const bool use_node_format = RNA_boolean_get(&active_input_ptr, "use_node_format"); if ((!is_exr && use_node_format) || (!is_socket_exr && !use_node_format)) { - uiItemR(col, &active_input_ptr, "save_as_render", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, &active_input_ptr, "save_as_render", DEFAULT_FLAGS, nullptr, ICON_NONE); } col = uiLayoutColumn(layout, false); @@ -2016,7 +2038,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi uiTemplateImageSettings(col, &imfptr, false); if (is_multiview) { - uiTemplateImageFormatViews(layout, &imfptr, NULL); + uiTemplateImageFormatViews(layout, &imfptr, nullptr); } } } @@ -2028,7 +2050,7 @@ static void node_composit_buts_scale(uiLayout *layout, bContext *UNUSED(C), Poin if (RNA_enum_get(ptr, "space") == CMP_SCALE_RENDERPERCENT) { uiLayout *row; - uiItemR(layout, ptr, "frame_method", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "frame_method", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); row = uiLayoutRow(layout, true); uiItemR(row, ptr, "offset_x", DEFAULT_FLAGS, "X", ICON_NONE); uiItemR(row, ptr, "offset_y", DEFAULT_FLAGS, "Y", ICON_NONE); @@ -2045,8 +2067,8 @@ static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), Poi uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "invert_rgb", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "invert_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "invert_rgb", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "invert_alpha", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_premulkey(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2056,86 +2078,86 @@ static void node_composit_buts_premulkey(uiLayout *layout, bContext *UNUSED(C), static void node_composit_buts_view_levels(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); } static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *split, *col, *row; - uiItemR(layout, ptr, "correction_method", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "correction_method", DEFAULT_FLAGS, nullptr, ICON_NONE); if (RNA_enum_get(ptr, "correction_method") == 0) { split = uiLayoutSplit(layout, 0.0f, false); col = uiLayoutColumn(split, false); - uiTemplateColorPicker(col, ptr, "lift", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "lift", true, true, false, true); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "lift", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "lift", DEFAULT_FLAGS, nullptr, ICON_NONE); col = uiLayoutColumn(split, false); - uiTemplateColorPicker(col, ptr, "gamma", 1, 1, 1, 1); + uiTemplateColorPicker(col, ptr, "gamma", true, true, true, true); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "gamma", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "gamma", DEFAULT_FLAGS, nullptr, ICON_NONE); col = uiLayoutColumn(split, false); - uiTemplateColorPicker(col, ptr, "gain", 1, 1, 1, 1); + uiTemplateColorPicker(col, ptr, "gain", true, true, true, true); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "gain", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "gain", DEFAULT_FLAGS, nullptr, ICON_NONE); } else { split = uiLayoutSplit(layout, 0.0f, false); col = uiLayoutColumn(split, false); - uiTemplateColorPicker(col, ptr, "offset", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "offset", true, true, false, true); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "offset_basis", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "offset", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "offset_basis", DEFAULT_FLAGS, nullptr, ICON_NONE); col = uiLayoutColumn(split, false); - uiTemplateColorPicker(col, ptr, "power", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "power", true, true, false, true); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "power", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "power", DEFAULT_FLAGS, nullptr, ICON_NONE); col = uiLayoutColumn(split, false); - uiTemplateColorPicker(col, ptr, "slope", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "slope", true, true, false, true); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "slope", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "slope", DEFAULT_FLAGS, nullptr, ICON_NONE); } } static void node_composit_buts_colorbalance_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "correction_method", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "correction_method", DEFAULT_FLAGS, nullptr, ICON_NONE); if (RNA_enum_get(ptr, "correction_method") == 0) { - uiTemplateColorPicker(layout, ptr, "lift", 1, 1, 0, 1); - uiItemR(layout, ptr, "lift", DEFAULT_FLAGS, NULL, ICON_NONE); + uiTemplateColorPicker(layout, ptr, "lift", true, true, false, true); + uiItemR(layout, ptr, "lift", DEFAULT_FLAGS, nullptr, ICON_NONE); - uiTemplateColorPicker(layout, ptr, "gamma", 1, 1, 1, 1); - uiItemR(layout, ptr, "gamma", DEFAULT_FLAGS, NULL, ICON_NONE); + uiTemplateColorPicker(layout, ptr, "gamma", true, true, true, true); + uiItemR(layout, ptr, "gamma", DEFAULT_FLAGS, nullptr, ICON_NONE); - uiTemplateColorPicker(layout, ptr, "gain", 1, 1, 1, 1); - uiItemR(layout, ptr, "gain", DEFAULT_FLAGS, NULL, ICON_NONE); + uiTemplateColorPicker(layout, ptr, "gain", true, true, true, true); + uiItemR(layout, ptr, "gain", DEFAULT_FLAGS, nullptr, ICON_NONE); } else { - uiTemplateColorPicker(layout, ptr, "offset", 1, 1, 0, 1); - uiItemR(layout, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE); + uiTemplateColorPicker(layout, ptr, "offset", true, true, false, true); + uiItemR(layout, ptr, "offset", DEFAULT_FLAGS, nullptr, ICON_NONE); - uiTemplateColorPicker(layout, ptr, "power", 1, 1, 0, 1); - uiItemR(layout, ptr, "power", DEFAULT_FLAGS, NULL, ICON_NONE); + uiTemplateColorPicker(layout, ptr, "power", true, true, false, true); + uiItemR(layout, ptr, "power", DEFAULT_FLAGS, nullptr, ICON_NONE); - uiTemplateColorPicker(layout, ptr, "slope", 1, 1, 0, 1); - uiItemR(layout, ptr, "slope", DEFAULT_FLAGS, NULL, ICON_NONE); + uiTemplateColorPicker(layout, ptr, "slope", true, true, false, true); + uiItemR(layout, ptr, "slope", DEFAULT_FLAGS, nullptr, ICON_NONE); } } static void node_composit_buts_huecorrect(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - bNode *node = ptr->data; - CurveMapping *cumap = node->storage; + bNode *node = (bNode *)ptr->data; + CurveMapping *cumap = (CurveMapping *)node->storage; if (_sample_col[0] != SAMPLE_FLT_ISNONE) { cumap->flag |= CUMA_DRAW_SAMPLE; @@ -2155,17 +2177,33 @@ static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), Pointe static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr) { - uiTemplateID( - layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + nullptr, + "CLIP_OT_open", + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); } static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; PointerRNA clipptr; - uiTemplateID( - layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + nullptr, + "CLIP_OT_open", + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); if (!node->id) { return; @@ -2178,23 +2216,31 @@ static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, Point static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; - uiTemplateID( - layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + nullptr, + "CLIP_OT_open", + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); if (!node->id) { return; } uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_translate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_relative", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "wrap_axis", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_relative", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "wrap_axis", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2204,10 +2250,18 @@ static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; - uiTemplateID( - layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + nullptr, + "CLIP_OT_open", + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); if (!node->id) { return; @@ -2223,9 +2277,9 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, uiLayout *row; row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "red", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(row, ptr, "green", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(row, ptr, "blue", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "red", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(row, ptr, "green", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(row, ptr, "blue", DEFAULT_FLAGS, nullptr, ICON_NONE); row = uiLayoutRow(layout, false); uiItemL(row, "", ICON_NONE); @@ -2268,8 +2322,8 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, uiItemR(row, ptr, "shadows_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "midtones_start", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_end", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_start", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "midtones_end", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); } static void node_composit_buts_colorcorrection_ex(uiLayout *layout, @@ -2279,53 +2333,53 @@ static void node_composit_buts_colorcorrection_ex(uiLayout *layout, uiLayout *row; row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "red", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(row, ptr, "green", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(row, ptr, "blue", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "red", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(row, ptr, "green", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(row, ptr, "blue", DEFAULT_FLAGS, nullptr, ICON_NONE); row = layout; uiItemL(row, IFACE_("Saturation"), ICON_NONE); - uiItemR(row, ptr, "master_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "highlights_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "midtones_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "shadows_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); uiItemL(row, IFACE_("Contrast"), ICON_NONE); - uiItemR(row, ptr, "master_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "highlights_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "midtones_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "shadows_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); uiItemL(row, IFACE_("Gamma"), ICON_NONE); - uiItemR(row, ptr, "master_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "highlights_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "midtones_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "shadows_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); uiItemL(row, IFACE_("Gain"), ICON_NONE); - uiItemR(row, ptr, "master_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "highlights_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "midtones_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "shadows_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); uiItemL(row, IFACE_("Lift"), ICON_NONE); - uiItemR(row, ptr, "master_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "highlights_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "midtones_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "shadows_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "midtones_start", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_end", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_start", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(row, ptr, "midtones_end", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_set_alpha(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "check", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "check", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_switch_view_ex(uiLayout *layout, @@ -2336,10 +2390,10 @@ static void node_composit_buts_switch_view_ex(uiLayout *layout, "NODE_OT_switch_view_update", "Update Views", ICON_FILE_REFRESH, - NULL, + nullptr, WM_OP_INVOKE_DEFAULT, 0, - NULL); + nullptr); } static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2347,32 +2401,32 @@ static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), Po uiLayout *row; row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "x", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(row, ptr, "y", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "x", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(row, ptr, "y", DEFAULT_FLAGS, nullptr, ICON_NONE); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "width", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "height", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "width", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "height", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); - uiItemR(layout, ptr, "rotation", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "mask_type", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "rotation", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "mask_type", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_bokehimage(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "flaps", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "angle", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "rounding", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(layout, ptr, "catadioptric", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(layout, ptr, "shift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "flaps", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "angle", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "rounding", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(layout, ptr, "catadioptric", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(layout, ptr, "shift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); } static void node_composit_buts_bokehblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_variable_size", DEFAULT_FLAGS, NULL, ICON_NONE); - // uiItemR(layout, ptr, "f_stop", DEFAULT_FLAGS, NULL, ICON_NONE); /* UNUSED */ - uiItemR(layout, ptr, "blur_max", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "use_extended_bounds", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_variable_size", DEFAULT_FLAGS, nullptr, ICON_NONE); + // uiItemR(layout, ptr, "f_stop", DEFAULT_FLAGS, nullptr, ICON_NONE); /* UNUSED */ + uiItemR(layout, ptr, "blur_max", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "use_extended_bounds", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_backdrop_viewer( @@ -2407,7 +2461,7 @@ static void node_composit_backdrop_viewer( static void node_composit_backdrop_boxmask( SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y) { - NodeBoxMask *boxmask = node->storage; + NodeBoxMask *boxmask = (NodeBoxMask *)node->storage; const float backdropWidth = backdrop->x; const float backdropHeight = backdrop->y; const float aspect = backdropWidth / backdropHeight; @@ -2452,7 +2506,7 @@ static void node_composit_backdrop_boxmask( static void node_composit_backdrop_ellipsemask( SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y) { - NodeEllipseMask *ellipsemask = node->storage; + NodeEllipseMask *ellipsemask = (NodeEllipseMask *)node->storage; const float backdropWidth = backdrop->x; const float backdropHeight = backdrop->y; const float aspect = backdropWidth / backdropHeight; @@ -2498,65 +2552,83 @@ static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C) { uiLayout *row; row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "x", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(row, ptr, "y", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "x", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(row, ptr, "y", DEFAULT_FLAGS, nullptr, ICON_NONE); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "width", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "height", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "width", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + uiItemR(row, ptr, "height", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); - uiItemR(layout, ptr, "rotation", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "mask_type", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "rotation", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "mask_type", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_composite(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_viewer(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_viewer_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *col; - uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "tile_order", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "tile_order", DEFAULT_FLAGS, nullptr, ICON_NONE); if (RNA_enum_get(ptr, "tile_order") == 0) { col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "center_x", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(col, ptr, "center_y", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "center_x", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(col, ptr, "center_y", DEFAULT_FLAGS, nullptr, ICON_NONE); } } static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; - uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); - uiItemR(layout, ptr, "use_feather", DEFAULT_FLAGS, NULL, ICON_NONE); + uiTemplateID(layout, + C, + ptr, + "mask", + nullptr, + nullptr, + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); + uiItemR(layout, ptr, "use_feather", DEFAULT_FLAGS, nullptr, ICON_NONE); uiItemR(layout, ptr, "size_source", DEFAULT_FLAGS, "", ICON_NONE); if (node->custom1 & (CMP_NODEFLAG_MASK_FIXED | CMP_NODEFLAG_MASK_FIXED_SCENE)) { - uiItemR(layout, ptr, "size_x", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "size_y", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "size_x", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "size_y", DEFAULT_FLAGS, nullptr, ICON_NONE); } - uiItemR(layout, ptr, "use_motion_blur", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_motion_blur", DEFAULT_FLAGS, nullptr, ICON_NONE); if (node->custom1 & CMP_NODEFLAG_MASK_MOTION_BLUR) { - uiItemR(layout, ptr, "motion_blur_samples", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "motion_blur_shutter", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "motion_blur_samples", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "motion_blur_shutter", DEFAULT_FLAGS, nullptr, ICON_NONE); } } static void node_composit_buts_keyingscreen(uiLayout *layout, bContext *C, PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; - uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + nullptr, + nullptr, + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); if (node->id) { MovieClip *clip = (MovieClip *)node->id; @@ -2572,28 +2644,36 @@ static void node_composit_buts_keyingscreen(uiLayout *layout, bContext *C, Point static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - /* bNode *node = ptr->data; */ /* UNUSED */ + /* bNode *node = (bNode*)ptr->data; */ /* UNUSED */ - uiItemR(layout, ptr, "blur_pre", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "screen_balance", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "despill_factor", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "despill_balance", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "edge_kernel_radius", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "edge_kernel_tolerance", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "clip_black", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "clip_white", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "dilate_distance", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "feather_falloff", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "feather_distance", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "blur_post", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "blur_pre", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "screen_balance", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "despill_factor", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "despill_balance", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "edge_kernel_radius", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "edge_kernel_tolerance", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "clip_black", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "clip_white", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "dilate_distance", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "feather_falloff", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "feather_distance", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "blur_post", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; - uiTemplateID( - layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + nullptr, + "CLIP_OT_open", + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); if (node->id) { MovieClip *clip = (MovieClip *)node->id; @@ -2601,7 +2681,7 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN MovieTrackingObject *object; uiLayout *col; PointerRNA tracking_ptr; - NodeTrackPosData *data = node->storage; + NodeTrackPosData *data = (NodeTrackPosData *)node->storage; RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking, &tracking_ptr); @@ -2620,21 +2700,29 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN uiItemR(layout, ptr, "track_name", DEFAULT_FLAGS, "", ICON_ANIM_DATA); } - uiItemR(layout, ptr, "position", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "position", DEFAULT_FLAGS, nullptr, ICON_NONE); if (ELEM(node->custom1, CMP_TRACKPOS_RELATIVE_FRAME, CMP_TRACKPOS_ABSOLUTE_FRAME)) { - uiItemR(layout, ptr, "frame_relative", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "frame_relative", DEFAULT_FLAGS, nullptr, ICON_NONE); } } } static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, PointerRNA *ptr) { - bNode *node = ptr->data; - NodePlaneTrackDeformData *data = node->storage; + bNode *node = (bNode *)ptr->data; + NodePlaneTrackDeformData *data = (NodePlaneTrackDeformData *)node->storage; - uiTemplateID( - layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + nullptr, + "CLIP_OT_open", + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); if (node->id) { MovieClip *clip = (MovieClip *)node->id; @@ -2662,10 +2750,10 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P } } - uiItemR(layout, ptr, "use_motion_blur", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_motion_blur", DEFAULT_FLAGS, nullptr, ICON_NONE); if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) { - uiItemR(layout, ptr, "motion_blur_samples", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "motion_blur_shutter", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "motion_blur_samples", DEFAULT_FLAGS, nullptr, ICON_NONE); + uiItemR(layout, ptr, "motion_blur_shutter", DEFAULT_FLAGS, nullptr, ICON_NONE); } } @@ -2678,7 +2766,7 @@ static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout), static void node_composit_buts_sunbeams(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "source", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, "", ICON_NONE); - uiItemR(layout, ptr, "ray_length", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "ray_length", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, nullptr, ICON_NONE); } static void node_composit_buts_cryptomatte_legacy(uiLayout *layout, @@ -2706,18 +2794,35 @@ static void node_composit_buts_cryptomatte_legacy_ex(uiLayout *layout, static void node_composit_buts_cryptomatte(uiLayout *layout, bContext *C, PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; uiLayout *row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "source", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "source", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); uiLayout *col = uiLayoutColumn(layout, false); if (node->custom1 == CMP_CRYPTOMATTE_SRC_RENDER) { - uiTemplateID(col, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(col, + C, + ptr, + "scene", + nullptr, + nullptr, + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); } else { - uiTemplateID( - col, C, ptr, "image", NULL, "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(col, + C, + ptr, + "image", + nullptr, + "IMAGE_OT_open", + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); NodeCryptomatte *crypto = (NodeCryptomatte *)node->storage; PointerRNA imaptr = RNA_pointer_get(ptr, "image"); @@ -2743,7 +2848,7 @@ static void node_composit_buts_brightcontrast(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_premultiply", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_premultiply", DEFAULT_FLAGS, nullptr, ICON_NONE); } static void node_composit_buts_denoise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2753,14 +2858,13 @@ static void node_composit_buts_denoise(uiLayout *layout, bContext *UNUSED(C), Po #else /* Always supported through Accelerate framework BNNS on macOS. */ # ifndef __APPLE__ - if (!BLI_cpu_support_sse41()) -# endif - { + if (!BLI_cpu_support_sse41()) { uiItemL(layout, IFACE_("Disabled, CPU with SSE4.1 is required"), ICON_ERROR); } +# endif #endif - uiItemR(layout, ptr, "use_hdr", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_hdr", DEFAULT_FLAGS, nullptr, ICON_NONE); } /* only once called */ @@ -3030,7 +3134,7 @@ static void node_texture_buts_bricks(uiLayout *layout, bContext *UNUSED(C), Poin static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { PointerRNA tex_ptr; - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; ID *id = ptr->owner_id; Tex *tex = (Tex *)node->storage; uiLayout *col, *row; @@ -3043,29 +3147,31 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe case TEX_BLEND: uiItemR(col, &tex_ptr, "progression", DEFAULT_FLAGS, "", ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "use_flip_axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR( + row, &tex_ptr, "use_flip_axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); break; case TEX_MARBLE: row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "marble_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "marble_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); row = uiLayoutRow(col, false); uiItemR(row, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR( + row, &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); break; case TEX_MAGIC: - uiItemR(col, &tex_ptr, "noise_depth", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, &tex_ptr, "noise_depth", DEFAULT_FLAGS, nullptr, ICON_NONE); break; case TEX_STUCCI: row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "stucci_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "stucci_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); break; @@ -3073,18 +3179,19 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); uiItemR(col, &tex_ptr, "wood_type", DEFAULT_FLAGS, "", ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR( + row, &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); row = uiLayoutRow(col, false); uiLayoutSetActive(row, !(ELEM(tex->stype, TEX_BAND, TEX_RING))); - uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); break; case TEX_CLOUDS: uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "cloud_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "cloud_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); uiItemR(col, &tex_ptr, "noise_depth", @@ -3105,7 +3212,7 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe case TEX_VORONOI: uiItemR(col, &tex_ptr, "distance_metric", DEFAULT_FLAGS, "", ICON_NONE); if (tex->vn_distm == TEX_MINKOVSKY) { - uiItemR(col, &tex_ptr, "minkovsky_exponent", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, &tex_ptr, "minkovsky_exponent", DEFAULT_FLAGS, nullptr, ICON_NONE); } uiItemR(col, &tex_ptr, "color_mode", DEFAULT_FLAGS, "", ICON_NONE); break; @@ -3120,19 +3227,19 @@ static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *p "image", "IMAGE_OT_new", "IMAGE_OT_open", - NULL, + nullptr, UI_TEMPLATE_ID_FILTER_ALL, false, - NULL); + nullptr); } static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; PointerRNA iuserptr; RNA_pointer_create(ptr->owner_id, &RNA_ImageUser, node->storage, &iuserptr); - uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0); + uiTemplateImage(layout, C, ptr, "image", &iuserptr, false, false); } static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -3189,12 +3296,16 @@ static void node_texture_set_butfunc(bNodeType *ntype) } } -/* ****** init draw callbacks for all tree types, only called in usiblender.c, once ************ */ +/* -------------------------------------------------------------------- */ +/** \name Init Draw Callbacks For All Tree Types + * + * Only called on node initialization, once. + * \{ */ static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { bNodeTree *ntree = (bNodeTree *)ptr->owner_id; - bNode *node = ptr->data; + bNode *node = (bNode *)ptr->data; ED_node_tag_update_nodetree(bmain, ntree, node); } @@ -3204,7 +3315,7 @@ static void node_socket_template_properties_update(bNodeType *ntype, bNodeSocket PropertyRNA *prop = RNA_struct_type_find_property(srna, stemp->identifier); if (prop) { - RNA_def_property_update_runtime(prop, node_property_update_default); + RNA_def_property_update_runtime(prop, (const void *)node_property_update_default); } } @@ -3261,6 +3372,8 @@ static void node_socket_undefined_interface_draw_color(bContext *UNUSED(C), r_color[3] = 1.0f; } +/** \} */ + void ED_node_init_butfuncs(void) { /* Fallback types for undefined tree, nodes, sockets @@ -3272,8 +3385,8 @@ void ED_node_init_butfuncs(void) NodeTypeUndefined.draw_nodetype_prepare = node_update_default; NodeTypeUndefined.select_area_func = node_select_area_default; NodeTypeUndefined.tweak_area_func = node_tweak_area_default; - NodeTypeUndefined.draw_buttons = NULL; - NodeTypeUndefined.draw_buttons_ex = NULL; + NodeTypeUndefined.draw_buttons = nullptr; + NodeTypeUndefined.draw_buttons_ex = nullptr; NodeTypeUndefined.resize_area_func = node_resize_area_default; NodeSocketTypeUndefined.draw = node_socket_undefined_draw; @@ -3350,7 +3463,7 @@ static void std_node_socket_draw_color(bContext *UNUSED(C), PointerRNA *UNUSED(node_ptr), float *r_color) { - bNodeSocket *sock = ptr->data; + bNodeSocket *sock = (bNodeSocket *)ptr->data; int type = sock->typeinfo->type; copy_v4_v4(r_color, std_node_socket_colors[type]); } @@ -3358,7 +3471,7 @@ static void std_node_socket_interface_draw_color(bContext *UNUSED(C), PointerRNA *ptr, float *r_color) { - bNodeSocket *sock = ptr->data; + bNodeSocket *sock = (bNodeSocket *)ptr->data; int type = sock->typeinfo->type; copy_v4_v4(r_color, std_node_socket_colors[type]); } @@ -3371,7 +3484,7 @@ static void node_file_output_socket_draw(bContext *C, PointerRNA *node_ptr) { bNodeTree *ntree = (bNodeTree *)ptr->owner_id; - bNodeSocket *sock = ptr->data; + bNodeSocket *sock = (bNodeSocket *)ptr->data; uiLayout *row; PointerRNA inputptr; @@ -3381,13 +3494,13 @@ static void node_file_output_socket_draw(bContext *C, int imtype = RNA_enum_get(&imfptr, "file_format"); if (imtype == R_IMF_IMTYPE_MULTILAYER) { - NodeImageMultiFileSocket *input = sock->storage; + NodeImageMultiFileSocket *input = (NodeImageMultiFileSocket *)sock->storage; RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr); uiItemL(row, input->layer, ICON_NONE); } else { - NodeImageMultiFileSocket *input = sock->storage; + NodeImageMultiFileSocket *input = (NodeImageMultiFileSocket *)sock->storage; uiBlock *block; RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr); @@ -3414,10 +3527,10 @@ static void node_file_output_socket_draw(bContext *C, static void std_node_socket_draw( bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, const char *text) { - bNode *node = node_ptr->data; - bNodeSocket *sock = ptr->data; + bNode *node = (bNode *)node_ptr->data; + bNodeSocket *sock = (bNodeSocket *)ptr->data; int type = sock->typeinfo->type; - /*int subtype = sock->typeinfo->subtype;*/ + // int subtype = sock->typeinfo->subtype; /* XXX not nice, eventually give this node its own socket type ... */ if (node->type == CMP_NODE_OUTPUT_FILE) { @@ -3430,6 +3543,8 @@ static void std_node_socket_draw( return; } + text = (sock->flag & SOCK_HIDE_LABEL) ? "" : text; + switch (type) { case SOCK_FLOAT: case SOCK_INT: @@ -3483,7 +3598,8 @@ static void std_node_socket_draw( break; } case SOCK_TEXTURE: { - uiTemplateID(layout, C, ptr, "default_value", "texture.new", NULL, NULL, 0, ICON_NONE, NULL); + uiTemplateID( + layout, C, ptr, "default_value", "texture.new", nullptr, nullptr, 0, ICON_NONE, nullptr); break; } case SOCK_MATERIAL: { @@ -3498,7 +3614,7 @@ static void std_node_socket_draw( static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout, PointerRNA *ptr) { - bNodeSocket *sock = ptr->data; + bNodeSocket *sock = (bNodeSocket *)ptr->data; int type = sock->typeinfo->type; uiLayout *col = uiLayoutColumn(layout, false); @@ -3533,7 +3649,7 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout } } - uiItemR(layout, ptr, "hide_value", DEFAULT_FLAGS, NULL, 0); + uiItemR(layout, ptr, "hide_value", DEFAULT_FLAGS, nullptr, 0); } void ED_init_standard_node_socket_type(bNodeSocketType *stype) @@ -3600,7 +3716,7 @@ void draw_nodespace_back_pix(const bContext *C, void *lock; Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock); if (ibuf) { /* somehow the offset has to be calculated inverse */ wmOrtho2_region_pixelspace(region); @@ -3609,7 +3725,7 @@ void draw_nodespace_back_pix(const bContext *C, /** \note draw selected info on backdrop */ if (snode->edittree) { - bNode *node = snode->edittree->nodes.first; + bNode *node = (bNode *)snode->edittree->nodes.first; rctf *viewer_border = &snode->nodetree->viewer_border; while (node) { if (node->flag & NODE_SELECT) { @@ -3646,7 +3762,7 @@ void draw_nodespace_back_pix(const bContext *C, GPU_matrix_pop(); } -/* return quadratic beziers points for a given nodelink and clip if v2d is not NULL. */ +/* return quadratic beziers points for a given nodelink and clip if v2d is not nullptr. */ bool node_link_bezier_handles(const View2D *v2d, const SpaceNode *snode, const bNodeLink *link, @@ -3676,7 +3792,7 @@ bool node_link_bezier_handles(const View2D *v2d, fromreroute = (link->fromnode && link->fromnode->type == NODE_REROUTE); } else { - if (snode == NULL) { + if (snode == nullptr) { return false; } copy_v2_v2(vec[0], cursor); @@ -3695,7 +3811,7 @@ bool node_link_bezier_handles(const View2D *v2d, toreroute = (link->tonode && link->tonode->type == NODE_REROUTE); } else { - if (snode == NULL) { + if (snode == nullptr) { return false; } copy_v2_v2(vec[3], cursor); @@ -3755,7 +3871,7 @@ bool node_link_bezier_handles(const View2D *v2d, return true; } -/* if v2d not NULL, it clips and returns 0 if not visible */ +/* if v2d not nullptr, it clips and returns 0 if not visible */ bool node_link_bezier_points(const View2D *v2d, const SpaceNode *snode, const bNodeLink *link, @@ -3788,6 +3904,7 @@ static float arrow_expand_axis[3][2] = {{0.7071f, 0.7071f}, {M_SQRT2, 0.0f}, {0. static float mute_verts[3][2] = {{0.7071f, 1.0f}, {0.7071f, 0.0f}, {0.7071f, -1.0f}}; static float mute_expand_axis[3][2] = {{1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, -0.0f}}; +/* Is zero initialized because it is static data. */ static struct { GPUBatch *batch; /* for batching line together */ GPUBatch *batch_single; /* for single line */ @@ -3798,9 +3915,9 @@ static struct { GPUVertBufRaw colid_step, muted_step; uint count; bool enabled; -} g_batch_link = {0}; +} g_batch_link; -static void nodelink_batch_reset(void) +static void nodelink_batch_reset() { GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p0_id, &g_batch_link.p0_step); GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p1_id, &g_batch_link.p1_step); @@ -3827,7 +3944,7 @@ static void set_nodelink_vertex(GPUVertBuf *vbo, GPU_vertbuf_attr_set(vbo, exp_id, v, exp); } -static void nodelink_batch_init(void) +static void nodelink_batch_init() { GPUVertFormat format = {0}; uint uv_id = GPU_vertformat_attr_add(&format, "uv", GPU_COMP_U8, 2, GPU_FETCH_INT_TO_FLOAT_UNIT); @@ -3906,10 +4023,11 @@ static void nodelink_batch_init(void) } } - g_batch_link.batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO); + g_batch_link.batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, nullptr, GPU_BATCH_OWNS_VBO); gpu_batch_presets_register(g_batch_link.batch); - g_batch_link.batch_single = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, 0); + g_batch_link.batch_single = GPU_batch_create_ex( + GPU_PRIM_TRI_STRIP, vbo, nullptr, GPU_BATCH_INVALID); gpu_batch_presets_register(g_batch_link.batch_single); /* Instances data */ @@ -4009,16 +4127,16 @@ static void nodelink_batch_add_link(const SpaceNode *snode, BLI_assert(ELEM(th_col3, TH_WIRE, TH_REDALERT, -1)); g_batch_link.count++; - copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p0_step), p0); - copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p1_step), p1); - copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p2_step), p2); - copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p3_step), p3); - char *colid = GPU_vertbuf_raw_step(&g_batch_link.colid_step); + copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p0_step), p0); + copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p1_step), p1); + copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p2_step), p2); + copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p3_step), p3); + char *colid = (char *)GPU_vertbuf_raw_step(&g_batch_link.colid_step); colid[0] = nodelink_get_color_id(th_col1); colid[1] = nodelink_get_color_id(th_col2); colid[2] = nodelink_get_color_id(th_col3); colid[3] = drawarrow; - char *muted = GPU_vertbuf_raw_step(&g_batch_link.muted_step); + char *muted = (char *)GPU_vertbuf_raw_step(&g_batch_link.muted_step); muted[0] = drawmuted; if (g_batch_link.count == NODELINK_GROUP_SIZE) { @@ -4040,7 +4158,7 @@ void node_draw_link_bezier(const View2D *v2d, int drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) && (link->fromnode && (link->fromnode->type == NODE_REROUTE))); int drawmuted = (link->flag & NODE_LINK_MUTED); - if (g_batch_link.batch == NULL) { + if (g_batch_link.batch == nullptr) { nodelink_batch_init(); } @@ -4077,12 +4195,12 @@ void node_draw_link_bezier(const View2D *v2d, } } -/* note; this is used for fake links in groups too */ +/* NOTE: this is used for fake links in groups too. */ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) { int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE; - if (link->fromsock == NULL && link->tosock == NULL) { + if (link->fromsock == nullptr && link->tosock == nullptr) { return; } diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.cc index a28d467df2e..c167744de01 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.cc @@ -65,13 +65,13 @@ /** * XXX Does some additional initialization on top of #nodeAddNode * Can be used with both custom and static nodes, - * if `idname == NULL` the static int type will be used instead. + * if `idname == nullptr` the static int type will be used instead. */ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx, float locy) { SpaceNode *snode = CTX_wm_space_node(C); Main *bmain = CTX_data_main(C); - bNode *node = NULL; + bNode *node = nullptr; node_deselect_all(snode); @@ -90,7 +90,7 @@ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx nodeSetSelected(node, true); ntreeUpdateTree(bmain, snode->edittree); - ED_node_set_active(bmain, snode->edittree, node, NULL); + ED_node_set_active(bmain, snode, snode->edittree, node, nullptr); snode_update(snode, node); @@ -114,7 +114,7 @@ static bool add_reroute_intersect_check(bNodeLink *link, { float coord_array[NODE_LINK_RESOL + 1][2]; - if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) { + if (node_link_bezier_points(nullptr, nullptr, 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_point( @@ -127,13 +127,13 @@ static bool add_reroute_intersect_check(bNodeLink *link, return false; } -typedef struct bNodeSocketLink { +struct bNodeSocketLink { struct bNodeSocketLink *next, *prev; struct bNodeSocket *sock; struct bNodeLink *link; float point[2]; -} bNodeSocketLink; +}; static bNodeSocketLink *add_reroute_insert_socket_link(ListBase *lb, bNodeSocket *sock, @@ -142,12 +142,12 @@ static bNodeSocketLink *add_reroute_insert_socket_link(ListBase *lb, { bNodeSocketLink *socklink, *prev; - socklink = MEM_callocN(sizeof(bNodeSocketLink), "socket link"); + socklink = (bNodeSocketLink *)MEM_callocN(sizeof(bNodeSocketLink), "socket link"); socklink->sock = sock; socklink->link = link; copy_v2_v2(socklink->point, point); - for (prev = lb->last; prev; prev = prev->prev) { + for (prev = (bNodeSocketLink *)lb->last; prev; prev = prev->prev) { if (prev->sock == sock) { break; } @@ -162,7 +162,7 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, { SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; - bNode *reroute_node = NULL; + bNode *reroute_node = nullptr; bNodeSocket *cursock = socklink->sock; float insert_point[2]; int num_links; @@ -184,12 +184,12 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, socklink->link->fromnode, socklink->link->fromsock, reroute_node, - reroute_node->inputs.first); + (bNodeSocket *)reroute_node->inputs.first); } else { nodeAddLink(ntree, reroute_node, - reroute_node->outputs.first, + (bNodeSocket *)reroute_node->outputs.first, socklink->link->tonode, socklink->link->tosock); } @@ -198,11 +198,11 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, /* insert the reroute node into the link */ if (in_out == SOCK_OUT) { socklink->link->fromnode = reroute_node; - socklink->link->fromsock = reroute_node->outputs.first; + socklink->link->fromsock = (bNodeSocket *)reroute_node->outputs.first; } else { socklink->link->tonode = reroute_node; - socklink->link->tosock = reroute_node->inputs.first; + socklink->link->tosock = (bNodeSocket *)reroute_node->inputs.first; } add_v2_v2(insert_point, socklink->point); @@ -259,7 +259,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op) BLI_listbase_clear(&output_links); BLI_listbase_clear(&input_links); - for (link = ntree->links.first; link; link = link->next) { + for (link = (bNodeLink *)ntree->links.first; link; link = link->next) { if (nodeLinkIsHidden(link)) { continue; } @@ -275,11 +275,11 @@ static int add_reroute_exec(bContext *C, wmOperator *op) /* Create reroute nodes for intersected links. * Only one reroute if links share the same input/output socket. */ - socklink = output_links.first; + socklink = (bNodeSocketLink *)output_links.first; while (socklink) { socklink = add_reroute_do_socket_section(C, socklink, SOCK_OUT); } - socklink = input_links.first; + socklink = (bNodeSocketLink *)input_links.first; while (socklink) { socklink = add_reroute_do_socket_section(C, socklink, SOCK_IN); } @@ -317,7 +317,7 @@ void NODE_OT_add_reroute(wmOperatorType *ot) /* properties */ PropertyRNA *prop; prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); /* internal */ RNA_def_int(ot->srna, "cursor", WM_CURSOR_CROSS, 0, INT_MAX, "Cursor", "", 0, INT_MAX); } @@ -337,10 +337,10 @@ static bNodeTree *node_add_group_get_and_poll_group_node_tree(Main *bmain, bNodeTree *node_group = (bNodeTree *)BKE_libblock_find_name(bmain, ID_NT, name); if (!node_group) { - return NULL; + return nullptr; } - const char *disabled_hint = NULL; + const char *disabled_hint = nullptr; if ((node_group->type != ntree->type) || !nodeGroupPoll(ntree, node_group, &disabled_hint)) { if (disabled_hint) { BKE_reportf(op->reports, @@ -358,7 +358,7 @@ static bNodeTree *node_add_group_get_and_poll_group_node_tree(Main *bmain, ntree->id.name + 2); } - return NULL; + return nullptr; } return node_group; @@ -450,7 +450,7 @@ static Object *node_add_object_get_and_poll_object_node_tree(Main *bmain, wmOper Object *object = (Object *)BKE_libblock_find_name(bmain, ID_OB, name); if (!object) { - return NULL; + return nullptr; } return object; @@ -470,7 +470,7 @@ static int node_add_object_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); bNode *object_node = node_add_node( - C, NULL, GEO_NODE_OBJECT_INFO, snode->runtime->cursor[0], snode->runtime->cursor[1]); + C, nullptr, GEO_NODE_OBJECT_INFO, snode->runtime->cursor[0], snode->runtime->cursor[1]); if (!object_node) { BKE_report(op->reports, RPT_WARNING, "Could not add node object"); return OPERATOR_CANCELLED; @@ -482,7 +482,7 @@ static int node_add_object_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - bNodeSocketValueObject *socket_data = sock->default_value; + bNodeSocketValueObject *socket_data = (bNodeSocketValueObject *)sock->default_value; socket_data->value = object; id_us_plus(&object->id); @@ -554,7 +554,7 @@ static Tex *node_add_texture_get_and_poll_texture_node_tree(Main *bmain, wmOpera Tex *texture = (Tex *)BKE_libblock_find_name(bmain, ID_TE, name); if (!texture) { - return NULL; + return nullptr; } return texture; @@ -574,7 +574,7 @@ static int node_add_texture_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); bNode *texture_node = node_add_node(C, - NULL, + nullptr, GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE, snode->runtime->cursor[0], snode->runtime->cursor[1]); @@ -591,6 +591,7 @@ static int node_add_texture_exec(bContext *C, wmOperator *op) snode_notify(C, snode); snode_dag_update(C, snode); + DEG_relations_tag_update(bmain); ED_node_tag_update_nodetree(bmain, ntree, texture_node); @@ -655,7 +656,7 @@ static Collection *node_add_collection_get_and_poll_collection_node_tree(Main *b Collection *collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name); if (!collection) { - return NULL; + return nullptr; } return collection; @@ -675,7 +676,7 @@ static int node_add_collection_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); bNode *collection_node = node_add_node( - C, NULL, GEO_NODE_COLLECTION_INFO, snode->runtime->cursor[0], snode->runtime->cursor[1]); + C, nullptr, GEO_NODE_COLLECTION_INFO, snode->runtime->cursor[0], snode->runtime->cursor[1]); if (!collection_node) { BKE_report(op->reports, RPT_WARNING, "Could not add node collection"); return OPERATOR_CANCELLED; @@ -687,7 +688,7 @@ static int node_add_collection_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - bNodeSocketValueCollection *socket_data = sock->default_value; + bNodeSocketValueCollection *socket_data = (bNodeSocketValueCollection *)sock->default_value; socket_data->value = collection; id_us_plus(&collection->id); @@ -696,6 +697,7 @@ static int node_add_collection_exec(bContext *C, wmOperator *op) snode_notify(C, snode); snode_dag_update(C, snode); + DEG_relations_tag_update(bmain); ED_node_tag_update_nodetree(bmain, ntree, collection_node); @@ -788,7 +790,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->runtime->cursor[0], snode->runtime->cursor[1]); + node = node_add_node(C, nullptr, type, snode->runtime->cursor[0], snode->runtime->cursor[1]); if (!node) { BKE_report(op->reports, RPT_WARNING, "Could not add an image node"); @@ -801,12 +803,13 @@ static int node_add_file_exec(bContext *C, wmOperator *op) * to get proper image source. */ if (RNA_struct_property_is_set(op->ptr, "filepath")) { - BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_RELOAD); + BKE_image_signal(bmain, ima, nullptr, IMA_SIGNAL_RELOAD); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); } snode_notify(C, snode); snode_dag_update(C, snode); + DEG_relations_tag_update(bmain); return OPERATOR_FINISHED; } @@ -876,7 +879,7 @@ static int node_add_mask_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); bNode *node; - ID *mask = NULL; + ID *mask = nullptr; /* check input variables */ char name[MAX_ID_NAME - 2]; @@ -890,7 +893,7 @@ 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->runtime->cursor[0], snode->runtime->cursor[1]); + C, nullptr, 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"); @@ -902,6 +905,7 @@ static int node_add_mask_exec(bContext *C, wmOperator *op) snode_notify(C, snode); snode_dag_update(C, snode); + DEG_relations_tag_update(bmain); return OPERATOR_FINISHED; } @@ -976,7 +980,7 @@ static int new_node_tree_exec(bContext *C, wmOperator *op) id_us_min(&ntree->id); RNA_id_pointer_create(&ntree->id, &idptr); - RNA_property_pointer_set(&ptr, prop, idptr, NULL); + RNA_property_pointer_set(&ptr, prop, idptr, nullptr); RNA_property_update(C, &ptr, prop); } else if (snode) { @@ -993,7 +997,7 @@ static const EnumPropertyItem *new_node_tree_type_itemf(bContext *UNUSED(C), PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_node_tree_type_itemf(NULL, NULL, r_free); + return rna_node_tree_type_itemf(nullptr, nullptr, r_free); } void NODE_OT_new_node_tree(wmOperatorType *ot) diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c deleted file mode 100644 index 336b0c46a81..00000000000 --- a/source/blender/editors/space_node/node_buttons.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup spnode - */ - -#include "MEM_guardedalloc.h" - -#include "DNA_node_types.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" - -#include "BLT_translation.h" - -#include "BKE_context.h" -#include "BKE_global.h" -#include "BKE_node.h" -#include "BKE_screen.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "RNA_access.h" - -#include "ED_screen.h" - -#include "UI_resources.h" - -#include "node_intern.h" /* own include */ - -/* ******************* node space & buttons ************** */ - -#if 0 -/* poll for active nodetree */ -static bool active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - return (snode && snode->nodetree); -} -#endif - -static bool node_sockets_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - return (snode && snode->nodetree && G.debug_value == 777); -} - -static void node_sockets_panel(const bContext *C, Panel *panel) -{ - SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */ - bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */ - bNode *node = nodeGetActive(ntree); - if (node == NULL) { - return; - } - - LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { - char name[UI_MAX_NAME_STR]; - BLI_snprintf(name, sizeof(name), "%s:", socket->name); - - uiLayout *split = uiLayoutSplit(panel->layout, 0.35f, false); - uiItemL(split, name, ICON_NONE); - uiTemplateNodeLink(split, (bContext *)C, ntree, node, socket); - } -} - -static bool node_tree_interface_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - return (snode && snode->edittree && - (snode->edittree->inputs.first || snode->edittree->outputs.first)); -} - -static bNodeSocket *node_tree_find_active_socket(bNodeTree *ntree, const eNodeSocketInOut in_out) -{ - ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs; - LISTBASE_FOREACH (bNodeSocket *, socket, sockets) { - if (socket->flag & SELECT) { - return socket; - } - } - return NULL; -} - -static void draw_socket_list(const bContext *C, - uiLayout *layout, - bNodeTree *ntree, - const eNodeSocketInOut in_out) -{ - PointerRNA tree_ptr; - RNA_id_pointer_create((ID *)ntree, &tree_ptr); - - uiLayout *split = uiLayoutRow(layout, false); - uiLayout *list_col = uiLayoutColumn(split, true); - uiTemplateList(list_col, - (bContext *)C, - "NODE_UL_interface_sockets", - (in_out == SOCK_IN) ? "inputs" : "outputs", - &tree_ptr, - (in_out == SOCK_IN) ? "inputs" : "outputs", - &tree_ptr, - (in_out == SOCK_IN) ? "active_input" : "active_output", - NULL, - 0, - 0, - 0, - 0, - false, - false); - PointerRNA opptr; - uiLayout *ops_col = uiLayoutColumn(split, false); - uiLayout *add_remove_col = uiLayoutColumn(ops_col, true); - wmOperatorType *ot = WM_operatortype_find("NODE_OT_tree_socket_add", false); - uiItemFullO_ptr(add_remove_col, ot, "", ICON_ADD, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); - RNA_enum_set(&opptr, "in_out", in_out); - ot = WM_operatortype_find("NODE_OT_tree_socket_remove", false); - uiItemFullO_ptr(add_remove_col, ot, "", ICON_REMOVE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); - RNA_enum_set(&opptr, "in_out", in_out); - - uiItemS(ops_col); - - uiLayout *up_down_col = uiLayoutColumn(ops_col, true); - ot = WM_operatortype_find("NODE_OT_tree_socket_move", false); - uiItemFullO_ptr(up_down_col, ot, "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); - RNA_enum_set(&opptr, "direction", 1); - RNA_enum_set(&opptr, "in_out", in_out); - uiItemFullO_ptr(up_down_col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); - RNA_enum_set(&opptr, "direction", 2); - RNA_enum_set(&opptr, "in_out", in_out); - - bNodeSocket *socket = node_tree_find_active_socket(ntree, in_out); - if (socket != NULL) { - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - PointerRNA socket_ptr; - RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, socket, &socket_ptr); - uiItemR(layout, &socket_ptr, "name", 0, NULL, ICON_NONE); - - /* Display descriptions only for Geometry Nodes, since it's only used in the modifier panel. */ - if (ntree->type == NTREE_GEOMETRY) { - uiItemR(layout, &socket_ptr, "description", 0, NULL, ICON_NONE); - } - - if (socket->typeinfo->interface_draw) { - socket->typeinfo->interface_draw((bContext *)C, layout, &socket_ptr); - } - } -} - -static void node_tree_interface_inputs_panel(const bContext *C, Panel *panel) -{ - SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */ - bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */ - - draw_socket_list(C, panel->layout, ntree, SOCK_IN); -} - -static void node_tree_interface_outputs_panel(const bContext *C, Panel *panel) -{ - SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */ - bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */ - - draw_socket_list(C, panel->layout, ntree, SOCK_OUT); -} - -/* ******************* node buttons registration ************** */ - -void node_buttons_register(ARegionType *art) -{ - { - PanelType *pt = MEM_callocN(sizeof(PanelType), __func__); - strcpy(pt->idname, "NODE_PT_sockets"); - strcpy(pt->category, N_("Node")); - strcpy(pt->label, N_("Sockets")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = node_sockets_panel; - pt->poll = node_sockets_poll; - pt->flag |= PANEL_TYPE_DEFAULT_CLOSED; - BLI_addtail(&art->paneltypes, pt); - } - - { - PanelType *pt = MEM_callocN(sizeof(PanelType), __func__); - strcpy(pt->idname, "NODE_PT_node_tree_interface_inputs"); - strcpy(pt->category, N_("Group")); - strcpy(pt->label, N_("Inputs")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = node_tree_interface_inputs_panel; - pt->poll = node_tree_interface_poll; - BLI_addtail(&art->paneltypes, pt); - } - { - PanelType *pt = MEM_callocN(sizeof(PanelType), __func__); - strcpy(pt->idname, "NODE_PT_node_tree_interface_outputs"); - strcpy(pt->category, N_("Group")); - strcpy(pt->label, N_("Outputs")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = node_tree_interface_outputs_panel; - pt->poll = node_tree_interface_poll; - BLI_addtail(&art->paneltypes, pt); - } -} diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index fd9c0f42f2d..7eca5c0c933 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -45,10 +45,10 @@ #include "BLT_translation.h" #include "BKE_context.h" +#include "BKE_idtype.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_node.h" -#include "BKE_node_ui_storage.hh" #include "BKE_object.h" #include "DEG_depsgraph.h" @@ -76,15 +76,21 @@ #include "RNA_access.h" +#include "NOD_geometry_nodes_eval_log.hh" + #include "node_intern.h" /* own include */ #ifdef WITH_COMPOSITOR # include "COM_compositor.h" #endif +using blender::Map; using blender::Set; using blender::Span; using blender::Vector; +using blender::fn::CPPType; +using blender::fn::GPointer; +namespace geo_log = blender::nodes::geometry_nodes_eval_log; extern "C" { /* XXX interface.h */ @@ -821,6 +827,149 @@ void node_socket_color_get( } } +struct SocketTooltipData { + bNodeTree *ntree; + bNode *node; + bNodeSocket *socket; +}; + +static void create_inspection_string_for_generic_value(const geo_log::GenericValueLog &value_log, + std::stringstream &ss) +{ + auto id_to_inspection_string = [&](ID *id) { + ss << (id ? id->name + 2 : TIP_("None")) << " (" << BKE_idtype_idcode_to_name(GS(id->name)) + << ")"; + }; + + const GPointer value = value_log.value(); + if (value.is_type<int>()) { + ss << *value.get<int>() << TIP_(" (Integer)"); + } + else if (value.is_type<float>()) { + ss << *value.get<float>() << TIP_(" (Float)"); + } + else if (value.is_type<blender::float3>()) { + ss << *value.get<blender::float3>() << TIP_(" (Vector)"); + } + else if (value.is_type<bool>()) { + ss << (*value.get<bool>() ? TIP_("True") : TIP_("False")) << TIP_(" (Boolean)"); + } + else if (value.is_type<std::string>()) { + ss << *value.get<std::string>() << TIP_(" (String)"); + } + else if (value.is_type<Object *>()) { + id_to_inspection_string((ID *)*value.get<Object *>()); + } + else if (value.is_type<Material *>()) { + id_to_inspection_string((ID *)*value.get<Material *>()); + } + else if (value.is_type<Tex *>()) { + id_to_inspection_string((ID *)*value.get<Tex *>()); + } + else if (value.is_type<Collection *>()) { + id_to_inspection_string((ID *)*value.get<Collection *>()); + } +} + +static void create_inspection_string_for_geometry(const geo_log::GeometryValueLog &value_log, + std::stringstream &ss) +{ + Span<GeometryComponentType> component_types = value_log.component_types(); + if (component_types.is_empty()) { + ss << TIP_("Empty Geometry"); + return; + } + + auto to_string = [](int value) { + char str[16]; + BLI_str_format_int_grouped(str, value); + return std::string(str); + }; + + ss << TIP_("Geometry:\n"); + for (GeometryComponentType type : component_types) { + const char *line_end = (type == component_types.last()) ? "" : ".\n"; + switch (type) { + case GEO_COMPONENT_TYPE_MESH: { + const geo_log::GeometryValueLog::MeshInfo &mesh_info = *value_log.mesh_info; + char line[256]; + BLI_snprintf(line, + sizeof(line), + TIP_("\u2022 Mesh: %s vertices, %s edges, %s faces"), + to_string(mesh_info.tot_verts).c_str(), + to_string(mesh_info.tot_edges).c_str(), + to_string(mesh_info.tot_faces).c_str()); + ss << line << line_end; + break; + } + case GEO_COMPONENT_TYPE_POINT_CLOUD: { + const geo_log::GeometryValueLog::PointCloudInfo &pointcloud_info = + *value_log.pointcloud_info; + char line[256]; + BLI_snprintf(line, + sizeof(line), + TIP_("\u2022 Point Cloud: %s points"), + to_string(pointcloud_info.tot_points).c_str()); + ss << line << line_end; + break; + } + case GEO_COMPONENT_TYPE_CURVE: { + const geo_log::GeometryValueLog::CurveInfo &curve_info = *value_log.curve_info; + char line[256]; + BLI_snprintf(line, + sizeof(line), + TIP_("\u2022 Curve: %s splines"), + to_string(curve_info.tot_splines).c_str()); + ss << line << line_end; + break; + } + case GEO_COMPONENT_TYPE_INSTANCES: { + const geo_log::GeometryValueLog::InstancesInfo &instances_info = *value_log.instances_info; + char line[256]; + BLI_snprintf(line, + sizeof(line), + TIP_("\u2022 Instances: %s"), + to_string(instances_info.tot_instances).c_str()); + ss << line << line_end; + break; + } + case GEO_COMPONENT_TYPE_VOLUME: { + ss << TIP_("\u2022 Volume") << line_end; + break; + } + } + } +} + +static std::optional<std::string> create_socket_inspection_string(bContext *C, + bNodeTree &UNUSED(ntree), + bNode &node, + bNodeSocket &socket) +{ + SpaceNode *snode = CTX_wm_space_node(C); + const geo_log::SocketLog *socket_log = geo_log::ModifierLog::find_socket_by_node_editor_context( + *snode, node, socket); + if (socket_log == nullptr) { + return {}; + } + const geo_log::ValueLog *value_log = socket_log->value(); + if (value_log == nullptr) { + return {}; + } + + std::stringstream ss; + if (const geo_log::GenericValueLog *generic_value_log = + dynamic_cast<const geo_log::GenericValueLog *>(value_log)) { + create_inspection_string_for_generic_value(*generic_value_log, ss); + } + else if (const geo_log::GeometryValueLog *geo_value_log = + dynamic_cast<const geo_log::GeometryValueLog *>(value_log)) { + create_inspection_string_for_geometry(*geo_value_log, ss); + } + + return ss.str(); +} + static void node_socket_draw_nested(const bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, @@ -850,6 +999,55 @@ static void node_socket_draw_nested(const bContext *C, shape_id, size_id, outline_col_id); + + if (ntree->type != NTREE_GEOMETRY) { + /* Only geometry nodes has socket value tooltips currently. */ + return; + } + + bNode *node = (bNode *)node_ptr->data; + uiBlock *block = node->block; + + /* Ideally sockets themselves should be buttons, but they aren't currently. So add an invisible + * button on top of them for the tooltip. */ + const eUIEmbossType old_emboss = UI_block_emboss_get(block); + UI_block_emboss_set(block, UI_EMBOSS_NONE); + uiBut *but = uiDefIconBut(block, + UI_BTYPE_BUT, + 0, + ICON_NONE, + sock->locx - size / 2, + sock->locy - size / 2, + size, + size, + nullptr, + 0, + 0, + 0, + 0, + nullptr); + + SocketTooltipData *data = (SocketTooltipData *)MEM_mallocN(sizeof(SocketTooltipData), __func__); + data->ntree = ntree; + data->node = (bNode *)node_ptr->data; + data->socket = sock; + + UI_but_func_tooltip_set( + but, + [](bContext *C, void *argN, const char *UNUSED(tip)) { + SocketTooltipData *data = (SocketTooltipData *)argN; + std::optional<std::string> str = create_socket_inspection_string( + C, *data->ntree, *data->node, *data->socket); + if (str.has_value()) { + return BLI_strdup(str->c_str()); + } + return BLI_strdup(TIP_("The socket value has not been computed yet")); + }, + data, + MEM_freeN); + /* Disable the button so that clicks on it are ignored the the link operator still works. */ + UI_but_flag_enable(but, UI_BUT_DISABLED); + UI_block_emboss_set(block, old_emboss); } /** @@ -1184,14 +1382,14 @@ void node_draw_sockets(const View2D *v2d, } } -static int node_error_type_to_icon(const NodeWarningType type) +static int node_error_type_to_icon(const geo_log::NodeWarningType type) { switch (type) { - case NodeWarningType::Error: + case geo_log::NodeWarningType::Error: return ICON_ERROR; - case NodeWarningType::Warning: + case geo_log::NodeWarningType::Warning: return ICON_ERROR; - case NodeWarningType::Info: + case geo_log::NodeWarningType::Info: return ICON_INFO; } @@ -1199,14 +1397,14 @@ static int node_error_type_to_icon(const NodeWarningType type) return ICON_ERROR; } -static uint8_t node_error_type_priority(const NodeWarningType type) +static uint8_t node_error_type_priority(const geo_log::NodeWarningType type) { switch (type) { - case NodeWarningType::Error: + case geo_log::NodeWarningType::Error: return 3; - case NodeWarningType::Warning: + case geo_log::NodeWarningType::Warning: return 2; - case NodeWarningType::Info: + case geo_log::NodeWarningType::Info: return 1; } @@ -1214,11 +1412,11 @@ static uint8_t node_error_type_priority(const NodeWarningType type) return 0; } -static NodeWarningType node_error_highest_priority(Span<NodeWarning> warnings) +static geo_log::NodeWarningType node_error_highest_priority(Span<geo_log::NodeWarning> warnings) { uint8_t highest_priority = 0; - NodeWarningType highest_priority_type = NodeWarningType::Info; - for (const NodeWarning &warning : warnings) { + geo_log::NodeWarningType highest_priority_type = geo_log::NodeWarningType::Info; + for (const geo_log::NodeWarning &warning : warnings) { const uint8_t priority = node_error_type_priority(warning.type); if (priority > highest_priority) { highest_priority = priority; @@ -1228,15 +1426,17 @@ static NodeWarningType node_error_highest_priority(Span<NodeWarning> warnings) return highest_priority_type; } +struct NodeErrorsTooltipData { + Span<geo_log::NodeWarning> warnings; +}; + static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char *UNUSED(tip)) { - const NodeUIStorage **storage_pointer_alloc = static_cast<const NodeUIStorage **>(argN); - const NodeUIStorage *node_ui_storage = *storage_pointer_alloc; - Span<NodeWarning> warnings = node_ui_storage->warnings; + NodeErrorsTooltipData &data = *(NodeErrorsTooltipData *)argN; std::string complete_string; - for (const NodeWarning &warning : warnings.drop_back(1)) { + for (const geo_log::NodeWarning &warning : data.warnings.drop_back(1)) { complete_string += warning.message; /* Adding the period is not ideal for multi-line messages, but it is consistent * with other tooltip implementations in Blender, so it is added here. */ @@ -1245,7 +1445,7 @@ static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char } /* Let the tooltip system automatically add the last period. */ - complete_string += warnings.last().message; + complete_string += data.warnings.last().message; return BLI_strdupn(complete_string.c_str(), complete_string.size()); } @@ -1253,20 +1453,26 @@ static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char #define NODE_HEADER_ICON_SIZE (0.8f * U.widget_unit) static void node_add_error_message_button( - const bContext *C, bNodeTree &ntree, bNode &node, const rctf &rect, float &icon_offset) + const bContext *C, bNodeTree &UNUSED(ntree), bNode &node, const rctf &rect, float &icon_offset) { - const NodeUIStorage *node_ui_storage = BKE_node_tree_ui_storage_get_from_context(C, ntree, node); - if (node_ui_storage == nullptr || node_ui_storage->warnings.is_empty()) { + SpaceNode *snode = CTX_wm_space_node(C); + const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(*snode, + node); + if (node_log == nullptr) { + return; + } + + Span<geo_log::NodeWarning> warnings = node_log->warnings(); + + if (warnings.is_empty()) { return; } - /* The UI API forces us to allocate memory for each error button, because the - * ownership of #UI_but_func_tooltip_set's argument is transferred to the button. */ - const NodeUIStorage **storage_pointer_alloc = (const NodeUIStorage **)MEM_mallocN( - sizeof(NodeUIStorage *), __func__); - *storage_pointer_alloc = node_ui_storage; + NodeErrorsTooltipData *tooltip_data = (NodeErrorsTooltipData *)MEM_mallocN( + sizeof(NodeErrorsTooltipData), __func__); + tooltip_data->warnings = warnings; - const NodeWarningType display_type = node_error_highest_priority(node_ui_storage->warnings); + const geo_log::NodeWarningType display_type = node_error_highest_priority(warnings); icon_offset -= NODE_HEADER_ICON_SIZE; UI_block_emboss_set(node.block, UI_EMBOSS_NONE); @@ -1284,7 +1490,7 @@ static void node_add_error_message_button( 0, 0, nullptr); - UI_but_func_tooltip_set(but, node_errors_tooltip_fn, storage_pointer_alloc); + UI_but_func_tooltip_set(but, node_errors_tooltip_fn, tooltip_data, MEM_freeN); UI_block_emboss_set(node.block, UI_EMBOSS); } @@ -1404,28 +1610,6 @@ static void node_draw_basis(const bContext *C, ""); UI_block_emboss_set(node->block, UI_EMBOSS); } - if (ntree->type == NTREE_GEOMETRY) { - /* Active preview toggle. */ - iconofs -= iconbutw; - UI_block_emboss_set(node->block, UI_EMBOSS_NONE); - int icon = (node->flag & NODE_ACTIVE_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON; - uiBut *but = uiDefIconBut(node->block, - UI_BTYPE_BUT_TOGGLE, - 0, - icon, - iconofs, - rct->ymax - NODE_DY, - iconbutw, - UI_UNIT_Y, - nullptr, - 0, - 0, - 0, - 0, - "Show this node's geometry output in the spreadsheet"); - UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_active_preview_toggle"); - UI_block_emboss_set(node->block, UI_EMBOSS); - } node_add_error_message_button(C, *ntree, *node, *rct, iconofs); @@ -1765,28 +1949,29 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node) } } -static void count_mutli_input_socket_links(bNodeTree *ntree, SpaceNode *snode) +static void count_multi_input_socket_links(bNodeTree *ntree, SpaceNode *snode) { + Map<bNodeSocket *, int> counts; + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { + if (link->tosock->flag & SOCK_MULTI_INPUT) { + int &count = counts.lookup_or_add(link->tosock, 0); + count++; + } + } + /* 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 && (link->tosock->flag & SOCK_MULTI_INPUT)) { + int &count = counts.lookup_or_add(link->tosock, 0); + count++; + } + } + } LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - LISTBASE_FOREACH (struct bNodeSocket *, socket, &node->inputs) { + LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { if (socket->flag & SOCK_MULTI_INPUT) { - Set<bNodeSocket *> visited_from_sockets; - socket->total_inputs = 0; - LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { - if (link->tosock == socket) { - visited_from_sockets.add(link->fromsock); - } - } - /* 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) { - visited_from_sockets.add(link->fromsock); - } - } - } - socket->total_inputs = visited_from_sockets.size(); + socket->total_inputs = counts.lookup_default(socket, 0); } } } @@ -1798,7 +1983,7 @@ void node_update_nodetree(const bContext *C, bNodeTree *ntree) SpaceNode *snode = CTX_wm_space_node(C); ntreeTagUsedSockets(ntree); - count_mutli_input_socket_links(ntree, snode); + count_multi_input_socket_links(ntree, snode); /* Update nodes front to back, so children sizes get updated before parents. */ LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree->nodes) { diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.cc index 50fa8b28468..5dd935bdd76 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.cc @@ -54,6 +54,7 @@ #include "ED_render.h" #include "ED_screen.h" #include "ED_select_utils.h" +#include "ED_spreadsheet.h" #include "RNA_access.h" #include "RNA_define.h" @@ -83,7 +84,7 @@ enum { COM_RECALC_VIEWER = 2, }; -typedef struct CompoJob { +struct CompoJob { /* Input parameters. */ Main *bmain; Scene *scene; @@ -97,7 +98,7 @@ typedef struct CompoJob { const short *stop; short *do_update; float *progress; -} CompoJob; +}; float node_socket_calculate_height(const bNodeSocket *socket) { @@ -150,7 +151,7 @@ static int compo_get_recalc_flags(const bContext *C) LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { if (area->spacetype == SPACE_IMAGE) { - SpaceImage *sima = area->spacedata.first; + SpaceImage *sima = (SpaceImage *)area->spacedata.first; if (sima->image) { if (sima->image->type == IMA_TYPE_R_RESULT) { recalc_flags |= COM_RECALC_COMPOSITE; @@ -161,7 +162,7 @@ static int compo_get_recalc_flags(const bContext *C) } } else if (area->spacetype == SPACE_NODE) { - SpaceNode *snode = area->spacedata.first; + SpaceNode *snode = (SpaceNode *)area->spacedata.first; if (snode->flag & SNODE_BACKDRAW) { recalc_flags |= COM_RECALC_VIEWER; } @@ -175,9 +176,9 @@ static int compo_get_recalc_flags(const bContext *C) /* called by compo, only to check job 'stop' value */ static int compo_breakjob(void *cjv) { - CompoJob *cj = cjv; + CompoJob *cj = (CompoJob *)cjv; - /* without G.is_break 'ESC' wont quit - which annoys users */ + /* without G.is_break 'ESC' won't quit - which annoys users */ return (*(cj->stop) #ifdef USE_ESC_COMPO || G.is_break @@ -188,7 +189,7 @@ static int compo_breakjob(void *cjv) /* called by compo, wmJob sends notifier */ static void compo_statsdrawjob(void *cjv, const char *UNUSED(str)) { - CompoJob *cj = cjv; + CompoJob *cj = (CompoJob *)cjv; *(cj->do_update) = true; } @@ -196,19 +197,19 @@ static void compo_statsdrawjob(void *cjv, const char *UNUSED(str)) /* called by compo, wmJob sends notifier */ static void compo_redrawjob(void *cjv) { - CompoJob *cj = cjv; + CompoJob *cj = (CompoJob *)cjv; *(cj->do_update) = true; } static void compo_freejob(void *cjv) { - CompoJob *cj = cjv; + CompoJob *cj = (CompoJob *)cjv; if (cj->localtree) { ntreeLocalMerge(cj->bmain, cj->localtree, cj->ntree); } - if (cj->compositor_depsgraph != NULL) { + if (cj->compositor_depsgraph != nullptr) { DEG_graph_free(cj->compositor_depsgraph); } MEM_freeN(cj); @@ -218,7 +219,7 @@ static void compo_freejob(void *cjv) * sliding buttons doesn't frustrate */ static void compo_initjob(void *cjv) { - CompoJob *cj = cjv; + CompoJob *cj = (CompoJob *)cjv; Main *bmain = cj->bmain; Scene *scene = cj->scene; ViewLayer *view_layer = cj->view_layer; @@ -243,12 +244,12 @@ static void compo_initjob(void *cjv) /* called before redraw notifiers, it moves finished previews over */ static void compo_updatejob(void *UNUSED(cjv)) { - WM_main_add_notifier(NC_SCENE | ND_COMPO_RESULT, NULL); + WM_main_add_notifier(NC_SCENE | ND_COMPO_RESULT, nullptr); } static void compo_progressjob(void *cjv, float progress) { - CompoJob *cj = cjv; + CompoJob *cj = (CompoJob *)cjv; *(cj->progress) = progress; } @@ -261,7 +262,7 @@ static void compo_startjob(void *cjv, short *do_update, float *progress) { - CompoJob *cj = cjv; + CompoJob *cj = (CompoJob *)cjv; bNodeTree *ntree = cj->localtree; Scene *scene = cj->scene; @@ -311,9 +312,9 @@ static void compo_startjob(void *cjv, } } - ntree->test_break = NULL; - ntree->stats_draw = NULL; - ntree->progress = NULL; + ntree->test_break = nullptr; + ntree->stats_draw = nullptr; + ntree->progress = nullptr; } /** @@ -347,7 +348,7 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene "Compositing", WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS, WM_JOB_TYPE_COMPOSITE); - CompoJob *cj = MEM_callocN(sizeof(CompoJob), "compo job"); + CompoJob *cj = (CompoJob *)MEM_callocN(sizeof(CompoJob), "compo job"); /* customdata for preview thread */ cj->bmain = bmain; @@ -359,7 +360,7 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene /* setup job */ WM_jobs_customdata_set(wm_job, cj, compo_freejob); WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_COMPO_RESULT, NC_SCENE | ND_COMPO_RESULT); - WM_jobs_callbacks(wm_job, compo_startjob, compo_initjob, compo_updatejob, NULL); + WM_jobs_callbacks(wm_job, compo_startjob, compo_initjob, compo_updatejob, nullptr); WM_jobs_start(CTX_wm_manager(C), wm_job); } @@ -412,7 +413,7 @@ void snode_notify(bContext *C, SpaceNode *snode) { ID *id = snode->id; - WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_NODE | NA_EDITED, nullptr); if (ED_node_is_shader(snode)) { if (GS(id->name) == ID_MA) { @@ -490,15 +491,15 @@ void ED_node_shader_default(const bContext *C, ID *id) } else if (ELEM(GS(id->name), ID_WO, ID_LA)) { /* Emission */ - bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname); + bNodeTree *ntree = ntreeAddTree(nullptr, "Shader Nodetree", ntreeType_Shader->idname); bNode *shader, *output; if (GS(id->name) == ID_WO) { World *world = (World *)id; world->nodetree = ntree; - shader = nodeAddStaticNode(NULL, ntree, SH_NODE_BACKGROUND); - output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_WORLD); + shader = nodeAddStaticNode(nullptr, ntree, SH_NODE_BACKGROUND); + output = nodeAddStaticNode(nullptr, ntree, SH_NODE_OUTPUT_WORLD); nodeAddLink(ntree, shader, nodeFindSocket(shader, SOCK_OUT, "Background"), @@ -512,8 +513,8 @@ void ED_node_shader_default(const bContext *C, ID *id) Light *light = (Light *)id; light->nodetree = ntree; - shader = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION); - output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_LIGHT); + shader = nodeAddStaticNode(nullptr, ntree, SH_NODE_EMISSION); + output = nodeAddStaticNode(nullptr, ntree, SH_NODE_OUTPUT_LIGHT); nodeAddLink(ntree, shader, nodeFindSocket(shader, SOCK_OUT, "Emission"), @@ -546,7 +547,7 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce) return; } - sce->nodetree = ntreeAddTree(NULL, "Compositing Nodetree", ntreeType_Composite->idname); + sce->nodetree = ntreeAddTree(nullptr, "Compositing Nodetree", ntreeType_Composite->idname); sce->nodetree->chunksize = 256; sce->nodetree->edit_quality = NTREE_QUALITY_HIGH; @@ -562,8 +563,8 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce) nodeSetActive(sce->nodetree, in); /* links from color to color */ - bNodeSocket *fromsock = in->outputs.first; - bNodeSocket *tosock = out->inputs.first; + bNodeSocket *fromsock = (bNodeSocket *)in->outputs.first; + bNodeSocket *tosock = (bNodeSocket *)out->inputs.first; nodeAddLink(sce->nodetree, in, fromsock, out, tosock); ntreeUpdateTree(CTX_data_main(C), sce->nodetree); @@ -581,7 +582,7 @@ void ED_node_texture_default(const bContext *C, Tex *tex) return; } - tex->nodetree = ntreeAddTree(NULL, "Texture Nodetree", ntreeType_Texture->idname); + tex->nodetree = ntreeAddTree(nullptr, "Texture Nodetree", ntreeType_Texture->idname); bNode *out = nodeAddStaticNode(C, tex->nodetree, TEX_NODE_OUTPUT); out->locx = 300.0f; @@ -592,8 +593,8 @@ void ED_node_texture_default(const bContext *C, Tex *tex) in->locy = 300.0f; nodeSetActive(tex->nodetree, in); - bNodeSocket *fromsock = in->outputs.first; - bNodeSocket *tosock = out->inputs.first; + bNodeSocket *fromsock = (bNodeSocket *)in->outputs.first; + bNodeSocket *tosock = (bNodeSocket *)out->inputs.first; nodeAddLink(tex->nodetree, in, fromsock, out, tosock); ntreeUpdateTree(CTX_data_main(C), tex->nodetree); @@ -618,24 +619,24 @@ void snode_set_context(const bContext *C) if (snode->nodetree && !STREQ(snode->nodetree->idname, snode->tree_idname)) { /* current tree does not match selected type, clear tree path */ - ntree = NULL; - id = NULL; - from = NULL; + ntree = nullptr; + id = nullptr; + from = nullptr; } - if (!(snode->flag & SNODE_PIN) || ntree == NULL) { + if (!(snode->flag & SNODE_PIN) || ntree == nullptr) { if (treetype->get_from_context) { /* reset and update from context */ - ntree = NULL; - id = NULL; - from = NULL; + ntree = nullptr; + id = nullptr; + from = nullptr; treetype->get_from_context(C, treetype, &ntree, &id, &from); } } if (snode->nodetree != ntree || snode->id != id || snode->from != from || - (snode->treepath.last == NULL && ntree)) { + (snode->treepath.last == nullptr && ntree)) { ED_node_tree_start(snode, ntree, id, from); } } @@ -648,7 +649,7 @@ void snode_update(SpaceNode *snode, bNode *node) */ /* update all edited group nodes */ - bNodeTreePath *path = snode->treepath.last; + bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last; if (path) { bNodeTree *ngroup = path->nodetree; for (path = path->prev; path; path = path->prev) { @@ -662,7 +663,8 @@ void snode_update(SpaceNode *snode, bNode *node) } } -void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_active_texture_changed) +void ED_node_set_active( + Main *bmain, SpaceNode *snode, bNodeTree *ntree, bNode *node, bool *r_active_texture_changed) { const bool was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE) != 0; if (r_active_texture_changed) { @@ -685,7 +687,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti node->flag |= NODE_DO_OUTPUT; if (!was_output) { - do_update = 1; + do_update = true; } } @@ -734,7 +736,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti *r_active_texture_changed = true; } ED_node_tag_update_nodetree(bmain, ntree, node); - WM_main_add_notifier(NC_IMAGE, NULL); + WM_main_add_notifier(NC_IMAGE, nullptr); } WM_main_add_notifier(NC_MATERIAL | ND_NODES, node->id); @@ -753,7 +755,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti ED_node_tag_update_nodetree(bmain, ntree, node); } - /* addnode() doesn't link this yet... */ + /* Adding a node doesn't link this yet. */ node->id = (ID *)BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); } else if (node->type == CMP_NODE_COMPOSITE) { @@ -782,6 +784,19 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti } #endif } + else if (ntree->type == NTREE_GEOMETRY) { + if (node->type == GEO_NODE_VIEWER) { + if ((node->flag & NODE_DO_OUTPUT) == 0) { + LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) { + if (node_iter->type == GEO_NODE_VIEWER) { + node_iter->flag &= ~NODE_DO_OUTPUT; + } + } + node->flag |= NODE_DO_OUTPUT; + ED_spreadsheet_context_paths_set_geometry_node(bmain, snode, node); + } + } + } } } @@ -806,7 +821,7 @@ static bool edit_node_poll(bContext *C) static void edit_node_properties(wmOperatorType *ot) { /* XXX could node be a context pointer? */ - RNA_def_string(ot->srna, "node", NULL, MAX_NAME, "Node", ""); + RNA_def_string(ot->srna, "node", nullptr, MAX_NAME, "Node", ""); RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET); RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Side", ""); } @@ -838,7 +853,7 @@ static void edit_node_properties_get( wmOperator *op, bNodeTree *ntree, bNode **r_node, bNodeSocket **r_sock, int *r_in_out) { bNode *node; - bNodeSocket *sock = NULL; + bNodeSocket *sock = nullptr; char nodename[MAX_NAME]; int sockindex; int in_out; @@ -876,29 +891,30 @@ static void edit_node_properties_get( static bNode *visible_node(SpaceNode *snode, const rctf *rct) { LISTBASE_FOREACH_BACKWARD (bNode *, node, &snode->edittree->nodes) { - if (BLI_rctf_isect(&node->totr, rct, NULL)) { + if (BLI_rctf_isect(&node->totr, rct, nullptr)) { return node; } } - return NULL; + return nullptr; } /* ********************** size widget operator ******************** */ -typedef struct NodeSizeWidget { +struct NodeSizeWidget { float mxstart, mystart; float oldlocx, oldlocy; float oldoffsetx, oldoffsety; float oldwidth, oldheight; int directions; -} NodeSizeWidget; +}; static void node_resize_init( bContext *C, wmOperator *op, const wmEvent *UNUSED(event), bNode *node, int dir) { SpaceNode *snode = CTX_wm_space_node(C); - NodeSizeWidget *nsw = MEM_callocN(sizeof(NodeSizeWidget), "size widget op data"); + NodeSizeWidget *nsw = (NodeSizeWidget *)MEM_callocN(sizeof(NodeSizeWidget), + "size widget op data"); op->customdata = nsw; nsw->mxstart = snode->runtime->cursor[0] * UI_DPI_FAC; @@ -926,7 +942,7 @@ static void node_resize_exit(bContext *C, wmOperator *op, bool cancel) if (cancel) { SpaceNode *snode = CTX_wm_space_node(C); bNode *node = nodeGetActive(snode->edittree); - NodeSizeWidget *nsw = op->customdata; + NodeSizeWidget *nsw = (NodeSizeWidget *)op->customdata; node->locx = nsw->oldlocx; node->locy = nsw->oldlocy; @@ -937,7 +953,7 @@ static void node_resize_exit(bContext *C, wmOperator *op, bool cancel) } MEM_freeN(op->customdata); - op->customdata = NULL; + op->customdata = nullptr; } static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event) @@ -945,7 +961,7 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event) SpaceNode *snode = CTX_wm_space_node(C); ARegion *region = CTX_wm_region(C); bNode *node = nodeGetActive(snode->edittree); - NodeSizeWidget *nsw = op->customdata; + NodeSizeWidget *nsw = (NodeSizeWidget *)op->customdata; switch (event->type) { case MOUSEMOVE: { @@ -1112,7 +1128,7 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) else { /* hide unused sockets */ LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - if (sock->link == NULL) { + if (sock->link == nullptr) { sock->flag |= SOCK_HIDDEN; } } @@ -1128,17 +1144,17 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) 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.0f, - .xmax = socket->locx + NODE_SOCKSIZE * 2.0f, - /*.xmax = socket->locx + NODE_SOCKSIZE * 5.5f - * would be the same behavior as for regular sockets. - * But keep it smaller because for multi-input socket you - * sometimes want to drag the link to the other side, if you may - * accidentally pick the wrong link otherwise. */ - .ymin = socket->locy - node_socket_height, - .ymax = socket->locy + node_socket_height, - }; + rctf multi_socket_rect; + /* `.xmax = socket->locx + NODE_SOCKSIZE * 5.5f` + * would be the same behavior as for regular sockets. + * But keep it smaller because for multi-input socket you + * sometimes want to drag the link to the other side, if you may + * accidentally pick the wrong link otherwise. */ + BLI_rctf_init(&multi_socket_rect, + socket->locx - NODE_SOCKSIZE * 4.0f, + socket->locx + NODE_SOCKSIZE * 2.0f, + socket->locy - node_socket_height, + socket->locy + node_socket_height); if (BLI_rctf_isect_pt(&multi_socket_rect, cursor[0], cursor[1])) { return true; } @@ -1151,8 +1167,8 @@ int node_find_indicated_socket( { rctf rect; - *nodep = NULL; - *sockp = NULL; + *nodep = nullptr; + *sockp = nullptr; /* check if we click in a socket */ LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { @@ -1244,7 +1260,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), bmain); - bNode *lastnode = ntree->nodes.last; + bNode *lastnode = (bNode *)ntree->nodes.last; LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & SELECT) { BKE_node_copy_store_new_pointers(ntree, node, LIB_ID_COPY_DEFAULT); @@ -1262,14 +1278,14 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) /* copy links between selected nodes * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy! */ - bNodeLink *lastlink = ntree->links.last; + bNodeLink *lastlink = (bNodeLink *)ntree->links.last; LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { /* This creates new links between copied nodes. - * If keep_inputs is set, also copies input links from unselected (when fromnode==NULL)! + * If keep_inputs is set, also copies input links from unselected (when fromnode==nullptr)! */ if (link->tonode && (link->tonode->flag & NODE_SELECT) && (keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT)))) { - bNodeLink *newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink"); + bNodeLink *newlink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "bNodeLink"); newlink->flag = link->flag; newlink->tonode = link->tonode->new_node; newlink->tosock = link->tosock->new_sock; @@ -1317,7 +1333,6 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) nodeSetSelected(node, false); node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_TEXTURE); nodeSetSelected(newnode, true); - newnode->flag &= ~NODE_ACTIVE_PREVIEW; do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, newnode)); } @@ -1353,12 +1368,12 @@ void NODE_OT_duplicate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean( - ot->srna, "keep_inputs", 0, "Keep Inputs", "Keep the input links to duplicated nodes"); + ot->srna, "keep_inputs", false, "Keep Inputs", "Keep the input links to duplicated nodes"); } -bool ED_node_select_check(ListBase *lb) +bool ED_node_select_check(const ListBase *lb) { - LISTBASE_FOREACH (bNode *, node, lb) { + LISTBASE_FOREACH (const bNode *, node, lb) { if (node->flag & NODE_SELECT) { return true; } @@ -1414,7 +1429,7 @@ static int node_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op)) if ((node->type == CMP_NODE_R_LAYERS) || (node->type == CMP_NODE_CRYPTOMATTE && node->custom1 == CMP_CRYPTOMATTE_SRC_RENDER)) { ID *id = node->id; - if (id == NULL) { + if (id == nullptr) { continue; } if (id->tag & LIB_TAG_DOIT) { @@ -1453,7 +1468,7 @@ int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op)) /* This is actually a test whether scene is used by the compositor or not. * All the nodes are using same render result, so there is no need to do * anything smart about check how exactly scene is used. */ - bNode *node = NULL; + bNode *node = nullptr; LISTBASE_FOREACH (bNode *, node_iter, &sce->nodetree->nodes) { if (node_iter->id == (ID *)sce) { node = node_iter; @@ -1462,7 +1477,7 @@ int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op)) } if (node) { - ViewLayer *view_layer = BLI_findlink(&sce->view_layers, node->custom1); + ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&sce->view_layers, node->custom1); if (view_layer) { PointerRNA op_ptr; @@ -1471,7 +1486,7 @@ int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op)) RNA_string_set(&op_ptr, "layer", view_layer->name); RNA_string_set(&op_ptr, "scene", sce->id.name + 2); - /* to keep keypositions */ + /* To keep keyframe positions. */ sce->r.scemode |= R_NO_FRAME_UPDATE; WM_operator_name_call(C, "RENDER_OT_render", WM_OP_INVOKE_DEFAULT, &op_ptr); @@ -1554,13 +1569,13 @@ static int node_hide_toggle_exec(bContext *C, wmOperator *UNUSED(op)) SpaceNode *snode = CTX_wm_space_node(C); /* sanity checking (poll callback checks this already) */ - if ((snode == NULL) || (snode->edittree == NULL)) { + if ((snode == nullptr) || (snode->edittree == nullptr)) { return OPERATOR_CANCELLED; } node_flag_toggle_exec(snode, NODE_HIDDEN); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; } @@ -1585,7 +1600,7 @@ static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op)) SpaceNode *snode = CTX_wm_space_node(C); /* sanity checking (poll callback checks this already) */ - if ((snode == NULL) || (snode->edittree == NULL)) { + if ((snode == nullptr) || (snode->edittree == nullptr)) { return OPERATOR_CANCELLED; } @@ -1618,13 +1633,13 @@ static int node_options_toggle_exec(bContext *C, wmOperator *UNUSED(op)) SpaceNode *snode = CTX_wm_space_node(C); /* sanity checking (poll callback checks this already) */ - if ((snode == NULL) || (snode->edittree == NULL)) { + if ((snode == nullptr) || (snode->edittree == nullptr)) { return OPERATOR_CANCELLED; } node_flag_toggle_exec(snode, NODE_OPTIONS); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; } @@ -1649,7 +1664,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op)) SpaceNode *snode = CTX_wm_space_node(C); /* sanity checking (poll callback checks this already) */ - if ((snode == NULL) || (snode->edittree == NULL)) { + if ((snode == nullptr) || (snode->edittree == nullptr)) { return OPERATOR_CANCELLED; } @@ -1674,7 +1689,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op)) ntreeUpdateTree(CTX_data_main(C), snode->edittree); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; } @@ -1870,12 +1885,12 @@ static int node_output_file_add_socket_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); SpaceNode *snode = CTX_wm_space_node(C); PointerRNA ptr = CTX_data_pointer_get(C, "node"); - bNodeTree *ntree = NULL; - bNode *node = NULL; + bNodeTree *ntree = nullptr; + bNode *node = nullptr; char file_path[MAX_NAME]; if (ptr.data) { - node = ptr.data; + node = (bNode *)ptr.data; ntree = (bNodeTree *)ptr.owner_id; } else if (snode && snode->edittree) { @@ -1919,11 +1934,11 @@ static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *U { SpaceNode *snode = CTX_wm_space_node(C); PointerRNA ptr = CTX_data_pointer_get(C, "node"); - bNodeTree *ntree = NULL; - bNode *node = NULL; + bNodeTree *ntree = nullptr; + bNode *node = nullptr; if (ptr.data) { - node = ptr.data; + node = (bNode *)ptr.data; ntree = (bNodeTree *)ptr.owner_id; } else if (snode && snode->edittree) { @@ -1965,10 +1980,10 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op) { SpaceNode *snode = CTX_wm_space_node(C); PointerRNA ptr = CTX_data_pointer_get(C, "node"); - bNode *node = NULL; + bNode *node = nullptr; if (ptr.data) { - node = ptr.data; + node = (bNode *)ptr.data; } else if (snode && snode->edittree) { node = nodeGetActive(snode->edittree); @@ -1978,9 +1993,9 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - NodeImageMultiFile *nimf = node->storage; + NodeImageMultiFile *nimf = (NodeImageMultiFile *)node->storage; - bNodeSocket *sock = BLI_findlink(&node->inputs, nimf->active_input); + bNodeSocket *sock = (bNodeSocket *)BLI_findlink(&node->inputs, nimf->active_input); if (!sock) { return OPERATOR_CANCELLED; } @@ -2014,7 +2029,7 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op) void NODE_OT_output_file_move_active_socket(wmOperatorType *ot) { static const EnumPropertyItem direction_items[] = { - {1, "UP", 0, "Up", ""}, {2, "DOWN", 0, "Down", ""}, {0, NULL, 0, NULL, NULL}}; + {1, "UP", 0, "Up", ""}, {2, "DOWN", 0, "Down", ""}, {0, nullptr, 0, nullptr, nullptr}}; /* identifiers */ ot->name = "Move File Node Socket"; @@ -2059,7 +2074,7 @@ static int node_copy_color_exec(bContext *C, wmOperator *UNUSED(op)) } ED_node_sort(ntree); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; } @@ -2097,7 +2112,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) /* No ID refcounting, this node is virtual, * detached from any actual Blender data currently. */ bNode *new_node = BKE_node_copy_store_new_pointers( - NULL, node, LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN); + nullptr, node, LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN); BKE_node_clipboard_add_node(new_node); } } @@ -2127,7 +2142,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) /* This creates new links between copied nodes. */ if (link->tonode && (link->tonode->flag & NODE_SELECT) && link->fromnode && (link->fromnode->flag & NODE_SELECT)) { - bNodeLink *newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink"); + bNodeLink *newlink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "bNodeLink"); newlink->flag = link->flag; newlink->tonode = link->tonode->new_node; newlink->tosock = link->tosock->new_sock; @@ -2188,7 +2203,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) /* make sure all clipboard nodes would be valid in the target tree */ bool all_nodes_valid = true; LISTBASE_FOREACH (bNode *, node, clipboard_nodes_lb) { - const char *disabled_hint = NULL; + const char *disabled_hint = nullptr; if (!node->typeinfo->poll_instance || !node->typeinfo->poll_instance(node, ntree, &disabled_hint)) { all_nodes_valid = false; @@ -2286,7 +2301,7 @@ static bNodeSocket *ntree_get_active_interface_socket(ListBase *lb) return socket; } } - return NULL; + return nullptr; } static int ntree_socket_add_exec(bContext *C, wmOperator *op) @@ -2297,7 +2312,7 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op) PointerRNA ntree_ptr; RNA_id_pointer_create((ID *)ntree, &ntree_ptr); - const eNodeSocketInOut in_out = RNA_enum_get(op->ptr, "in_out"); + const eNodeSocketInOut in_out = (eNodeSocketInOut)RNA_enum_get(op->ptr, "in_out"); ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs; const char *default_name = (in_out == SOCK_IN) ? "Input" : "Output"; @@ -2309,10 +2324,10 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op) sock = ntreeInsertSocketInterface( ntree, in_out, active_sock->idname, active_sock->next, active_sock->name); /* XXX this only works for actual sockets, not interface templates! */ - /*nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);*/ + // nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr); } else { - /* XXX TODO define default socket type for a tree! */ + /* XXX TODO: define default socket type for a tree! */ sock = ntreeAddSocketInterface(ntree, in_out, "NodeSocketFloat", default_name); } @@ -2328,7 +2343,7 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op) snode_notify(C, snode); snode_dag_update(C, snode); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; } @@ -2356,11 +2371,11 @@ static int ntree_socket_remove_exec(bContext *C, wmOperator *op) { SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; - const eNodeSocketInOut in_out = RNA_enum_get(op->ptr, "in_out"); + const eNodeSocketInOut in_out = (eNodeSocketInOut)RNA_enum_get(op->ptr, "in_out"); bNodeSocket *iosock = ntree_get_active_interface_socket(in_out == SOCK_IN ? &ntree->inputs : &ntree->outputs); - if (iosock == NULL) { + if (iosock == nullptr) { return OPERATOR_CANCELLED; } @@ -2378,7 +2393,7 @@ static int ntree_socket_remove_exec(bContext *C, wmOperator *op) snode_notify(C, snode); snode_dag_update(C, snode); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; } @@ -2399,12 +2414,115 @@ void NODE_OT_tree_socket_remove(wmOperatorType *ot) RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", ""); } +/********************** Change interface socket type operator *********************/ + +static int ntree_socket_change_type_exec(bContext *C, wmOperator *op) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree = snode->edittree; + const eNodeSocketInOut in_out = (eNodeSocketInOut)RNA_enum_get(op->ptr, "in_out"); + const bNodeSocketType *socket_type = rna_node_socket_type_from_enum( + RNA_enum_get(op->ptr, "socket_type")); + ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs; + + Main *main = CTX_data_main(C); + + bNodeSocket *iosock = ntree_get_active_interface_socket(sockets); + if (iosock == nullptr) { + return OPERATOR_CANCELLED; + } + + /* The type remains the same, so we don't need to change anything. */ + if (iosock->typeinfo == socket_type) { + return OPERATOR_FINISHED; + } + + /* Don't handle subtypes for now. */ + nodeModifySocketType(ntree, nullptr, iosock, socket_type->idname); + + /* Need the extra update here because the loop above does not check for valid links in the node + * group we're currently editing. */ + ntree->update |= NTREE_UPDATE_GROUP | NTREE_UPDATE_LINKS; + + /* Deactivate sockets. */ + LISTBASE_FOREACH (bNodeSocket *, socket_iter, sockets) { + socket_iter->flag &= ~SELECT; + } + /* Make the new socket active. */ + iosock->flag |= SELECT; + + ntreeUpdateTree(main, ntree); + + snode_notify(C, snode); + snode_dag_update(C, snode); + + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); + + return OPERATOR_FINISHED; +} + +static bool socket_change_poll_type(void *userdata, bNodeSocketType *socket_type) +{ + /* Check if the node tree supports the socket type. */ + bNodeTreeType *ntreetype = (bNodeTreeType *)userdata; + if (ntreetype->valid_socket_type && !ntreetype->valid_socket_type(ntreetype, socket_type)) { + return false; + } + + /* Only use basic socket types for this enum. */ + if (socket_type->subtype != PROP_NONE) { + return false; + } + + return true; +} + +static const EnumPropertyItem *socket_change_type_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) +{ + if (!C) { + return DummyRNA_NULL_items; + } + + SpaceNode *snode = CTX_wm_space_node(C); + if (!snode || !snode->edittree) { + return DummyRNA_NULL_items; + } + + return rna_node_socket_type_itemf(snode->edittree->typeinfo, socket_change_poll_type, r_free); +} + +void NODE_OT_tree_socket_change_type(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Change Node Tree Interface Socket Type"; + ot->description = "Change the type of a socket of the current node tree"; + ot->idname = "NODE_OT_tree_socket_change_type"; + + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = ntree_socket_change_type_exec; + ot->poll = ED_operator_node_editable; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", ""); + prop = RNA_def_enum(ot->srna, "socket_type", DummyRNA_DEFAULT_items, 0, "Socket Type", ""); + RNA_def_enum_funcs(prop, socket_change_type_itemf); + ot->prop = prop; +} + /********************** Move interface socket operator *********************/ static const EnumPropertyItem move_direction_items[] = { {1, "UP", 0, "Up", ""}, {2, "DOWN", 0, "Down", ""}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; static int ntree_socket_move_exec(bContext *C, wmOperator *op) @@ -2413,12 +2531,12 @@ static int ntree_socket_move_exec(bContext *C, wmOperator *op) bNodeTree *ntree = snode->edittree; int direction = RNA_enum_get(op->ptr, "direction"); - const eNodeSocketInOut in_out = RNA_enum_get(op->ptr, "in_out"); + const eNodeSocketInOut in_out = (eNodeSocketInOut)RNA_enum_get(op->ptr, "in_out"); ListBase *sockets = in_out == SOCK_IN ? &ntree->inputs : &ntree->outputs; bNodeSocket *iosock = ntree_get_active_interface_socket(sockets); - if (iosock == NULL) { + if (iosock == nullptr) { return OPERATOR_CANCELLED; } @@ -2453,7 +2571,7 @@ static int ntree_socket_move_exec(bContext *C, wmOperator *op) snode_notify(C, snode); snode_dag_update(C, snode); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; } @@ -2486,18 +2604,18 @@ static bool node_shader_script_update_poll(bContext *C) /* test if we have a render engine that supports shaders scripts */ if (!(type && type->update_script_node)) { - return 0; + return false; } /* see if we have a shader script node in context */ - bNode *node = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data; + bNode *node = (bNode *)CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data; if (!node && snode && snode->edittree) { node = nodeGetActive(snode->edittree); } if (node && node->type == SH_NODE_SCRIPT) { - NodeShaderScript *nss = node->storage; + NodeShaderScript *nss = (NodeShaderScript *)node->storage; if (node->id || nss->filepath[0]) { return ED_operator_node_editable(C); @@ -2505,14 +2623,14 @@ static bool node_shader_script_update_poll(bContext *C) } /* see if we have a text datablock in context */ - Text *text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; + Text *text = (Text *)CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; if (text) { - return 1; + return true; } /* we don't check if text datablock is actually in use, too slow for poll */ - return 0; + return false; } /* recursively check for script nodes in groups using this text and update */ @@ -2556,11 +2674,11 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op) engine->reports = op->reports; /* get node */ - bNodeTree *ntree_base = NULL; - bNode *node = NULL; + bNodeTree *ntree_base = nullptr; + bNode *node = nullptr; if (nodeptr.data) { ntree_base = (bNodeTree *)nodeptr.owner_id; - node = nodeptr.data; + node = (bNode *)nodeptr.data; } else if (snode && snode->edittree) { ntree_base = snode->edittree; @@ -2575,7 +2693,7 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op) } else { /* update all nodes using text datablock */ - Text *text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; + Text *text = (Text *)CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; if (text) { /* clear flags for recursion check */ @@ -2647,7 +2765,7 @@ static int viewer_border_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), bmain); Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock); if (ibuf) { ARegion *region = CTX_wm_region(C); @@ -2683,7 +2801,7 @@ static int viewer_border_exec(bContext *C, wmOperator *op) } snode_notify(C, snode); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); } else { btree->flag &= ~NTREE_VIEWER_BORDER; @@ -2723,7 +2841,7 @@ static int clear_viewer_border_exec(bContext *C, wmOperator *UNUSED(op)) btree->flag &= ~NTREE_VIEWER_BORDER; snode_notify(C, snode); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; } @@ -2749,11 +2867,11 @@ static int node_cryptomatte_add_socket_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode = CTX_wm_space_node(C); PointerRNA ptr = CTX_data_pointer_get(C, "node"); - bNodeTree *ntree = NULL; - bNode *node = NULL; + bNodeTree *ntree = nullptr; + bNode *node = nullptr; if (ptr.data) { - node = ptr.data; + node = (bNode *)ptr.data; ntree = (bNodeTree *)ptr.owner_id; } else if (snode && snode->edittree) { @@ -2793,11 +2911,11 @@ static int node_cryptomatte_remove_socket_exec(bContext *C, wmOperator *UNUSED(o { SpaceNode *snode = CTX_wm_space_node(C); PointerRNA ptr = CTX_data_pointer_get(C, "node"); - bNodeTree *ntree = NULL; - bNode *node = NULL; + bNodeTree *ntree = nullptr; + bNode *node = nullptr; if (ptr.data) { - node = ptr.data; + node = (bNode *)ptr.data; ntree = (bNodeTree *)ptr.owner_id; } else if (snode && snode->edittree) { diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc index 856a90be5ae..a6901c21862 100644 --- a/source/blender/editors/space_node/node_geometry_attribute_search.cc +++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc @@ -27,28 +27,33 @@ #include "DNA_space_types.h" #include "BKE_context.h" -#include "BKE_node_ui_storage.hh" #include "BKE_object.h" #include "RNA_access.h" #include "RNA_enum_types.h" +#include "ED_undo.h" + #include "BLT_translation.h" #include "UI_interface.h" #include "UI_resources.h" +#include "NOD_geometry_nodes_eval_log.hh" + #include "node_intern.h" using blender::IndexRange; using blender::Map; using blender::Set; using blender::StringRef; +namespace geo_log = blender::nodes::geometry_nodes_eval_log; +using geo_log::GeometryAttributeInfo; struct AttributeSearchData { - AvailableAttributeInfo &dummy_info_for_search; - const NodeUIStorage &ui_storage; - bNodeSocket &socket; + const bNodeTree *tree; + const bNode *node; + bNodeSocket *socket; }; /* This class must not have a destructor, since it is used by buttons and freed with #MEM_freeN. */ @@ -71,7 +76,7 @@ static StringRef attribute_domain_string(const AttributeDomain domain) /* Unicode arrow. */ #define MENU_SEP "\xe2\x96\xb6" -static bool attribute_search_item_add(uiSearchItems *items, const AvailableAttributeInfo &item) +static bool attribute_search_item_add(uiSearchItems *items, const GeometryAttributeInfo &item) { const StringRef data_type_name = attribute_data_type_string(item.data_type); const StringRef domain_name = attribute_domain_string(item.domain); @@ -82,31 +87,47 @@ static bool attribute_search_item_add(uiSearchItems *items, const AvailableAttri items, search_item_text.c_str(), (void *)&item, ICON_NONE, UI_BUT_HAS_SEP_CHAR, 0); } -static void attribute_search_update_fn(const bContext *UNUSED(C), - void *arg, - const char *str, - uiSearchItems *items, - const bool is_first) +static GeometryAttributeInfo &get_dummy_item_info() +{ + static GeometryAttributeInfo info; + return info; +} + +static void attribute_search_update_fn( + const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first) { AttributeSearchData *data = static_cast<AttributeSearchData *>(arg); - const Set<AvailableAttributeInfo> &attribute_hints = data->ui_storage.attribute_hints; + SpaceNode *snode = CTX_wm_space_node(C); + const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context( + *snode, *data->node); + if (node_log == nullptr) { + return; + } + blender::Vector<const GeometryAttributeInfo *> infos = node_log->lookup_available_attributes(); + + GeometryAttributeInfo &dummy_info = get_dummy_item_info(); /* Any string may be valid, so add the current search string along with the hints. */ if (str[0] != '\0') { - /* Note that the attribute domain and data type are dummies, since - * #AvailableAttributeInfo equality is only based on the string. */ - if (!attribute_hints.contains(AvailableAttributeInfo{str, ATTR_DOMAIN_AUTO, CD_PROP_BOOL})) { - data->dummy_info_for_search.name = std::string(str); - UI_search_item_add(items, str, &data->dummy_info_for_search, ICON_ADD, 0, 0); + bool contained = false; + for (const GeometryAttributeInfo *attribute_info : infos) { + if (attribute_info->name == str) { + contained = true; + break; + } + } + if (!contained) { + dummy_info.name = str; + UI_search_item_add(items, str, &dummy_info, ICON_ADD, 0, 0); } } if (str[0] == '\0' && !is_first) { /* Allow clearing the text field when the string is empty, but not on the first pass, * or opening an attribute field for the first time would show this search item. */ - data->dummy_info_for_search.name = std::string(str); - UI_search_item_add(items, str, &data->dummy_info_for_search, ICON_X, 0, 0); + dummy_info.name = str; + UI_search_item_add(items, str, &dummy_info, ICON_X, 0, 0); } /* Don't filter when the menu is first opened, but still run the search @@ -114,15 +135,15 @@ static void attribute_search_update_fn(const bContext *UNUSED(C), const char *string = is_first ? "" : str; StringSearch *search = BLI_string_search_new(); - for (const AvailableAttributeInfo &item : attribute_hints) { - BLI_string_search_add(search, item.name.c_str(), (void *)&item); + for (const GeometryAttributeInfo *item : infos) { + BLI_string_search_add(search, item->name.c_str(), (void *)item); } - AvailableAttributeInfo **filtered_items; + GeometryAttributeInfo **filtered_items; const int filtered_amount = BLI_string_search_query(search, string, (void ***)&filtered_items); for (const int i : IndexRange(filtered_amount)) { - const AvailableAttributeInfo *item = filtered_items[i]; + const GeometryAttributeInfo *item = filtered_items[i]; if (!attribute_search_item_add(items, *item)) { break; } @@ -132,32 +153,27 @@ static void attribute_search_update_fn(const bContext *UNUSED(C), BLI_string_search_free(search); } -static void attribute_search_exec_fn(bContext *UNUSED(C), void *data_v, void *item_v) +static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v) { + if (item_v == nullptr) { + return; + } AttributeSearchData *data = static_cast<AttributeSearchData *>(data_v); - AvailableAttributeInfo *item = static_cast<AvailableAttributeInfo *>(item_v); + GeometryAttributeInfo *item = (GeometryAttributeInfo *)item_v; - bNodeSocket &socket = data->socket; + bNodeSocket &socket = *data->socket; bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket.default_value); BLI_strncpy(value->value, item->name.c_str(), MAX_NAME); + + ED_undo_push(C, "Assign Attribute Name"); } -void node_geometry_add_attribute_search_button(const bContext *C, +void node_geometry_add_attribute_search_button(const bContext *UNUSED(C), const bNodeTree *node_tree, const bNode *node, PointerRNA *socket_ptr, uiLayout *layout) { - const NodeUIStorage *ui_storage = BKE_node_tree_ui_storage_get_from_context( - C, *node_tree, *node); - - if (ui_storage == nullptr) { - uiItemR(layout, socket_ptr, "default_value", 0, "", 0); - return; - } - - const NodeTreeUIStorage *tree_ui_storage = node_tree->ui_storage; - uiBlock *block = uiLayoutGetBlock(layout); uiBut *but = uiDefIconTextButR(block, UI_BTYPE_SEARCH_MENU, @@ -177,10 +193,8 @@ void node_geometry_add_attribute_search_button(const bContext *C, 0.0f, ""); - AttributeSearchData *data = OBJECT_GUARDED_NEW(AttributeSearchData, - {tree_ui_storage->dummy_info_for_search, - *ui_storage, - *static_cast<bNodeSocket *>(socket_ptr->data)}); + AttributeSearchData *data = OBJECT_GUARDED_NEW( + AttributeSearchData, {node_tree, node, (bNodeSocket *)socket_ptr->data}); UI_but_func_search_set_results_are_suggestions(but, true); UI_but_func_search_set_sep_string(but, MENU_SEP); diff --git a/source/blender/editors/space_node/node_gizmo.c b/source/blender/editors/space_node/node_gizmo.c index 28d7e1b8d04..e1deca54890 100644 --- a/source/blender/editors/space_node/node_gizmo.c +++ b/source/blender/editors/space_node/node_gizmo.c @@ -97,7 +97,6 @@ static void gizmo_node_backdrop_prop_matrix_set(const wmGizmo *UNUSED(gz), BLI_assert(gz_prop->type->array_length == 16); SpaceNode *snode = gz_prop->custom_func.user_data; snode->zoom = matrix[0][0]; - snode->zoom = matrix[1][1]; snode->xof = matrix[3][0]; snode->yof = matrix[3][1]; } @@ -156,7 +155,7 @@ static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup * WM_gizmo_set_matrix_location(cage, origin); WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, false); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* Need to set property here for undo. TODO: would prefer to do this in _init. */ SpaceNode *snode = CTX_wm_space_node(C); #if 0 PointerRNA nodeptr; @@ -493,7 +492,7 @@ static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *gzgr SpaceNode *snode = CTX_wm_space_node(C); bNode *node = nodeGetActive(snode->edittree); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* Need to set property here for undo. TODO: would prefer to do this in _init. */ PointerRNA nodeptr; RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeSunBeams, node, &nodeptr); WM_gizmo_target_property_def_rna(gz, "offset", &nodeptr, "source", -1); @@ -605,7 +604,7 @@ static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup SpaceNode *snode = CTX_wm_space_node(C); bNode *node = nodeGetActive(snode->edittree); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* need to set property here for undo. TODO: would prefer to do this in _init. */ int i = 0; for (bNodeSocket *sock = node->inputs.first; sock && i < 4; sock = sock->next) { if (sock->type == SOCK_VECTOR) { diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.cc index 335e2f93ff3..d7541d8f512 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.cc @@ -21,7 +21,7 @@ * \ingroup spnode */ -#include <stdlib.h> +#include <cstdlib> #include "MEM_guardedalloc.h" @@ -70,9 +70,8 @@ static bool node_group_operator_active_poll(bContext *C) SpaceNode *snode = CTX_wm_space_node(C); /* Group operators only defined for standard node tree types. - * Disabled otherwise to allow pynodes define their own operators - * with same keymap. - */ + * Disabled otherwise to allow python-nodes define their own operators + * with same key-map. */ if (STR_ELEM(snode->tree_idname, "ShaderNodeTree", "CompositorNodeTree", @@ -90,9 +89,8 @@ static bool node_group_operator_editable(bContext *C) SpaceNode *snode = CTX_wm_space_node(C); /* Group operators only defined for standard node tree types. - * Disabled otherwise to allow pynodes define their own operators - * with same keymap. - */ + * Disabled otherwise to allow python-nodes define their own operators + * with same key-map. */ if (ED_node_is_shader(snode) || ED_node_is_compositor(snode) || ED_node_is_texture(snode) || ED_node_is_geometry(snode)) { return true; @@ -135,7 +133,7 @@ static bNode *node_group_get_active(bContext *C, const char *node_idname) if (node && STREQ(node->idname, node_idname)) { return node; } - return NULL; + return nullptr; } /** \} */ @@ -165,7 +163,7 @@ static int node_group_edit_exec(bContext *C, wmOperator *op) ED_node_tree_pop(snode); } - WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_NODES, nullptr); return OPERATOR_FINISHED; } @@ -200,7 +198,8 @@ void NODE_OT_group_edit(wmOperatorType *ot) static AnimationBasePathChange *animation_basepath_change_new(const char *src_basepath, const char *dst_basepath) { - AnimationBasePathChange *basepath_change = MEM_callocN(sizeof(*basepath_change), AT); + AnimationBasePathChange *basepath_change = (AnimationBasePathChange *)MEM_callocN( + sizeof(*basepath_change), AT); basepath_change->src_basepath = src_basepath; basepath_change->dst_basepath = dst_basepath; return basepath_change; @@ -218,13 +217,13 @@ static void animation_basepath_change_free(AnimationBasePathChange *basepath_cha /* returns 1 if its OK */ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) { - /* clear new pointers, set in copytree */ + /* Clear new pointers, set in #ntreeCopyTree_ex_new_pointers. */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - node->new_node = NULL; + node->new_node = nullptr; } - ListBase anim_basepaths = {NULL, NULL}; - LinkNode *nodes_delayed_free = NULL; + ListBase anim_basepaths = {nullptr, nullptr}; + LinkNode *nodes_delayed_free = nullptr; bNodeTree *ngroup = (bNodeTree *)gnode->id; /* wgroup is a temporary copy of the NodeTree we're merging in @@ -247,7 +246,7 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) /* keep track of this node's RNA "base" path (the part of the path identifying the node) * if the old nodetree has animation data which potentially covers this node */ - const char *old_animation_basepath = NULL; + const char *old_animation_basepath = nullptr; if (wgroup->adt) { PointerRNA ptr; RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr); @@ -277,7 +276,7 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) node->flag |= NODE_SELECT; } - bNodeLink *glinks_first = ntree->links.last; + bNodeLink *glinks_first = (bNodeLink *)ntree->links.last; /* Add internal links to the ntree */ LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &wgroup->links) { @@ -285,10 +284,10 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) BLI_addtail(&ntree->links, link); } - bNodeLink *glinks_last = ntree->links.last; + bNodeLink *glinks_last = (bNodeLink *)ntree->links.last; /* and copy across the animation, - * note that the animation data's action can be NULL here */ + * note that the animation data's action can be nullptr here */ if (wgroup->adt) { bAction *waction; @@ -307,7 +306,7 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) /* free temp action too */ if (waction) { BKE_id_free(bmain, waction); - wgroup->adt->action = NULL; + wgroup->adt->action = nullptr; } } @@ -317,14 +316,14 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) /* restore external links to and from the gnode */ /* input links */ - if (glinks_first != NULL) { + if (glinks_first != nullptr) { for (bNodeLink *link = glinks_first->next; link != glinks_last->next; link = link->next) { if (link->fromnode->type == NODE_GROUP_INPUT) { const char *identifier = link->fromsock->identifier; int num_external_links = 0; /* find external links to this input */ - for (bNodeLink *tlink = ntree->links.first; tlink != glinks_first->next; + for (bNodeLink *tlink = (bNodeLink *)ntree->links.first; tlink != glinks_first->next; tlink = tlink->next) { if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) { nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode, link->tosock); @@ -348,10 +347,11 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) } /* Also iterate over new links to cover passthrough links. */ - glinks_last = ntree->links.last; + glinks_last = (bNodeLink *)ntree->links.last; /* output links */ - for (bNodeLink *link = ntree->links.first; link != glinks_first->next; link = link->next) { + for (bNodeLink *link = (bNodeLink *)ntree->links.first; link != glinks_first->next; + link = link->next) { if (link->fromnode == gnode) { const char *identifier = link->fromsock->identifier; int num_internal_links = 0; @@ -384,7 +384,7 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) } while (nodes_delayed_free) { - bNode *node = BLI_linklist_pop(&nodes_delayed_free); + bNode *node = (bNode *)BLI_linklist_pop(&nodes_delayed_free); nodeRemoveNode(bmain, ntree, node, false); } @@ -455,10 +455,10 @@ static int node_group_separate_selected( /* clear new pointers, set in BKE_node_copy_ex(). */ LISTBASE_FOREACH (bNode *, node, &ngroup->nodes) { - node->new_node = NULL; + node->new_node = nullptr; } - ListBase anim_basepaths = {NULL, NULL}; + ListBase anim_basepaths = {nullptr, nullptr}; /* add selected nodes into the ntree */ LISTBASE_FOREACH_MUTABLE (bNode *, node, &ngroup->nodes) { @@ -543,7 +543,7 @@ static int node_group_separate_selected( } /* and copy across the animation, - * note that the animation data's action can be NULL here */ + * note that the animation data's action can be nullptr here */ if (ngroup->adt) { /* now perform the moving */ BKE_animdata_transfer_by_basepath(bmain, &ngroup->id, &ntree->id, &anim_basepaths); @@ -562,16 +562,16 @@ static int node_group_separate_selected( return 1; } -typedef enum eNodeGroupSeparateType { +enum eNodeGroupSeparateType { NODE_GS_COPY, NODE_GS_MOVE, -} eNodeGroupSeparateType; +}; /* Operator Property */ static const EnumPropertyItem node_group_separate_types[] = { {NODE_GS_COPY, "COPY", 0, "Copy", "Copy to parent node tree, keep group intact"}, {NODE_GS_MOVE, "MOVE", 0, "Move", "Move to parent node tree, remove from group"}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; static int node_group_separate_exec(bContext *C, wmOperator *op) @@ -628,8 +628,8 @@ static int node_group_separate_invoke(bContext *C, uiLayout *layout = UI_popup_menu_layout(pup); uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT); - uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY); - uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE); + uiItemEnumO(layout, "NODE_OT_group_separate", nullptr, 0, "type", NODE_GS_COPY); + uiItemEnumO(layout, "NODE_OT_group_separate", nullptr, 0, "type", NODE_GS_MOVE); UI_popup_menu_end(C, pup); @@ -674,12 +674,12 @@ static bool node_group_make_test_selected(bNodeTree *ntree, int ok = true; /* make a local pseudo node tree to pass to the node poll functions */ - bNodeTree *ngroup = ntreeAddTree(NULL, "Pseudo Node Group", ntree_idname); + bNodeTree *ngroup = ntreeAddTree(nullptr, "Pseudo Node Group", ntree_idname); /* check poll functions for selected nodes */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node_group_make_use_node(node, gnode)) { - const char *disabled_hint = NULL; + const char *disabled_hint = nullptr; if (node->typeinfo->poll_instance && !node->typeinfo->poll_instance(node, ngroup, &disabled_hint)) { if (disabled_hint) { @@ -781,7 +781,7 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, expose_visible = true; } - ListBase anim_basepaths = {NULL, NULL}; + ListBase anim_basepaths = {nullptr, nullptr}; /* move nodes over */ LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) { @@ -926,7 +926,7 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, } } - /* expose all unlinked sockets too but only the visible ones*/ + /* Expose all unlinked sockets too but only the visible ones. */ if (expose_visible) { LISTBASE_FOREACH (bNode *, node, &ngroup->nodes) { if (node_group_make_use_node(node, gnode)) { @@ -995,10 +995,10 @@ static bNode *node_group_make_from_selected(const bContext *C, Main *bmain = CTX_data_main(C); float min[2], max[2]; - const int totselect = node_get_selected_minmax(ntree, NULL, min, max, false); + const int totselect = node_get_selected_minmax(ntree, nullptr, min, max, false); /* don't make empty group */ if (totselect == 0) { - return NULL; + return nullptr; } /* new nodetree */ @@ -1029,7 +1029,7 @@ static int node_group_make_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); - if (!node_group_make_test_selected(ntree, NULL, ntree_idname, op->reports)) { + if (!node_group_make_test_selected(ntree, nullptr, ntree_idname, op->reports)) { return OPERATOR_CANCELLED; } @@ -1042,7 +1042,7 @@ static int node_group_make_exec(bContext *C, wmOperator *op) if (ngroup) { ED_node_tree_push(snode, ngroup, gnode); LISTBASE_FOREACH (bNode *, node, &ngroup->nodes) { - sort_multi_input_socket_links(snode, node, NULL, NULL); + sort_multi_input_socket_links(snode, node, nullptr, nullptr); } ntreeUpdateTree(bmain, ngroup); } diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 2fcc59cde0b..09e5a110a45 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -25,6 +25,7 @@ #include "BKE_node.h" #include "UI_interface.h" +#include "UI_view2d.h" #include <stddef.h> /* for size_t */ /* internal exports only */ @@ -51,7 +52,7 @@ typedef struct bNodeLinkDrag { struct bNodeLinkDrag *next, *prev; /* List of links dragged by the operator. - * Note: This is a list of LinkData structs on top of the actual bNodeLinks. + * NOTE: This is a list of LinkData structs on top of the actual bNodeLinks. * This way the links can be added to the node tree while being stored in this list. */ ListBase links; @@ -64,6 +65,9 @@ typedef struct bNodeLinkDrag { /** Temporarily stores the last hovered socket for multi-input socket operator. * Store it to recalculate sorting after it is no longer hovered. */ struct bNode *last_node_hovered_while_dragging_a_link; + + /* Data for edge panning */ + View2DEdgePanData pan_data; } bNodeLinkDrag; typedef struct SpaceNode_Runtime { @@ -136,9 +140,6 @@ void node_to_view(const struct bNode *node, float x, float y, float *rx, float * void node_to_updated_rect(const struct bNode *node, rctf *r_rect); void node_from_view(const struct bNode *node, float x, float y, float *rx, float *ry); -/* node_buttons.c */ -void node_buttons_register(struct ARegionType *art); - /* node_toolbar.c */ void node_toolbar_register(struct ARegionType *art); @@ -275,7 +276,6 @@ void NODE_OT_hide_toggle(struct wmOperatorType *ot); void NODE_OT_hide_socket_toggle(struct wmOperatorType *ot); void NODE_OT_preview_toggle(struct wmOperatorType *ot); void NODE_OT_options_toggle(struct wmOperatorType *ot); -void NODE_OT_active_preview_toggle(struct wmOperatorType *ot); void NODE_OT_node_copy_color(struct wmOperatorType *ot); void NODE_OT_read_viewlayers(struct wmOperatorType *ot); @@ -287,12 +287,13 @@ void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot); void NODE_OT_switch_view_update(struct wmOperatorType *ot); -/* Note: clipboard_cut is a simple macro of copy + delete */ +/* NOTE: clipboard_cut is a simple macro of copy + delete. */ void NODE_OT_clipboard_copy(struct wmOperatorType *ot); void NODE_OT_clipboard_paste(struct wmOperatorType *ot); void NODE_OT_tree_socket_add(struct wmOperatorType *ot); void NODE_OT_tree_socket_remove(struct wmOperatorType *ot); +void NODE_OT_tree_socket_change_type(struct wmOperatorType *ot); void NODE_OT_tree_socket_move(struct wmOperatorType *ot); void NODE_OT_shader_script_update(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index e35b444aa11..610c2889e7a 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -119,6 +119,7 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_tree_socket_add); WM_operatortype_append(NODE_OT_tree_socket_remove); + WM_operatortype_append(NODE_OT_tree_socket_change_type); WM_operatortype_append(NODE_OT_tree_socket_move); WM_operatortype_append(NODE_OT_cryptomatte_layer_add); @@ -157,7 +158,7 @@ void ED_operatormacros_node(void) WM_operatortype_macro_define(ot, "NODE_OT_attach"); WM_operatortype_macro_define(ot, "NODE_OT_insert_offset"); - /* Note: Currently not in a default keymap or menu due to messy keymaps + /* NOTE: Currently not in a default keymap or menu due to messy keymaps * and tricky invoke functionality. * Kept around in case users want to make own shortcuts. */ diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.cc index 28c660b0632..aadf93961e9 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.cc @@ -40,11 +40,14 @@ #include "ED_node.h" /* own include */ #include "ED_render.h" #include "ED_screen.h" +#include "ED_spreadsheet.h" #include "ED_util.h" #include "RNA_access.h" #include "RNA_define.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -55,12 +58,14 @@ #include "node_intern.h" /* own include */ -/* ****************** Relations helpers *********************** */ +/* -------------------------------------------------------------------- */ +/** \name Relations Helpers + * \{ */ static bool ntree_has_drivers(bNodeTree *ntree) { const AnimData *adt = BKE_animdata_from_id(&ntree->id); - if (adt == NULL) { + if (adt == nullptr) { return false; } return !BLI_listbase_is_empty(&adt->drivers); @@ -102,7 +107,7 @@ static bool node_group_has_output_dfs(bNode *node) return false; } ntree->id.tag |= LIB_TAG_DOIT; - for (bNode *current_node = ntree->nodes.first; current_node != NULL; + for (bNode *current_node = (bNode *)ntree->nodes.first; current_node != nullptr; current_node = current_node->next) { if (current_node->type == NODE_GROUP) { if (current_node->id && node_group_has_output_dfs(current_node)) { @@ -120,7 +125,7 @@ static bool node_group_has_output(Main *bmain, bNode *node) { BLI_assert(ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)); bNodeTree *ntree = (bNodeTree *)node->id; - if (ntree == NULL) { + if (ntree == nullptr) { return false; } BKE_main_id_tag_listbase(&bmain->nodetrees, LIB_TAG_DOIT, false); @@ -145,7 +150,7 @@ bool node_connected_to_output(Main *bmain, bNodeTree *ntree, bNode *node) * is connected to and so eventually. */ if (ELEM(current_node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) { - if (current_node->id != NULL && ntree_has_drivers((bNodeTree *)current_node->id)) { + if (current_node->id != nullptr && ntree_has_drivers((bNodeTree *)current_node->id)) { return true; } if (ntree_check_nodes_connected(ntree, node, current_node) && @@ -158,18 +163,27 @@ bool node_connected_to_output(Main *bmain, bNodeTree *ntree, bNode *node) return true; } } + if (current_node->type == GEO_NODE_VIEWER) { + if (ntree_check_nodes_connected(ntree, node, current_node)) { + return true; + } + } } return false; } -/* ****************** Add *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Node + * \{ */ -typedef struct bNodeListItem { +struct bNodeListItem { struct bNodeListItem *next, *prev; struct bNode *node; -} bNodeListItem; +}; -typedef struct NodeInsertOfsData { +struct NodeInsertOfsData { bNodeTree *ntree; bNode *insert; /* inserted node */ bNode *prev, *next; /* prev/next node in the chain */ @@ -178,7 +192,7 @@ typedef struct NodeInsertOfsData { wmTimer *anim_timer; float offset_x; /* offset to apply to node chain */ -} NodeInsertOfsData; +}; static void clear_picking_highlight(ListBase *links) { @@ -189,8 +203,8 @@ static void clear_picking_highlight(ListBase *links) 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 *linkdata = (LinkData *)MEM_callocN(sizeof(LinkData), "drag link op link data"); + bNodeLink *oplink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "drag link op link"); linkdata->data = oplink; if (sock->in_out == SOCK_OUT) { oplink->fromnode = node; @@ -225,10 +239,10 @@ static void pick_link(const bContext *C, BLI_addtail(&nldrag->links, linkdata); nodeRemLink(snode->edittree, link_to_pick); - BLI_assert(nldrag->last_node_hovered_while_dragging_a_link != NULL); + BLI_assert(nldrag->last_node_hovered_while_dragging_a_link != nullptr); sort_multi_input_socket_links( - snode, nldrag->last_node_hovered_while_dragging_a_link, NULL, NULL); + snode, nldrag->last_node_hovered_while_dragging_a_link, nullptr, nullptr); /* Send changed event to original link->tonode. */ if (node) { @@ -256,7 +270,7 @@ static void pick_input_link_by_link_intersect(const bContext *C, const int resolution = NODE_LINK_RESOL; - bNodeLink *link_to_pick = NULL; + bNodeLink *link_to_pick = nullptr; clear_picking_highlight(&snode->edittree->links); LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { if (link->tosock == socket) { @@ -305,8 +319,8 @@ static void pick_input_link_by_link_intersect(const bContext *C, static int sort_nodes_locx(const void *a, const void *b) { - const bNodeListItem *nli1 = a; - const bNodeListItem *nli2 = b; + const bNodeListItem *nli1 = (const bNodeListItem *)a; + const bNodeListItem *nli2 = (const bNodeListItem *)b; const bNode *node1 = nli1->node; const bNode *node2 = nli2->node; @@ -319,14 +333,14 @@ static int sort_nodes_locx(const void *a, const void *b) static bool socket_is_available(bNodeTree *UNUSED(ntree), bNodeSocket *sock, const bool allow_used) { if (nodeSocketIsHidden(sock)) { - return 0; + return false; } if (!allow_used && (sock->flag & SOCK_IN_USE)) { - return 0; + return false; } - return 1; + return true; } static bNodeSocket *best_socket_output(bNodeTree *ntree, @@ -374,10 +388,10 @@ static bNodeSocket *best_socket_output(bNodeTree *ntree, /* Always allow linking to an reroute node. The socket type of the reroute sockets might change * after the link has been created. */ if (node->type == NODE_REROUTE) { - return node->outputs.first; + return (bNodeSocket *)node->outputs.first; } - return NULL; + return nullptr; } /* this is a bit complicated, but designed to prioritize finding @@ -409,7 +423,7 @@ static bNodeSocket *best_socket_input(bNodeTree *ntree, bNode *node, int num, in } } - return NULL; + return nullptr; } static bool snode_autoconnect_input(SpaceNode *snode, @@ -430,10 +444,10 @@ static bool snode_autoconnect_input(SpaceNode *snode, return true; } -typedef struct LinkAndPosition { +struct LinkAndPosition { struct bNodeLink *link; float multi_socket_position[2]; -} LinkAndPosition; +}; static int compare_link_by_y_position(const void *a, const void *b) { @@ -457,14 +471,14 @@ void sort_multi_input_socket_links(SpaceNode *snode, } /* The total is calculated in #node_update_nodetree, which runs before this draw step. */ int total_inputs = socket->total_inputs + 1; - struct LinkAndPosition **input_links = MEM_malloc_arrayN( + struct LinkAndPosition **input_links = (LinkAndPosition **)MEM_malloc_arrayN( total_inputs, sizeof(LinkAndPosition *), __func__); int index = 0; LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { if (link->tosock == socket) { - struct LinkAndPosition *link_and_position = MEM_callocN(sizeof(struct LinkAndPosition), - __func__); + struct LinkAndPosition *link_and_position = (LinkAndPosition *)MEM_callocN( + sizeof(struct LinkAndPosition), __func__); link_and_position->link = link; node_link_calculate_multi_input_position(link->tosock->locx, link->tosock->locy, @@ -477,7 +491,8 @@ void sort_multi_input_socket_links(SpaceNode *snode, } if (drag_link) { - LinkAndPosition *link_and_position = MEM_callocN(sizeof(LinkAndPosition), __func__); + LinkAndPosition *link_and_position = (LinkAndPosition *)MEM_callocN(sizeof(LinkAndPosition), + __func__); link_and_position->link = drag_link; copy_v2_v2(link_and_position->multi_socket_position, cursor); input_links[index] = link_and_position; @@ -505,11 +520,12 @@ static void snode_autoconnect(Main *bmain, const bool replace) { bNodeTree *ntree = snode->edittree; - ListBase *nodelist = MEM_callocN(sizeof(ListBase), "items_list"); + ListBase *nodelist = (ListBase *)MEM_callocN(sizeof(ListBase), "items_list"); LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & NODE_SELECT) { - bNodeListItem *nli = MEM_mallocN(sizeof(bNodeListItem), "temporary node list item"); + bNodeListItem *nli = (bNodeListItem *)MEM_mallocN(sizeof(bNodeListItem), + "temporary node list item"); nli->node = node; BLI_addtail(nodelist, nli); } @@ -522,7 +538,7 @@ static void snode_autoconnect(Main *bmain, LISTBASE_FOREACH (bNodeListItem *, nli, nodelist) { bool has_selected_inputs = false; - if (nli->next == NULL) { + if (nli->next == nullptr) { break; } @@ -536,7 +552,7 @@ static void snode_autoconnect(Main *bmain, /* if there are selected sockets, connect those */ LISTBASE_FOREACH (bNodeSocket *, sock_to, &node_to->inputs) { if (sock_to->flag & SELECT) { - has_selected_inputs = 1; + has_selected_inputs = true; if (!socket_is_available(ntree, sock_to, replace)) { continue; @@ -588,24 +604,28 @@ static void snode_autoconnect(Main *bmain, MEM_freeN(nodelist); } -/* *************************** link viewer op ******************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Link Viewer Operator + * \{ */ static int node_link_viewer(const bContext *C, bNode *tonode) { SpaceNode *snode = CTX_wm_space_node(C); /* context check */ - if (tonode == NULL || BLI_listbase_is_empty(&tonode->outputs)) { + if (tonode == nullptr || BLI_listbase_is_empty(&tonode->outputs)) { return OPERATOR_CANCELLED; } - if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) { return OPERATOR_CANCELLED; } /* get viewer */ - bNode *viewer_node = NULL; + bNode *viewer_node = nullptr; LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { - if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) { if (node->flag & NODE_DO_OUTPUT) { viewer_node = node; break; @@ -613,9 +633,9 @@ static int node_link_viewer(const bContext *C, bNode *tonode) } } /* no viewer, we make one active */ - if (viewer_node == NULL) { + if (viewer_node == nullptr) { LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { - if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) { node->flag |= NODE_DO_OUTPUT; viewer_node = node; break; @@ -623,14 +643,14 @@ static int node_link_viewer(const bContext *C, bNode *tonode) } } - bNodeSocket *sock = NULL; - bNodeLink *link = NULL; + bNodeSocket *sock = nullptr; + bNodeLink *link = nullptr; /* try to find an already connected socket to cycle to the next */ if (viewer_node) { - link = NULL; + link = nullptr; - for (link = snode->edittree->links.first; link; link = link->next) { + for (link = (bNodeLink *)snode->edittree->links.first; link; link = link->next) { if (link->tonode == viewer_node && link->fromnode == tonode) { if (link->tosock == viewer_node->inputs.first) { break; @@ -663,7 +683,7 @@ static int node_link_viewer(const bContext *C, bNode *tonode) /* find a socket starting from the first socket */ if (!sock) { - for (sock = tonode->outputs.first; sock; sock = sock->next) { + for (sock = (bNodeSocket *)tonode->outputs.first; sock; sock = sock->next) { if (!nodeSocketIsHidden(sock)) { break; } @@ -674,24 +694,26 @@ static int node_link_viewer(const bContext *C, bNode *tonode) /* add a new viewer if none exists yet */ if (!viewer_node) { /* XXX location is a quick hack, just place it next to the linked socket */ - viewer_node = node_add_node(C, NULL, CMP_NODE_VIEWER, sock->locx + 100, sock->locy); + const int viewer_type = ED_node_is_compositor(snode) ? CMP_NODE_VIEWER : GEO_NODE_VIEWER; + viewer_node = node_add_node(C, nullptr, viewer_type, sock->locx + 100, sock->locy); if (!viewer_node) { return OPERATOR_CANCELLED; } - link = NULL; + link = nullptr; } else { /* get link to viewer */ - for (link = snode->edittree->links.first; link; link = link->next) { + for (link = (bNodeLink *)snode->edittree->links.first; link; link = link->next) { if (link->tonode == viewer_node && link->tosock == viewer_node->inputs.first) { break; } } } - if (link == NULL) { - nodeAddLink(snode->edittree, tonode, sock, viewer_node, viewer_node->inputs.first); + if (link == nullptr) { + nodeAddLink( + snode->edittree, tonode, sock, viewer_node, (bNodeSocket *)viewer_node->inputs.first); } else { link->fromnode = tonode; @@ -699,8 +721,13 @@ static int node_link_viewer(const bContext *C, bNode *tonode) /* make sure the dependency sorting is updated */ snode->edittree->update |= NTREE_UPDATE_LINKS; } + if (ED_node_is_geometry(snode)) { + ED_spreadsheet_context_paths_set_geometry_node(CTX_data_main(C), snode, viewer_node); + } + ntreeUpdateTree(CTX_data_main(C), snode->edittree); snode_update(snode, viewer_node); + DEG_id_tag_update(&snode->edittree->id, 0); } return OPERATOR_FINISHED; @@ -726,6 +753,15 @@ static int node_active_link_viewer_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +static bool node_active_link_viewer_poll(bContext *C) +{ + if (!ED_operator_node_editable(C)) { + return false; + } + SpaceNode *snode = CTX_wm_space_node(C); + return ED_node_is_compositor(snode) || ED_node_is_geometry(snode); +} + void NODE_OT_link_viewer(wmOperatorType *ot) { /* identifiers */ @@ -735,13 +771,17 @@ void NODE_OT_link_viewer(wmOperatorType *ot) /* api callbacks */ ot->exec = node_active_link_viewer_exec; - ot->poll = composite_node_editable; + ot->poll = node_active_link_viewer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* *************************** add link op ******************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Link Operator + * \{ */ static void node_link_update_header(bContext *C, bNodeLinkDrag *UNUSED(nldrag)) { @@ -779,7 +819,7 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link) if (tlink && tlink->fromsock == from) { if (from_count > from_link_limit) { nodeRemLink(ntree, tlink); - tlink = NULL; + tlink = nullptr; from_count--; } } @@ -787,13 +827,13 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link) if (tlink && tlink->tosock == to) { if (to_count > to_link_limit) { nodeRemLink(ntree, tlink); - tlink = NULL; + tlink = nullptr; to_count--; } else if (tlink->fromsock == from) { /* Also remove link if it comes from the same output. */ nodeRemLink(ntree, tlink); - tlink = NULL; + tlink = nullptr; to_count--; from_count--; } @@ -806,13 +846,13 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links) Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; - bNodeLinkDrag *nldrag = op->customdata; + bNodeLinkDrag *nldrag = (bNodeLinkDrag *)op->customdata; bool do_tag_update = false; /* avoid updates while applying links */ ntree->is_updating = true; LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { - bNodeLink *link = linkdata->data; + bNodeLink *link = (bNodeLink *)linkdata->data; /* See note below, but basically TEST flag means that the link * was connected to output (or to a node which affects the @@ -867,14 +907,14 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links) static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2]) { SpaceNode *snode = CTX_wm_space_node(C); - bNodeLinkDrag *nldrag = op->customdata; + bNodeLinkDrag *nldrag = (bNodeLinkDrag *)op->customdata; if (nldrag->in_out == SOCK_OUT) { bNode *tnode; - bNodeSocket *tsock = NULL; + bNodeSocket *tsock = nullptr; if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_IN)) { LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { - bNodeLink *link = linkdata->data; + bNodeLink *link = (bNodeLink *)linkdata->data; /* skip if socket is on the same node as the fromsock */ if (tnode && link->fromnode == tnode) { @@ -882,7 +922,7 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2]) } /* Skip if tsock is already linked with this output. */ - bNodeLink *existing_link_connected_to_fromsock = NULL; + bNodeLink *existing_link_connected_to_fromsock = nullptr; LISTBASE_FOREACH (bNodeLink *, existing_link, &snode->edittree->links) { if (existing_link->fromsock == link->fromsock && existing_link->tosock == tsock) { existing_link_connected_to_fromsock = existing_link; @@ -906,22 +946,22 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2]) } else { LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { - bNodeLink *link = linkdata->data; + bNodeLink *link = (bNodeLink *)linkdata->data; if (nldrag->last_node_hovered_while_dragging_a_link) { sort_multi_input_socket_links( - snode, nldrag->last_node_hovered_while_dragging_a_link, NULL, cursor); + snode, nldrag->last_node_hovered_while_dragging_a_link, nullptr, cursor); } - link->tonode = NULL; - link->tosock = NULL; + link->tonode = nullptr; + link->tosock = nullptr; } } } else { bNode *tnode; - bNodeSocket *tsock = NULL; + bNodeSocket *tsock = nullptr; if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_OUT)) { LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { - bNodeLink *link = linkdata->data; + bNodeLink *link = (bNodeLink *)linkdata->data; /* skip if this is already the target socket */ if (link->fromsock == tsock) { @@ -939,10 +979,10 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2]) } else { LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { - bNodeLink *link = linkdata->data; + bNodeLink *link = (bNodeLink *)linkdata->data; - link->fromnode = NULL; - link->fromsock = NULL; + link->fromnode = nullptr; + link->fromsock = nullptr; } } } @@ -952,10 +992,12 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2]) /* in_out = starting socket */ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) { - bNodeLinkDrag *nldrag = op->customdata; + bNodeLinkDrag *nldrag = (bNodeLinkDrag *)op->customdata; ARegion *region = CTX_wm_region(C); float cursor[2]; + UI_view2d_edge_pan_apply_event(C, &nldrag->pan_data, event); + UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]); switch (event->type) { @@ -977,7 +1019,7 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) if (event->val == KM_RELEASE) { node_link_exit(C, op, true); - ED_workspace_status_text(C, NULL); + ED_workspace_status_text(C, nullptr); ED_region_tag_redraw(region); SpaceNode *snode = CTX_wm_space_node(C); clear_picking_highlight(&snode->edittree->links); @@ -993,13 +1035,13 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) /* return 1 when socket clicked */ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor[2], bool detach) { - bNodeLinkDrag *nldrag = NULL; + bNodeLinkDrag *nldrag = nullptr; /* output indicated? */ bNode *node; bNodeSocket *sock; if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) { - nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata"); + nldrag = (bNodeLinkDrag *)MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata"); const int num_links = nodeCountSocketLinks(snode->edittree, sock); int link_limit = nodeSocketLinkLimit(sock); @@ -1009,11 +1051,11 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor /* detach current links and store them in the operator data */ LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &snode->edittree->links) { if (link->fromsock == sock) { - LinkData *linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data"); - bNodeLink *oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); + LinkData *linkdata = (LinkData *)MEM_callocN(sizeof(LinkData), "drag link op link data"); + bNodeLink *oplink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "drag link op link"); linkdata->data = oplink; *oplink = *link; - oplink->next = oplink->prev = NULL; + oplink->next = oplink->prev = nullptr; oplink->flag |= NODE_LINK_VALID; /* The link could be disconnected and in that case we @@ -1043,7 +1085,7 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor } /* or an input? */ else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) { - nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata"); + nldrag = (bNodeLinkDrag *)MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata"); nldrag->last_node_hovered_while_dragging_a_link = node; const int num_links = nodeCountSocketLinks(snode->edittree, sock); @@ -1061,12 +1103,12 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor } } - 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"); + if (link_to_pick != nullptr && !nldrag->from_multi_input_socket) { + LinkData *linkdata = (LinkData *)MEM_callocN(sizeof(LinkData), "drag link op link data"); + bNodeLink *oplink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "drag link op link"); linkdata->data = oplink; *oplink = *link_to_pick; - oplink->next = oplink->prev = NULL; + oplink->next = oplink->prev = nullptr; oplink->flag |= NODE_LINK_VALID; oplink->flag &= ~NODE_LINK_TEST; if (node_connected_to_output(bmain, snode->edittree, link_to_pick->tonode)) { @@ -1113,6 +1155,8 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) bNodeLinkDrag *nldrag = node_link_init(bmain, snode, cursor, detach); if (nldrag) { + UI_view2d_edge_pan_operator_init(C, &nldrag->pan_data, op); + op->customdata = nldrag; BLI_addtail(&snode->runtime->linkdrag, nldrag); @@ -1127,7 +1171,7 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) static void node_link_cancel(bContext *C, wmOperator *op) { SpaceNode *snode = CTX_wm_space_node(C); - bNodeLinkDrag *nldrag = op->customdata; + bNodeLinkDrag *nldrag = (bNodeLinkDrag *)op->customdata; BLI_remlink(&snode->runtime->linkdrag, nldrag); @@ -1167,7 +1211,7 @@ void NODE_OT_link(wmOperatorType *ot) RNA_def_float_array(ot->srna, "drag_start", 2, - 0, + nullptr, -UI_PRECISION_FLOAT_MAX, UI_PRECISION_FLOAT_MAX, "Drag Start", @@ -1176,9 +1220,20 @@ void NODE_OT_link(wmOperatorType *ot) UI_PRECISION_FLOAT_MAX); RNA_def_property_flag(prop, PROP_HIDDEN); RNA_def_property_flag(prop, PROP_HIDDEN); + + UI_view2d_edge_pan_operator_properties_ex(ot, + NODE_EDGE_PAN_INSIDE_PAD, + NODE_EDGE_PAN_OUTSIDE_PAD, + NODE_EDGE_PAN_SPEED_RAMP, + NODE_EDGE_PAN_MAX_SPEED, + NODE_EDGE_PAN_DELAY); } -/* ********************** Make Link operator ***************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Make Link Operator + * \{ */ /* makes a link between selected output and input sockets */ static int node_make_link_exec(bContext *C, wmOperator *op) @@ -1189,11 +1244,11 @@ static int node_make_link_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), bmain); - snode_autoconnect(bmain, snode, 1, replace); + snode_autoconnect(bmain, snode, true, replace); /* deselect sockets after linking */ - node_deselect_all_input_sockets(snode, 0); - node_deselect_all_output_sockets(snode, 0); + node_deselect_all_input_sockets(snode, false); + node_deselect_all_output_sockets(snode, false); ntreeUpdateTree(CTX_data_main(C), snode->edittree); snode_notify(C, snode); @@ -1218,27 +1273,37 @@ void NODE_OT_link_make(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean( - ot->srna, "replace", 0, "Replace", "Replace socket connections with the new links"); + ot->srna, "replace", false, "Replace", "Replace socket connections with the new links"); } -/* ********************** Node Link Intersect ***************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Node Link Intersect + * \{ */ + static bool node_links_intersect(bNodeLink *link, const float mcoords[][2], int tot) { float coord_array[NODE_LINK_RESOL + 1][2]; - if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) { + if (node_link_bezier_points(nullptr, nullptr, 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) { - return 1; + return true; } } } } - return 0; + return false; } -/* ********************** Cut Link operator ***************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cut Link Operator + * \{ */ + static int cut_links_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -1285,7 +1350,7 @@ static int cut_links_exec(bContext *C, wmOperator *op) snode_update(snode, link->tonode); bNode *to_node = link->tonode; nodeRemLink(snode->edittree, link); - sort_multi_input_socket_links(snode, to_node, NULL, NULL); + sort_multi_input_socket_links(snode, to_node, nullptr, nullptr); } } @@ -1324,13 +1389,17 @@ void NODE_OT_links_cut(wmOperatorType *ot) /* properties */ PropertyRNA *prop; prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); /* internal */ RNA_def_int(ot->srna, "cursor", WM_CURSOR_KNIFE, 0, INT_MAX, "Cursor", "", 0, INT_MAX); } -/* ********************** Mute links operator ***************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mute Links Operator + * \{ */ static int mute_links_exec(bContext *C, wmOperator *op) { @@ -1426,13 +1495,17 @@ void NODE_OT_links_mute(wmOperatorType *ot) /* properties */ PropertyRNA *prop; prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); /* internal */ RNA_def_int(ot->srna, "cursor", WM_CURSOR_MUTE, 0, INT_MAX, "Cursor", "", 0, INT_MAX); } -/* ********************** Detach links operator ***************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Detach Links Operator + * \{ */ static int detach_links_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1469,7 +1542,11 @@ void NODE_OT_links_detach(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ****************** Set Parent ******************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Parent Operator + * \{ */ static int node_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1491,7 +1568,7 @@ static int node_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) } ED_node_sort(ntree); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; } @@ -1511,7 +1588,11 @@ void NODE_OT_parent_set(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ****************** Join Nodes ******************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Join Nodes Operator + * \{ */ /* tags for depth-first search */ #define NODE_JOIN_DONE 1 @@ -1563,7 +1644,7 @@ static int node_join_exec(bContext *C, wmOperator *UNUSED(op)) } } - bNode *frame = node_add_node(C, NULL, NODE_FRAME, 0.0f, 0.0f); + bNode *frame = node_add_node(C, nullptr, NODE_FRAME, 0.0f, 0.0f); /* reset tags */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { @@ -1584,7 +1665,7 @@ static int node_join_exec(bContext *C, wmOperator *UNUSED(op)) } ED_node_sort(ntree); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; } @@ -1604,7 +1685,11 @@ void NODE_OT_join(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ****************** Attach ******************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Attach Operator + * \{ */ static bNode *node_find_frame_to_attach(ARegion *region, const bNodeTree *ntree, @@ -1624,7 +1709,7 @@ static bNode *node_find_frame_to_attach(ARegion *region, } } - return NULL; + return nullptr; } static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) @@ -1637,7 +1722,7 @@ static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent if (frame) { LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree->nodes) { if (node->flag & NODE_SELECT) { - if (node->parent == NULL) { + if (node->parent == nullptr) { /* disallow moving a parent into its child */ if (nodeAttachNodeCheck(frame, node) == false) { /* attach all unparented nodes */ @@ -1666,7 +1751,7 @@ static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent } ED_node_sort(ntree); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; } @@ -1687,7 +1772,11 @@ void NODE_OT_attach(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ****************** Detach ******************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Detach Operator + * \{ */ /* tags for depth-first search */ #define NODE_DETACH_DONE 1 @@ -1738,7 +1827,7 @@ static int node_detach_exec(bContext *C, wmOperator *UNUSED(op)) } ED_node_sort(ntree); - WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; } @@ -1758,7 +1847,11 @@ void NODE_OT_detach(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************* automatic node insert on dragging ******************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Automatic Node Insert on Dragging + * \{ */ /* prevent duplicate testing code below */ static bool ed_node_link_conditions(ScrArea *area, @@ -1766,13 +1859,13 @@ static bool ed_node_link_conditions(ScrArea *area, SpaceNode **r_snode, bNode **r_select) { - SpaceNode *snode = area ? area->spacedata.first : NULL; + SpaceNode *snode = area ? (SpaceNode *)area->spacedata.first : nullptr; *r_snode = snode; - *r_select = NULL; + *r_select = nullptr; /* no unlucky accidents */ - if (area == NULL || area->spacetype != SPACE_NODE) { + if (area == nullptr || area->spacetype != SPACE_NODE) { return false; } @@ -1782,8 +1875,8 @@ static bool ed_node_link_conditions(ScrArea *area, } bNode *node; - bNode *select = NULL; - for (node = snode->edittree->nodes.first; node; node = node->next) { + bNode *select = nullptr; + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { if (node->flag & SELECT) { if (select) { break; @@ -1792,7 +1885,7 @@ static bool ed_node_link_conditions(ScrArea *area, } } /* only one selected */ - if (node || select == NULL) { + if (node || select == nullptr) { return false; } @@ -1835,7 +1928,7 @@ void ED_node_link_intersect_test(ScrArea *area, int test) } /* find link to select/highlight */ - bNodeLink *selink = NULL; + bNodeLink *selink = nullptr; float dist_best = FLT_MAX; LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { float coord_array[NODE_LINK_RESOL + 1][2]; @@ -1844,7 +1937,7 @@ void ED_node_link_intersect_test(ScrArea *area, int test) continue; } - if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) { + if (node_link_bezier_points(nullptr, nullptr, link, coord_array, NODE_LINK_RESOL)) { float dist = FLT_MAX; /* loop over link coords to find shortest dist to @@ -1876,6 +1969,12 @@ void ED_node_link_intersect_test(ScrArea *area, int test) } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Node Insert Offset Operator + * \{ */ + static int get_main_socket_priority(const bNodeSocket *socket) { switch ((eNodeSocketDatatype)socket->type) { @@ -1939,7 +2038,7 @@ static bNodeSocket *get_main_socket(ListBase *sockets) } } - return NULL; + return nullptr; } static bool node_parents_offset_flag_enable_cb(bNode *parent, void *UNUSED(userdata)) @@ -1977,7 +2076,7 @@ static void node_parent_offset_apply(NodeInsertOfsData *data, bNode *parent, con #define NODE_INSOFS_ANIM_DURATION 0.25f /** - * Callback that applies NodeInsertOfsData.offset_x to a node or its parent, similar + * Callback that applies #NodeInsertOfsData.offset_x to a node or its parent, similar * to node_link_insert_offset_output_chain_cb below, but with slightly different logic */ static bool node_link_insert_offset_frame_chain_cb(bNode *fromnode, @@ -1985,7 +2084,7 @@ static bool node_link_insert_offset_frame_chain_cb(bNode *fromnode, void *userdata, const bool reversed) { - NodeInsertOfsData *data = userdata; + NodeInsertOfsData *data = (NodeInsertOfsData *)userdata; bNode *ofs_node = reversed ? fromnode : tonode; if (ofs_node->parent && ofs_node->parent != data->insert_parent) { @@ -2022,7 +2121,7 @@ static bool node_link_insert_offset_chain_cb(bNode *fromnode, void *userdata, const bool reversed) { - NodeInsertOfsData *data = userdata; + NodeInsertOfsData *data = (NodeInsertOfsData *)userdata; bNode *ofs_node = reversed ? fromnode : tonode; if (data->insert_parent) { @@ -2035,7 +2134,7 @@ static bool node_link_insert_offset_chain_cb(bNode *fromnode, } if (nodeIsChildOf(data->insert_parent, ofs_node) == false) { - data->insert_parent = NULL; + data->insert_parent = nullptr; } } else if (ofs_node->parent) { @@ -2086,7 +2185,7 @@ static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd, rctf totr_frame; /* check nodes front to back */ - for (frame = ntree->nodes.last; frame; frame = frame->prev) { + for (frame = (bNode *)ntree->nodes.last; frame; frame = frame->prev) { /* skip selected, those are the nodes we want to attach */ if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT)) { continue; @@ -2152,7 +2251,7 @@ static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd, iofsd->offset_x = margin; /* flag all parents of insert as offset to prevent them from being offset */ - nodeParentsIter(insert, node_parents_offset_flag_enable_cb, NULL); + nodeParentsIter(insert, node_parents_offset_flag_enable_cb, nullptr); /* iterate over entire chain and apply offsets */ nodeChainIter(ntree, right_alignment ? next : prev, @@ -2173,7 +2272,8 @@ static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const w NodeInsertOfsData *iofsd = snode->runtime->iofsd; bool redraw = false; - if (!snode || event->type != TIMER || iofsd == NULL || iofsd->anim_timer != event->customdata) { + if (!snode || event->type != TIMER || iofsd == nullptr || + iofsd->anim_timer != event->customdata) { return OPERATOR_PASS_THROUGH; } @@ -2203,13 +2303,13 @@ static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const w /* end timer + free insert offset data */ if (duration > NODE_INSOFS_ANIM_DURATION) { - WM_event_remove_timer(CTX_wm_manager(C), NULL, iofsd->anim_timer); + WM_event_remove_timer(CTX_wm_manager(C), nullptr, iofsd->anim_timer); LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { node->anim_init_locx = node->anim_ofsx = 0.0f; } - snode->runtime->iofsd = NULL; + snode->runtime->iofsd = nullptr; MEM_freeN(iofsd); return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); @@ -2259,6 +2359,12 @@ void NODE_OT_insert_offset(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Note Link Insert + * \{ */ + /* assumes link with NODE_LINKFLAG_HILITE set */ void ED_node_link_insert(Main *bmain, ScrArea *area) { @@ -2270,7 +2376,7 @@ void ED_node_link_insert(Main *bmain, ScrArea *area) /* get the link */ bNodeLink *link; - for (link = snode->edittree->links.first; link; link = link->next) { + for (link = (bNodeLink *)snode->edittree->links.first; link; link = link->next) { if (link->flag & NODE_LINKFLAG_HILITE) { break; } @@ -2298,7 +2404,8 @@ void ED_node_link_insert(Main *bmain, ScrArea *area) /* set up insert offset data, it needs stuff from here */ if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) { - NodeInsertOfsData *iofsd = MEM_callocN(sizeof(NodeInsertOfsData), __func__); + NodeInsertOfsData *iofsd = (NodeInsertOfsData *)MEM_callocN(sizeof(NodeInsertOfsData), + __func__); iofsd->insert = select; iofsd->prev = link->fromnode; @@ -2314,3 +2421,5 @@ void ED_node_link_insert(Main *bmain, ScrArea *area) } } } + +/** \} */ diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.cc index de63aa07acb..a081cc83481 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.cc @@ -21,7 +21,8 @@ * \ingroup spnode */ -#include <stdlib.h> +#include <array> +#include <cstdlib> #include "DNA_node_types.h" #include "DNA_windowmanager_types.h" @@ -43,6 +44,7 @@ #include "ED_node.h" /* own include */ #include "ED_screen.h" #include "ED_select_utils.h" +#include "ED_spreadsheet.h" #include "ED_view3d.h" #include "RNA_access.h" @@ -81,7 +83,7 @@ static bool has_workbench_in_texture_color(const wmWindowManager *wm, const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { if (area->spacetype == SPACE_VIEW3D) { - const View3D *v3d = area->spacedata.first; + const View3D *v3d = (const View3D *)area->spacedata.first; if (ED_view3d_has_workbench_in_texture_color(scene, ob, v3d)) { return true; @@ -100,28 +102,28 @@ static bNode *node_under_mouse_select(bNodeTree *ntree, int mx, int my) { bNode *node; - for (node = ntree->nodes.last; node; node = node->prev) { + for (node = (bNode *)ntree->nodes.last; node; node = node->prev) { if (node->typeinfo->select_area_func) { if (node->typeinfo->select_area_func(node, mx, my)) { return node; } } } - return NULL; + return nullptr; } static bNode *node_under_mouse_tweak(bNodeTree *ntree, int mx, int my) { bNode *node; - for (node = ntree->nodes.last; node; node = node->prev) { + for (node = (bNode *)ntree->nodes.last; node; node = node->prev) { if (node->typeinfo->tweak_area_func) { if (node->typeinfo->tweak_area_func(node, mx, my)) { return node; } } } - return NULL; + return nullptr; } static bool is_position_over_node_or_socket(SpaceNode *snode, float mouse[2]) @@ -168,18 +170,18 @@ void node_socket_deselect(bNode *node, bNodeSocket *sock, const bool deselect_no sock->flag &= ~SELECT; if (node && deselect_node) { - bool sel = 0; + bool sel = false; /* if no selected sockets remain, also deselect the node */ - for (sock = node->inputs.first; sock; sock = sock->next) { + for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) { if (sock->flag & SELECT) { - sel = 1; + sel = true; break; } } - for (sock = node->outputs.first; sock; sock = sock->next) { + for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) { if (sock->flag & SELECT) { - sel = 1; + sel = true; break; } } @@ -205,7 +207,7 @@ void node_deselect_all(SpaceNode *snode) { bNode *node; - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { nodeSetSelected(node, false); } } @@ -220,16 +222,16 @@ void node_deselect_all_input_sockets(SpaceNode *snode, const bool deselect_nodes * We can do that more efficiently here. */ - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { int sel = 0; - for (sock = node->inputs.first; sock; sock = sock->next) { + for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) { sock->flag &= ~SELECT; } /* if no selected sockets remain, also deselect the node */ if (deselect_nodes) { - for (sock = node->outputs.first; sock; sock = sock->next) { + for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) { if (sock->flag & SELECT) { sel = 1; break; @@ -253,18 +255,18 @@ void node_deselect_all_output_sockets(SpaceNode *snode, const bool deselect_node * We can do that more efficiently here. */ - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { bool sel = false; - for (sock = node->outputs.first; sock; sock = sock->next) { + for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) { sock->flag &= ~SELECT; } /* if no selected sockets remain, also deselect the node */ if (deselect_nodes) { - for (sock = node->inputs.first; sock; sock = sock->next) { + for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) { if (sock->flag & SELECT) { - sel = 1; + sel = true; break; } } @@ -289,7 +291,7 @@ static bool node_select_grouped_type(SpaceNode *snode, bNode *node_act) bNode *node; bool changed = false; - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { if ((node->flag & SELECT) == 0) { if (node->type == node_act->type) { nodeSetSelected(node, true); @@ -306,7 +308,7 @@ static bool node_select_grouped_color(SpaceNode *snode, bNode *node_act) bNode *node; bool changed = false; - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { if ((node->flag & SELECT) == 0) { if (compare_v3v3(node->color, node_act->color, 0.005f)) { nodeSetSelected(node, true); @@ -327,20 +329,20 @@ static bool node_select_grouped_name(SpaceNode *snode, bNode *node_act, const bo const char *sep, *suf_act, *suf_curr; pref_len_act = BLI_str_partition_ex_utf8( - node_act->name, NULL, delims, &sep, &suf_act, from_right); + node_act->name, nullptr, delims, &sep, &suf_act, from_right); - /* Note: in case we are searching for suffix, and found none, use whole name as suffix. */ + /* NOTE: in case we are searching for suffix, and found none, use whole name as suffix. */ if (from_right && !(sep && suf_act)) { pref_len_act = 0; suf_act = node_act->name; } - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { if (node->flag & SELECT) { continue; } pref_len_curr = BLI_str_partition_ex_utf8( - node->name, NULL, delims, &sep, &suf_curr, from_right); + node->name, nullptr, delims, &sep, &suf_curr, from_right); /* Same as with active node name! */ if (from_right && !(sep && suf_curr)) { @@ -371,7 +373,7 @@ static int node_select_grouped_exec(bContext *C, wmOperator *op) SpaceNode *snode = CTX_wm_space_node(C); bNode *node_act = nodeGetActive(snode->edittree); - if (node_act == NULL) { + if (node_act == nullptr) { return OPERATOR_CANCELLED; } @@ -381,7 +383,7 @@ static int node_select_grouped_exec(bContext *C, wmOperator *op) const int type = RNA_enum_get(op->ptr, "type"); if (!extend) { - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { nodeSetSelected(node, false); } } @@ -406,7 +408,7 @@ static int node_select_grouped_exec(bContext *C, wmOperator *op) if (changed) { ED_node_sort(snode->edittree); - WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); return OPERATOR_FINISHED; } @@ -420,7 +422,7 @@ void NODE_OT_select_grouped(wmOperatorType *ot) {NODE_SELECT_GROUPED_COLOR, "COLOR", 0, "Color", ""}, {NODE_SELECT_GROUPED_PREFIX, "PREFIX", 0, "Prefix", ""}, {NODE_SELECT_GROUPED_SUFIX, "SUFFIX", 0, "Suffix", ""}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; /* identifiers */ @@ -461,14 +463,14 @@ void node_select_single(bContext *C, bNode *node) bool active_texture_changed = false; bNode *tnode; - for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) { + for (tnode = (bNode *)snode->edittree->nodes.first; tnode; tnode = tnode->next) { if (tnode != node) { nodeSetSelected(tnode, false); } } nodeSetSelected(node, true); - ED_node_set_active(bmain, snode->edittree, node, &active_texture_changed); + ED_node_set_active(bmain, snode, snode->edittree, node, &active_texture_changed); ED_node_set_active_viewer_key(snode); ED_node_sort(snode->edittree); @@ -476,7 +478,7 @@ void node_select_single(bContext *C, bNode *node) DEG_id_tag_update(&snode->edittree->id, ID_RECALC_COPY_ON_WRITE); } - WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); } static int node_mouse_select(bContext *C, @@ -491,7 +493,7 @@ static int node_mouse_select(bContext *C, const Scene *scene = CTX_data_scene(C); const wmWindowManager *wm = CTX_wm_manager(C); bNode *node, *tnode; - bNodeSocket *sock = NULL; + bNodeSocket *sock = nullptr; bNodeSocket *tsock; float cursor[2]; int ret_value = OPERATOR_CANCELLED; @@ -530,7 +532,7 @@ static int node_mouse_select(bContext *C, /* Only allow one selected output per node, for sensible linking. * Allow selecting outputs from different nodes though, if extend is true. */ if (node) { - for (tsock = node->outputs.first; tsock; tsock = tsock->next) { + for (tsock = (bNodeSocket *)node->outputs.first; tsock; tsock = tsock->next) { if (tsock == sock) { continue; } @@ -538,11 +540,11 @@ static int node_mouse_select(bContext *C, } } if (!extend) { - for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) { + for (tnode = (bNode *)snode->edittree->nodes.first; tnode; tnode = tnode->next) { if (tnode == node) { continue; } - for (tsock = tnode->outputs.first; tsock; tsock = tsock->next) { + for (tsock = (bNodeSocket *)tnode->outputs.first; tsock; tsock = tsock->next) { node_socket_deselect(tnode, tsock, true); } } @@ -558,7 +560,7 @@ static int node_mouse_select(bContext *C, node = node_under_mouse_select(snode->edittree, (int)cursor[0], (int)cursor[1]); if (extend) { - if (node != NULL) { + if (node != nullptr) { /* If node is selected but not active, we want to make it active, * but not toggle (deselect) it. */ if (!((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0)) { @@ -567,7 +569,7 @@ static int node_mouse_select(bContext *C, ret_value = OPERATOR_FINISHED; } } - else if (deselect_all && node == NULL) { + else if (deselect_all && node == nullptr) { /* Rather than deselecting others, users may want to drag to box-select (drag from empty * space) or tweak-translate an already selected item. If these cases may apply, delay * deselection. */ @@ -576,13 +578,13 @@ static int node_mouse_select(bContext *C, } else { /* Deselect in empty space. */ - for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) { + for (tnode = (bNode *)snode->edittree->nodes.first; tnode; tnode = tnode->next) { nodeSetSelected(tnode, false); } ret_value = OPERATOR_FINISHED; } } - else if (node != NULL) { + else if (node != nullptr) { /* When clicking on an already selected node, we want to wait to deselect * others and allow the user to start moving the node without that. */ if (wait_to_deselect_others && (node->flag & SELECT)) { @@ -591,7 +593,7 @@ static int node_mouse_select(bContext *C, else { nodeSetSelected(node, true); - for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) { + for (tnode = (bNode *)snode->edittree->nodes.first; tnode; tnode = tnode->next) { if (tnode != node) { nodeSetSelected(tnode, false); } @@ -605,16 +607,22 @@ static int node_mouse_select(bContext *C, /* update node order */ if (ret_value != OPERATOR_CANCELLED) { bool active_texture_changed = false; - if (node != NULL && ret_value != OPERATOR_RUNNING_MODAL) { - ED_node_set_active(bmain, snode->edittree, node, &active_texture_changed); + bool viewer_node_changed = false; + if (node != nullptr && ret_value != OPERATOR_RUNNING_MODAL) { + viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER; + ED_node_set_active(bmain, snode, snode->edittree, node, &active_texture_changed); + } + else if (node != nullptr && node->type == GEO_NODE_VIEWER) { + ED_spreadsheet_context_paths_set_geometry_node(bmain, snode, node); } ED_node_set_active_viewer_key(snode); ED_node_sort(snode->edittree); - if (active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) { + if ((active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) || + viewer_node_changed) { DEG_id_tag_update(&snode->edittree->id, ID_RECALC_COPY_ON_WRITE); } - WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); } return ret_value; @@ -681,7 +689,7 @@ static int node_box_select_exec(bContext *C, wmOperator *op) WM_operator_properties_border_to_rctf(op, &rectf); UI_view2d_region_to_view_rctf(®ion->v2d, &rectf, &rectf); - const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); + const eSelectOp sel_op = (eSelectOp)RNA_enum_get(op->ptr, "mode"); const bool select = (sel_op != SEL_OP_SUB); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { ED_node_select_all(&snode->edittree->nodes, SEL_DESELECT); @@ -693,7 +701,7 @@ static int node_box_select_exec(bContext *C, wmOperator *op) is_inside = BLI_rctf_inside_rctf(&rectf, &node->totr); } else { - is_inside = BLI_rctf_isect(&rectf, &node->totr, NULL); + is_inside = BLI_rctf_isect(&rectf, &node->totr, nullptr); } if (is_inside) { @@ -703,7 +711,7 @@ static int node_box_select_exec(bContext *C, wmOperator *op) ED_node_sort(snode->edittree); - WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); return OPERATOR_FINISHED; } @@ -740,7 +748,7 @@ void NODE_OT_select_box(wmOperatorType *ot) /* properties */ RNA_def_boolean(ot->srna, "tweak", - 0, + false, "Tweak", "Only activate when mouse is not over a node (useful for tweak gesture)"); @@ -766,8 +774,9 @@ static int node_circleselect_exec(bContext *C, wmOperator *op) float zoom = (float)(BLI_rcti_size_x(®ion->winrct)) / (float)(BLI_rctf_size_x(®ion->v2d.cur)); - const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"), - WM_gesture_is_modal_first(op->customdata)); + const eSelectOp sel_op = ED_select_op_modal( + (eSelectOp)RNA_enum_get(op->ptr, "mode"), + WM_gesture_is_modal_first((const wmGesture *)op->customdata)); const bool select = (sel_op != SEL_OP_SUB); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { ED_node_select_all(&snode->edittree->nodes, SEL_DESELECT); @@ -780,13 +789,13 @@ static int node_circleselect_exec(bContext *C, wmOperator *op) UI_view2d_region_to_view(®ion->v2d, x, y, &offset[0], &offset[1]); - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { if (BLI_rctf_isect_circle(&node->totr, offset, radius / zoom)) { nodeSetSelected(node, select); } } - WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); return OPERATOR_FINISHED; } @@ -853,7 +862,7 @@ static bool do_lasso_select_node(bContext *C, BLI_lasso_boundbox(&rect, mcoords, mcoords_len); /* do actual selection */ - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { if (select && (node->flag & NODE_SELECT)) { continue; @@ -873,7 +882,7 @@ static bool do_lasso_select_node(bContext *C, } if (changed) { - WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); } return changed; @@ -885,7 +894,7 @@ static int node_lasso_select_exec(bContext *C, wmOperator *op) const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); if (mcoords) { - const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); + const eSelectOp sel_op = (eSelectOp)RNA_enum_get(op->ptr, "mode"); do_lasso_select_node(C, mcoords, mcoords_len, sel_op); @@ -916,7 +925,7 @@ void NODE_OT_select_lasso(wmOperatorType *ot) /* properties */ RNA_def_boolean(ot->srna, "tweak", - 0, + false, "Tweak", "Only activate when mouse is not over a node (useful for tweak gesture)"); @@ -940,7 +949,7 @@ static int node_select_all_exec(bContext *C, wmOperator *op) ED_node_sort(snode->edittree); - WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); return OPERATOR_FINISHED; } @@ -973,11 +982,11 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op)) bNodeLink *link; bNode *node; - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { node->flag &= ~NODE_TEST; } - for (link = snode->edittree->links.first; link; link = link->next) { + for (link = (bNodeLink *)snode->edittree->links.first; link; link = link->next) { if (nodeLinkIsHidden(link)) { continue; } @@ -986,7 +995,7 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op)) } } - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { if (node->flag & NODE_TEST) { nodeSetSelected(node, true); } @@ -994,7 +1003,7 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op)) ED_node_sort(snode->edittree); - WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); return OPERATOR_FINISHED; } @@ -1025,11 +1034,11 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op)) bNodeLink *link; bNode *node; - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { node->flag &= ~NODE_TEST; } - for (link = snode->edittree->links.first; link; link = link->next) { + for (link = (bNodeLink *)snode->edittree->links.first; link; link = link->next) { if (nodeLinkIsHidden(link)) { continue; } @@ -1038,7 +1047,7 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op)) } } - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { if (node->flag & NODE_TEST) { nodeSetSelected(node, true); } @@ -1046,7 +1055,7 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op)) ED_node_sort(snode->edittree); - WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); return OPERATOR_FINISHED; } @@ -1079,7 +1088,7 @@ static int node_select_same_type_step_exec(bContext *C, wmOperator *op) bNode *active = nodeGetActive(snode->edittree); int totnodes; const bool revert = RNA_boolean_get(op->ptr, "prev"); - const bool same_type = 1; + const bool same_type = true; ntreeGetDependencyList(snode->edittree, &node_array, &totnodes); @@ -1093,9 +1102,9 @@ static int node_select_same_type_step_exec(bContext *C, wmOperator *op) } if (same_type) { - bNode *node = NULL; + bNode *node = nullptr; - while (node == NULL) { + while (node == nullptr) { if (revert) { a--; } @@ -1112,7 +1121,7 @@ static int node_select_same_type_step_exec(bContext *C, wmOperator *op) if (node->type == active->type) { break; } - node = NULL; + node = nullptr; } if (node) { active = node; @@ -1168,7 +1177,7 @@ void NODE_OT_select_same_type_step(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "prev", 0, "Previous", ""); + RNA_def_boolean(ot->srna, "prev", false, "Previous", ""); } /** \} */ @@ -1223,7 +1232,7 @@ static void node_find_update_fn(const struct bContext *C, static void node_find_exec_fn(struct bContext *C, void *UNUSED(arg1), void *arg2) { SpaceNode *snode = CTX_wm_space_node(C); - bNode *active = arg2; + bNode *active = (bNode *)arg2; if (active) { ARegion *region = CTX_wm_region(C); @@ -1261,7 +1270,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *region, void *arg_op) 0, ""); UI_but_func_search_set( - but, NULL, node_find_update_fn, op->type, false, NULL, node_find_exec_fn, NULL); + but, nullptr, node_find_update_fn, op->type, false, nullptr, node_find_exec_fn, nullptr); UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); /* fake button, it holds space for search items */ @@ -1273,22 +1282,23 @@ static uiBlock *node_find_menu(bContext *C, ARegion *region, void *arg_op) 10 - UI_searchbox_size_y(), UI_searchbox_size_x(), UI_searchbox_size_y(), - NULL, + nullptr, 0, 0, 0, 0, - NULL); + nullptr); /* Move it downwards, mouse over button. */ - UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, (const int[2]){0, -UI_UNIT_Y}); + std::array<int, 2> bounds_offset = {0, -UI_UNIT_Y}; + UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, bounds_offset.data()); return block; } static int node_find_node_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - UI_popup_block_invoke(C, node_find_menu, op, NULL); + UI_popup_block_invoke(C, node_find_menu, op, nullptr); return OPERATOR_CANCELLED; } @@ -1306,7 +1316,7 @@ void NODE_OT_find_node(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "prev", 0, "Previous", ""); + RNA_def_boolean(ot->srna, "prev", false, "Previous", ""); } /** \} */ diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.cc index c880f3e99d8..cbe33fab64e 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.cc @@ -18,8 +18,8 @@ * \ingroup edinterface */ -#include <stdlib.h> -#include <string.h> +#include <cstdlib> +#include <cstring> #include "MEM_guardedalloc.h" @@ -29,6 +29,7 @@ #include "BLI_array.h" #include "BLI_listbase.h" #include "BLI_string.h" +#include "BLI_vector.hh" #include "BLT_translation.h" @@ -51,7 +52,7 @@ /************************* Node Socket Manipulation **************************/ /* describes an instance of a node type and a specific socket to link */ -typedef struct NodeLinkItem { +struct NodeLinkItem { int socket_index; /* index for linking */ int socket_type; /* socket type for compatibility check */ const char *socket_name; /* ui label of the socket */ @@ -59,7 +60,7 @@ typedef struct NodeLinkItem { /* extra settings */ bNodeTree *ngroup; /* group node tree */ -} NodeLinkItem; +}; /* Compare an existing node to a link item to see if it can be reused. * item must be for the same node type! @@ -98,7 +99,7 @@ static void node_tag_recursive(bNode *node) node->flag |= NODE_TEST; - for (input = node->inputs.first; input; input = input->next) { + for (input = (bNodeSocket *)node->inputs.first; input; input = input->next) { if (input->link) { node_tag_recursive(input->link->fromnode); } @@ -115,7 +116,7 @@ static void node_clear_recursive(bNode *node) node->flag &= ~NODE_TEST; - for (input = node->inputs.first; input; input = input->next) { + for (input = (bNodeSocket *)node->inputs.first; input; input = input->next) { if (input->link) { node_clear_recursive(input->link->fromnode); } @@ -132,16 +133,16 @@ static void node_remove_linked(Main *bmain, bNodeTree *ntree, bNode *rem_node) } /* tag linked nodes to be removed */ - for (node = ntree->nodes.first; node; node = node->next) { + for (node = (bNode *)ntree->nodes.first; node; node = node->next) { node->flag &= ~NODE_TEST; } node_tag_recursive(rem_node); /* clear tags on nodes that are still used by other nodes */ - for (node = ntree->nodes.first; node; node = node->next) { + for (node = (bNode *)ntree->nodes.first; node; node = node->next) { if (!(node->flag & NODE_TEST)) { - for (sock = node->inputs.first; sock; sock = sock->next) { + for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) { if (sock->link && sock->link->fromnode != rem_node) { node_clear_recursive(sock->link->fromnode); } @@ -150,7 +151,7 @@ static void node_remove_linked(Main *bmain, bNodeTree *ntree, bNode *rem_node) } /* remove nodes */ - for (node = ntree->nodes.first; node; node = next) { + for (node = (bNode *)ntree->nodes.first; node; node = next) { next = node->next; if (node->flag & NODE_TEST) { @@ -205,7 +206,7 @@ static void node_socket_add_replace(const bContext *C, Main *bmain = CTX_data_main(C); bNode *node_from; bNodeSocket *sock_from_tmp; - bNode *node_prev = NULL; + bNode *node_prev = nullptr; /* unlink existing node */ if (sock_to->link) { @@ -214,7 +215,7 @@ static void node_socket_add_replace(const bContext *C, } /* find existing node that we can use */ - for (node_from = ntree->nodes.first; node_from; node_from = node_from->next) { + for (node_from = (bNode *)ntree->nodes.first; node_from; node_from = node_from->next) { if (node_from->type == type) { break; } @@ -223,7 +224,7 @@ static void node_socket_add_replace(const bContext *C, if (node_from) { if (node_from->inputs.first || node_from->typeinfo->draw_buttons || node_from->typeinfo->draw_buttons_ex) { - node_from = NULL; + node_from = nullptr; } } @@ -233,7 +234,7 @@ static void node_socket_add_replace(const bContext *C, } else if (!node_from) { node_from = nodeAddStaticNode(C, ntree, type); - if (node_prev != NULL) { + if (node_prev != nullptr) { /* If we're replacing existing node, use its location. */ node_from->locx = node_prev->locx; node_from->locy = node_prev->locy; @@ -241,7 +242,7 @@ static void node_socket_add_replace(const bContext *C, node_from->offsety = node_prev->offsety; } else { - sock_from_tmp = BLI_findlink(&node_from->outputs, item->socket_index); + sock_from_tmp = (bNodeSocket *)BLI_findlink(&node_from->outputs, item->socket_index); nodePositionRelative(node_from, node_to, sock_from_tmp, sock_to); } @@ -251,7 +252,7 @@ static void node_socket_add_replace(const bContext *C, nodeSetActive(ntree, node_from); /* add link */ - sock_from_tmp = BLI_findlink(&node_from->outputs, item->socket_index); + sock_from_tmp = (bNodeSocket *)BLI_findlink(&node_from->outputs, item->socket_index); nodeAddLink(ntree, node_from, sock_from_tmp, node_to, sock_to); sock_to->flag &= ~SOCK_COLLAPSED; @@ -259,8 +260,10 @@ static void node_socket_add_replace(const bContext *C, if (node_prev && node_from != node_prev) { bNodeSocket *sock_prev, *sock_from; - for (sock_prev = node_prev->inputs.first; sock_prev; sock_prev = sock_prev->next) { - for (sock_from = node_from->inputs.first; sock_from; sock_from = sock_from->next) { + for (sock_prev = (bNodeSocket *)node_prev->inputs.first; sock_prev; + sock_prev = sock_prev->next) { + for (sock_from = (bNodeSocket *)node_from->inputs.first; sock_from; + sock_from = sock_from->next) { if (nodeCountSocketLinks(ntree, sock_from) >= nodeSocketLinkLimit(sock_from)) { continue; } @@ -282,7 +285,7 @@ static void node_socket_add_replace(const bContext *C, if (node_from->typeinfo->nclass == NODE_CLASS_TEXTURE && node_prev->typeinfo->nclass == NODE_CLASS_TEXTURE && /* White noise texture node does not have NodeTexBase. */ - node_from->storage != NULL && node_prev->storage != NULL) { + node_from->storage != nullptr && node_prev->storage != nullptr) { memcpy(node_from->storage, node_prev->storage, sizeof(NodeTexBase)); } @@ -303,7 +306,7 @@ static void node_socket_add_replace(const bContext *C, #define UI_NODE_LINK_DISCONNECT -1 #define UI_NODE_LINK_REMOVE -2 -typedef struct NodeLinkArg { +struct NodeLinkArg { Main *bmain; Scene *scene; bNodeTree *ntree; @@ -314,7 +317,7 @@ typedef struct NodeLinkArg { NodeLinkItem item; uiLayout *layout; -} NodeLinkArg; +}; static void ui_node_link_items(NodeLinkArg *arg, int in_out, @@ -322,14 +325,15 @@ static void ui_node_link_items(NodeLinkArg *arg, int *r_totitems) { /* XXX this should become a callback for node types! */ - NodeLinkItem *items = NULL; + NodeLinkItem *items = nullptr; int totitems = 0; if (arg->node_type->type == NODE_GROUP) { bNodeTree *ngroup; int i; - for (ngroup = arg->bmain->nodetrees.first; ngroup; ngroup = ngroup->id.next) { + for (ngroup = (bNodeTree *)arg->bmain->nodetrees.first; ngroup; + ngroup = (bNodeTree *)ngroup->id.next) { const char *disabled_hint; if ((ngroup->type != arg->ntree->type) || !nodeGroupPoll(arg->ntree, ngroup, &disabled_hint)) { @@ -341,10 +345,11 @@ static void ui_node_link_items(NodeLinkArg *arg, } if (totitems > 0) { - items = MEM_callocN(sizeof(NodeLinkItem) * totitems, "ui node link items"); + items = (NodeLinkItem *)MEM_callocN(sizeof(NodeLinkItem) * totitems, "ui node link items"); i = 0; - for (ngroup = arg->bmain->nodetrees.first; ngroup; ngroup = ngroup->id.next) { + for (ngroup = (bNodeTree *)arg->bmain->nodetrees.first; ngroup; + ngroup = (bNodeTree *)ngroup->id.next) { const char *disabled_hint; if ((ngroup->type != arg->ntree->type) || !nodeGroupPoll(arg->ntree, ngroup, &disabled_hint)) { @@ -354,11 +359,12 @@ static void ui_node_link_items(NodeLinkArg *arg, ListBase *lb = (in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs); bNodeSocket *stemp; int index; - for (stemp = lb->first, index = 0; stemp; stemp = stemp->next, index++, i++) { + for (stemp = (bNodeSocket *)lb->first, index = 0; stemp; + stemp = stemp->next, index++, i++) { NodeLinkItem *item = &items[i]; item->socket_index = index; - /* note: int stemp->type is not fully reliable, not used for node group + /* NOTE: int stemp->type is not fully reliable, not used for node group * interface sockets. use the typeinfo->type instead. */ item->socket_type = stemp->typeinfo->type; @@ -380,7 +386,7 @@ static void ui_node_link_items(NodeLinkArg *arg, } if (totitems > 0) { - items = MEM_callocN(sizeof(NodeLinkItem) * totitems, "ui node link items"); + items = (NodeLinkItem *)MEM_callocN(sizeof(NodeLinkItem) * totitems, "ui node link items"); i = 0; for (stemp = socket_templates; stemp && stemp->type != -1; stemp++, i++) { @@ -474,15 +480,14 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) bNodeTree *ntree = arg->ntree; bNodeSocket *sock = arg->sock; uiLayout *layout = arg->layout; - uiLayout *column = NULL; + uiLayout *column = nullptr; uiBlock *block = uiLayoutGetBlock(layout); uiBut *but; NodeLinkArg *argN; int first = 1; /* generate array of node types sorted by UI name */ - bNodeType **sorted_ntypes = NULL; - BLI_array_declare(sorted_ntypes); + blender::Vector<bNodeType *> sorted_ntypes; NODE_TYPES_BEGIN (ntype) { const char *disabled_hint; @@ -498,20 +503,20 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) continue; } - BLI_array_append(sorted_ntypes, ntype); + sorted_ntypes.append(ntype); } NODE_TYPES_END; qsort( - sorted_ntypes, BLI_array_len(sorted_ntypes), sizeof(bNodeType *), ui_node_item_name_compare); + sorted_ntypes.data(), sorted_ntypes.size(), sizeof(bNodeType *), ui_node_item_name_compare); /* generate UI */ - for (int j = 0; j < BLI_array_len(sorted_ntypes); j++) { + for (int j = 0; j < sorted_ntypes.size(); j++) { bNodeType *ntype = sorted_ntypes[j]; NodeLinkItem *items; int totitems; char name[UI_MAX_NAME_STR]; - const char *cur_node_name = NULL; + const char *cur_node_name = nullptr; int num = 0; int icon = ICON_NONE; @@ -531,11 +536,11 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) } if (first) { - column = uiLayoutColumn(layout, 0); + column = uiLayoutColumn(layout, false); UI_block_layout_set_current(block, column); uiItemL(column, IFACE_(cname), ICON_NODE); - but = block->buttons.last; + but = (uiBut *)block->buttons.last; first = 0; } @@ -553,7 +558,7 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) 0, UI_UNIT_X * 4, UI_UNIT_Y, - NULL, + nullptr, 0.0, 0.0, 0.0, @@ -578,24 +583,22 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) 0, UI_UNIT_X * 4, UI_UNIT_Y, - NULL, + nullptr, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input")); - argN = MEM_dupallocN(arg); + argN = (NodeLinkArg *)MEM_dupallocN(arg); argN->item = items[i]; - UI_but_funcN_set(but, ui_node_link, argN, NULL); + UI_but_funcN_set(but, ui_node_link, argN, nullptr); } if (items) { MEM_freeN(items); } } - - BLI_array_free(sorted_ntypes); } static void node_menu_column_foreach_cb(void *calldata, int nclass, const char *name) @@ -635,7 +638,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_ if (sock->link) { uiItemL(column, IFACE_("Link"), ICON_NONE); - but = block->buttons.last; + but = (uiBut *)block->buttons.last; but->drawflag = UI_BUT_TEXT_LEFT; but = uiDefBut(block, @@ -646,7 +649,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_ 0, UI_UNIT_X * 4, UI_UNIT_Y, - NULL, + nullptr, 0.0, 0.0, 0.0, @@ -662,7 +665,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_ 0, UI_UNIT_X * 4, UI_UNIT_Y, - NULL, + nullptr, 0.0, 0.0, 0.0, @@ -683,7 +686,7 @@ void uiTemplateNodeLink( uiBut *but; float socket_col[4]; - arg = MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg"); + arg = (NodeLinkArg *)MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg"); arg->ntree = ntree; arg->node = node; arg->sock = input; @@ -698,11 +701,11 @@ void uiTemplateNodeLink( char name[UI_MAX_NAME_STR]; ui_node_sock_name(ntree, input, name); but = uiDefMenuBut( - block, ui_template_node_link_menu, NULL, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y, ""); + block, ui_template_node_link_menu, nullptr, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y, ""); } else { but = uiDefIconMenuBut( - block, ui_template_node_link_menu, NULL, ICON_NONE, 0, 0, UI_UNIT_X, UI_UNIT_Y, ""); + block, ui_template_node_link_menu, nullptr, ICON_NONE, 0, 0, UI_UNIT_X, UI_UNIT_Y, ""); } UI_but_type_set_menu_from_pulldown(but); @@ -739,7 +742,7 @@ static void ui_node_draw_node( } } - for (input = node->inputs.first; input; input = input->next) { + for (input = (bNodeSocket *)node->inputs.first; input; input = input->next) { ui_node_draw_input(layout, C, ntree, node, input, depth + 1); } } @@ -749,7 +752,7 @@ static void ui_node_draw_input( { PointerRNA inputptr, nodeptr; uiBlock *block = uiLayoutGetBlock(layout); - uiLayout *row = NULL; + uiLayout *row = nullptr; bNode *lnode; bool dependency_loop; @@ -759,11 +762,11 @@ static void ui_node_draw_input( /* to avoid eternal loops on cyclic dependencies */ node->flag |= NODE_TEST; - lnode = (input->link) ? input->link->fromnode : NULL; + lnode = (input->link) ? input->link->fromnode : nullptr; dependency_loop = (lnode && (lnode->flag & NODE_TEST)); if (dependency_loop) { - lnode = NULL; + lnode = nullptr; } /* socket RNA pointer */ @@ -862,7 +865,7 @@ static void ui_node_draw_input( } if (add_dummy_decorator) { - uiItemDecoratorR(split_wrapper.decorate_column, NULL, NULL, 0); + uiItemDecoratorR(split_wrapper.decorate_column, nullptr, nullptr, 0); } /* clear */ @@ -879,7 +882,7 @@ void uiTemplateNodeView( } /* clear for cycle check */ - for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) { + for (tnode = (bNode *)ntree->nodes.first; tnode; tnode = tnode->next) { tnode->flag &= ~NODE_TEST; } diff --git a/source/blender/editors/space_node/node_toolbar.c b/source/blender/editors/space_node/node_toolbar.cc index 2e7d6ab6cd5..2e7d6ab6cd5 100644 --- a/source/blender/editors/space_node/node_toolbar.c +++ b/source/blender/editors/space_node/node_toolbar.cc diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.cc index 8ecab92aa26..f0db0539c4f 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.cc @@ -76,7 +76,7 @@ int space_node_view_flag( BLI_rctf_init_minmax(&cur_new); if (snode->edittree) { - for (node = snode->edittree->nodes.first; node; node = node->next) { + for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { if ((node->flag & node_flag) == node_flag) { BLI_rctf_union(&cur_new, &node->totr); tot++; @@ -191,16 +191,16 @@ void NODE_OT_view_selected(wmOperatorType *ot) /** \name Background Image Operators * \{ */ -typedef struct NodeViewMove { +struct NodeViewMove { int mvalo[2]; int xmin, ymin, xmax, ymax; -} NodeViewMove; +}; static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *region = CTX_wm_region(C); - NodeViewMove *nvm = op->customdata; + NodeViewMove *nvm = (NodeViewMove *)op->customdata; switch (event->type) { case MOUSEMOVE: @@ -215,8 +215,8 @@ static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, const wmEvent *e CLAMP(snode->yof, nvm->ymin, nvm->ymax); ED_region_tag_redraw(region); - WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL); - WM_main_add_notifier(NC_SPACE | ND_SPACE_NODE_VIEW, NULL); + WM_main_add_notifier(NC_NODE | ND_DISPLAY, nullptr); + WM_main_add_notifier(NC_SPACE | ND_SPACE_NODE_VIEW, nullptr); break; @@ -225,7 +225,7 @@ static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, const wmEvent *e case RIGHTMOUSE: if (event->val == KM_RELEASE) { MEM_freeN(nvm); - op->customdata = NULL; + op->customdata = nullptr; return OPERATOR_FINISHED; } break; @@ -247,14 +247,14 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, const wmEvent * void *lock; ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock); - if (ibuf == NULL) { + if (ibuf == nullptr) { BKE_image_release_ibuf(ima, ibuf, lock); return OPERATOR_CANCELLED; } - nvm = MEM_callocN(sizeof(NodeViewMove), "NodeViewMove struct"); + nvm = (NodeViewMove *)MEM_callocN(sizeof(NodeViewMove), "NodeViewMove struct"); op->customdata = nvm; nvm->mvalo[0] = event->mval[0]; nvm->mvalo[1] = event->mval[1]; @@ -275,7 +275,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, const wmEvent * static void snode_bg_viewmove_cancel(bContext *UNUSED(C), wmOperator *op) { MEM_freeN(op->customdata); - op->customdata = NULL; + op->customdata = nullptr; } void NODE_OT_backimage_move(wmOperatorType *ot) @@ -309,8 +309,8 @@ static int backimage_zoom_exec(bContext *C, wmOperator *op) snode->zoom *= fac; ED_region_tag_redraw(region); - WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL); - WM_main_add_notifier(NC_SPACE | ND_SPACE_NODE_VIEW, NULL); + WM_main_add_notifier(NC_NODE | ND_DISPLAY, nullptr); + WM_main_add_notifier(NC_SPACE | ND_SPACE_NODE_VIEW, nullptr); return OPERATOR_FINISHED; } @@ -356,9 +356,9 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op)) float facx, facy; ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock); - if ((ibuf == NULL) || (ibuf->x == 0) || (ibuf->y == 0)) { + if ((ibuf == nullptr) || (ibuf->x == 0) || (ibuf->y == 0)) { BKE_image_release_ibuf(ima, ibuf, lock); return OPERATOR_CANCELLED; } @@ -374,8 +374,8 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op)) snode->yof = 0; ED_region_tag_redraw(region); - WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL); - WM_main_add_notifier(NC_SPACE | ND_SPACE_NODE_VIEW, NULL); + WM_main_add_notifier(NC_NODE | ND_DISPLAY, nullptr); + WM_main_add_notifier(NC_SPACE | ND_SPACE_NODE_VIEW, nullptr); return OPERATOR_FINISHED; } @@ -402,7 +402,7 @@ void NODE_OT_backimage_fit(wmOperatorType *ot) /** \name Sample Backdrop Operator * \{ */ -typedef struct ImageSampleInfo { +struct ImageSampleInfo { ARegionType *art; void *draw_handle; int x, y; @@ -420,12 +420,12 @@ typedef struct ImageSampleInfo { int draw; int color_manage; -} ImageSampleInfo; +}; static void sample_draw(const bContext *C, ARegion *region, void *arg_info) { Scene *scene = CTX_data_scene(C); - ImageSampleInfo *info = arg_info; + ImageSampleInfo *info = (ImageSampleInfo *)arg_info; if (info->draw) { ED_image_draw_info(scene, @@ -445,7 +445,7 @@ static void sample_draw(const bContext *C, ARegion *region, void *arg_info) /* Returns mouse position in image space. */ bool ED_space_node_get_position( - Main *bmain, SpaceNode *snode, struct ARegion *ar, const int mval[2], float fpos[2]) + Main *bmain, SpaceNode *snode, struct ARegion *region, const int mval[2], float fpos[2]) { if (!ED_node_is_compositor(snode) || (snode->flag & SNODE_BACKDRAW) == 0) { return false; @@ -453,7 +453,7 @@ bool ED_space_node_get_position( void *lock; Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock); if (!ibuf) { BKE_image_release_ibuf(ima, ibuf, lock); return false; @@ -462,8 +462,10 @@ bool ED_space_node_get_position( /* map the mouse coords to the backdrop image space */ float bufx = ibuf->x * snode->zoom; float bufy = ibuf->y * snode->zoom; - fpos[0] = (bufx > 0.0f ? ((float)mval[0] - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f); - fpos[1] = (bufy > 0.0f ? ((float)mval[1] - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f); + fpos[0] = (bufx > 0.0f ? ((float)mval[0] - 0.5f * region->winx - snode->xof) / bufx + 0.5f : + 0.0f); + fpos[1] = (bufy > 0.0f ? ((float)mval[1] - 0.5f * region->winy - snode->yof) / bufy + 0.5f : + 0.0f); BKE_image_release_ibuf(ima, ibuf, lock); return true; @@ -489,7 +491,7 @@ bool ED_space_node_color_sample( } ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock); if (!ibuf) { return false; } @@ -532,14 +534,14 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event) Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); ARegion *region = CTX_wm_region(C); - ImageSampleInfo *info = op->customdata; + ImageSampleInfo *info = (ImageSampleInfo *)op->customdata; void *lock; Image *ima; ImBuf *ibuf; float fx, fy, bufx, bufy; ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock); if (!ibuf) { info->draw = 0; return; @@ -570,8 +572,8 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event) info->draw = 1; info->channels = ibuf->channels; - info->zp = NULL; - info->zfp = NULL; + info->zp = nullptr; + info->zfp = nullptr; if (ibuf->rect) { cp = (uchar *)(ibuf->rect + y * ibuf->x + x); @@ -616,7 +618,7 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event) } else { info->draw = 0; - ED_node_sample_set(NULL); + ED_node_sample_set(nullptr); } BKE_image_release_ibuf(ima, ibuf, lock); @@ -626,9 +628,9 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event) static void sample_exit(bContext *C, wmOperator *op) { - ImageSampleInfo *info = op->customdata; + ImageSampleInfo *info = (ImageSampleInfo *)op->customdata; - ED_node_sample_set(NULL); + ED_node_sample_set(nullptr); ED_region_draw_cb_exit(info->art, info->draw_handle); ED_area_tag_redraw(CTX_wm_area(C)); MEM_freeN(info); @@ -644,7 +646,7 @@ static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_CANCELLED; } - info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo"); + info = (ImageSampleInfo *)MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo"); info->art = region->type; info->draw_handle = ED_region_draw_cb_activate( region->type, sample_draw, info, REGION_DRAW_POST_PIXEL); diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index f20a9409d90..ff848a7bb95 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -345,7 +345,7 @@ 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 */ + /* 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 */ short shader_type = snode->shaderfrom; @@ -563,7 +563,7 @@ static SpaceLink *node_duplicate(SpaceLink *sl) BLI_listbase_clear(&snoden->runtime->linkdrag); } - /* Note: no need to set node tree user counts, + /* NOTE: no need to set node tree user counts, * the editor only keeps at least 1 (id_us_ensure_real), * which is already done by the original SpaceNode. */ @@ -651,6 +651,10 @@ static void node_main_region_init(wmWindowManager *wm, ARegion *region) lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW); WM_event_add_dropbox_handler(®ion->handlers, lb); + + /* The backdrop image gizmo needs to change together with the view. So always refresh gizmos on + * region size changes. */ + WM_gizmomap_tag_refresh(region->gizmo_map); } static void node_main_region_draw(const bContext *C, ARegion *region) @@ -1094,8 +1098,6 @@ void ED_spacetype_node(void) art->draw = node_buttons_region_draw; BLI_addhead(&st->regiontypes, art); - node_buttons_register(art); - /* regions: toolbar */ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region"); art->regionid = RGN_TYPE_TOOLS; diff --git a/source/blender/editors/space_outliner/outliner_context.c b/source/blender/editors/space_outliner/outliner_context.c index 4293d8da73e..d61bb17f661 100644 --- a/source/blender/editors/space_outliner/outliner_context.c +++ b/source/blender/editors/space_outliner/outliner_context.c @@ -64,7 +64,7 @@ int /*eContextResult*/ outliner_context(const bContext *C, outliner_context_selected_ids(space_outliner, result); return CTX_RESULT_OK; } - /* Note: Querying non-ID selection could also work if tree elements stored their matching RNA + /* NOTE: Querying non-ID selection could also work if tree elements stored their matching RNA * struct type. */ return CTX_RESULT_MEMBER_NOT_FOUND; diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index 8e19f76ea16..86aab86db10 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -818,12 +818,7 @@ static bool datastack_drop_are_types_valid(StackDropData *drop_data) switch (drop_data->drag_tselem->type) { case TSE_MODIFIER_BASE: case TSE_MODIFIER: - if (ob_parent->type == OB_GPENCIL) { - return ob_dst->type == OB_GPENCIL; - } - else if (ob_parent->type != OB_GPENCIL) { - return ob_dst->type != OB_GPENCIL; - } + return (ob_parent->type == OB_GPENCIL) == (ob_dst->type == OB_GPENCIL); break; case TSE_CONSTRAINT_BASE: case TSE_CONSTRAINT: @@ -1008,7 +1003,7 @@ static void datastack_drop_reorder(bContext *C, ReportList *reports, StackDropDa drag_te, drop_te, insert_type, &ob->greasepencil_modifiers); ED_object_gpencil_modifier_move_to_index(reports, ob, drop_data->drag_directdata, index); } - else if (ob->type != OB_GPENCIL) { + else { index = outliner_get_insert_index(drag_te, drop_te, insert_type, &ob->modifiers); ED_object_modifier_move_to_index(reports, ob, drop_data->drag_directdata, index); } @@ -1330,7 +1325,7 @@ static TreeElement *outliner_item_drag_element_find(SpaceOutliner *space_outline ARegion *region, const wmEvent *event) { - /* note: using EVT_TWEAK_ events to trigger dragging is fine, + /* NOTE: using EVT_TWEAK_ events to trigger dragging is fine, * it sends coordinates from where dragging was started */ const float my = UI_view2d_region_to_view_y(®ion->v2d, event->mval[1]); return outliner_find_item_at_y(space_outliner, &space_outliner->tree, my); @@ -1370,7 +1365,7 @@ static int outliner_item_drag_drop_invoke(bContext *C, wmOperatorType *ot = WM_operatortype_find("VIEW2D_OT_edge_pan", true); PointerRNA op_ptr; WM_operator_properties_create_ptr(&op_ptr, ot); - RNA_int_set(&op_ptr, "outside_padding", OUTLINER_DRAG_SCOLL_OUTSIDE_PAD); + RNA_float_set(&op_ptr, "outside_padding", OUTLINER_DRAG_SCOLL_OUTSIDE_PAD); WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr); WM_operator_properties_free(&op_ptr); } diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 92cd50560e4..db37c8c1c8c 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -355,7 +355,7 @@ static void outliner_base_or_object_pointer_create( } } -/* Note: Collection is only valid when we want to change the collection data, otherwise we get it +/* NOTE: Collection is only valid when we want to change the collection data, otherwise we get it * from layer collection. Layer collection is valid whenever we are looking at a view layer. */ static void outliner_collection_set_flag_recursive(Scene *scene, ViewLayer *view_layer, @@ -374,7 +374,7 @@ static void outliner_collection_set_flag_recursive(Scene *scene, /* Set the same flag for the nested objects as well. */ if (base_or_object_prop) { - /* Note: We can't use BKE_collection_object_cache_get() + /* NOTE: We can't use BKE_collection_object_cache_get() * otherwise we would not take collection exclusion into account. */ LISTBASE_FOREACH (CollectionObject *, cob, &layer_collection->collection->gobject) { @@ -414,7 +414,7 @@ static void outliner_collection_set_flag_recursive(Scene *scene, * A collection is isolated if all its parents and children are "visible". * All the other collections must be "invisible". * - * Note: We could/should boost performance by iterating over the tree twice. + * NOTE: We could/should boost performance by iterating over the tree twice. * First tagging all the children/parent collections, then getting their values and comparing. * To run BKE_collection_has_collection() so many times is silly and slow. */ @@ -1090,7 +1090,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, RestrictPropertiesActive props_active = props_active_parent; if (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && te->ys <= region->v2d.cur.ymax) { - if (tselem->type == TSE_R_LAYER && (space_outliner->outlinevis == SO_SCENES)) { + if (tselem->type == TSE_R_LAYER && + ELEM(space_outliner->outlinevis, SO_SCENES, SO_VIEW_LAYER)) { if (space_outliner->show_restrict_flags & SO_RESTRICT_RENDER) { /* View layer render toggle. */ ViewLayer *layer = te->directdata; @@ -2106,7 +2107,7 @@ static void outliner_draw_mode_column_toggle(uiBlock *block, tip); UI_but_func_set(but, outliner_mode_toggle_fn, tselem, NULL); UI_but_flag_enable(but, UI_BUT_DRAG_LOCK); - /* Mode toggling handles it's own undo state because undo steps need to be grouped. */ + /* Mode toggling handles its own undo state because undo steps need to be grouped. */ UI_but_flag_disable(but, UI_BUT_UNDO); if (ID_IS_LINKED(&ob->id)) { @@ -2355,6 +2356,9 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case eGpencilModifierType_Texture: data.icon = ICON_TEXTURE; break; + case eGpencilModifierType_Weight: + data.icon = ICON_MOD_VERTEX_WEIGHT; + break; /* Default */ default: @@ -2960,7 +2964,8 @@ static void outliner_draw_iconrow(bContext *C, te->flag &= ~(TE_ICONROW | TE_ICONROW_MERGED); /* object hierarchy always, further constrained on level */ - if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB))) { + if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) || + ELEM(tselem->type, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL)) { /* active blocks get white circle */ if (tselem->type == TSE_SOME_ID) { if (te->idcode == ID_OB) { @@ -3125,7 +3130,7 @@ static void outliner_draw_tree_element(bContext *C, *te_edit = te; } - /* Icons can be ui buts, we don't want it to overlap with restrict .*/ + /* Icons can be UI buts, we don't want it to overlap with restrict. */ if (restrict_column_width > 0) { xmax -= restrict_column_width + UI_UNIT_X; } @@ -3727,7 +3732,7 @@ static void outliner_update_viewable_area(ARegion *region, } /* ****************************************************** */ -/* Main Entrypoint - Draw contents of Outliner editor */ +/* Main Entry-point - Draw contents of Outliner editor */ void draw_outliner(const bContext *C) { diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 0c97fdc1c18..5be6c69363e 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -154,7 +154,9 @@ void OUTLINER_OT_highlight_update(wmOperatorType *ot) /** \name Toggle Open/Closed Operator * \{ */ -/* Open or close a tree element, optionally toggling all children recursively */ +/** + * Open or close a tree element, optionally toggling all children recursively. + */ void outliner_item_openclose(SpaceOutliner *space_outliner, TreeElement *te, bool open, @@ -964,7 +966,7 @@ void OUTLINER_OT_lib_relocate(wmOperatorType *ot) /* XXX This does not work with several items * (it is only called once in the end, due to the 'deferred' - * filebrowser invocation through event system...). */ + * file-browser invocation through event system...). */ void lib_relocate_fn(bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), @@ -1599,8 +1601,10 @@ void OUTLINER_OT_show_one_level(wmOperatorType *ot) /** \name Show Hierarchy Operator * \{ */ -/* Helper function for tree_element_shwo_hierarchy() - - * recursively checks whether subtrees have any objects. */ +/** + * Helper function for #tree_element_shwo_hierarchy() - + * recursively checks whether subtrees have any objects. + */ static int subtree_has_objects(ListBase *lb) { LISTBASE_FOREACH (TreeElement *, te, lb) { diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index fea5ddae16b..5336376b576 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -191,7 +191,7 @@ typedef enum { #define OL_RNA_COL_SPACEX (UI_UNIT_X * 2.5f) /* The outliner display modes that support the filter system. - * Note: keep it synced with space_outliner.py */ + * NOTE: keep it synced with `space_outliner.py`. */ #define SUPPORT_FILTER_OUTLINER(space_outliner_) \ (ELEM((space_outliner_)->outlinevis, SO_VIEW_LAYER, SO_OVERRIDES_LIBRARY)) diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 50f089f894a..35015356f0b 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -42,6 +42,7 @@ #include "BKE_collection.h" #include "BKE_constraint.h" #include "BKE_context.h" +#include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" #include "BKE_layer.h" @@ -450,7 +451,7 @@ static void tree_element_defgroup_activate(bContext *C, TreeElement *te, TreeSto /* id in tselem is object */ Object *ob = (Object *)tselem->id; BLI_assert(te->index + 1 >= 0); - ob->actdef = te->index + 1; + BKE_object_defgroup_active_index_set(ob, te->index + 1); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob); @@ -830,7 +831,7 @@ static eOLDrawState tree_element_defgroup_state_get(const ViewLayer *view_layer, { const Object *ob = (const Object *)tselem->id; if (ob == OBACT(view_layer)) { - if (ob->actdef == te->index + 1) { + if (BKE_object_defgroup_active_index_get(ob) == te->index + 1) { return OL_DRAWSEL_NORMAL; } } @@ -1654,7 +1655,7 @@ static int outliner_item_do_activate_from_cursor(bContext *C, return OPERATOR_FINISHED; } -/* event can enterkey, then it opens/closes */ +/* Event can enter-key, then it opens/closes. */ static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { const bool extend = RNA_boolean_get(op->ptr, "extend"); @@ -1816,7 +1817,7 @@ static TreeElement *outliner_find_rightmost_visible_child(SpaceOutliner *space_o return te; } -/* Find previous visible element in the tree */ +/* Find previous visible element in the tree. */ static TreeElement *outliner_find_previous_element(SpaceOutliner *space_outliner, TreeElement *te) { if (te->prev) { diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index c532dd8accd..8a3ba9a24c2 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -86,6 +86,8 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "../../blender/blenloader/BLO_readfile.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -166,7 +168,7 @@ static void get_element_operation_type( case ID_WM: case ID_SCR: /* Those are ignored here. */ - /* Note: while Screens should be manageable here, deleting a screen used by a workspace + /* NOTE: while Screens should be manageable here, deleting a screen used by a workspace * will cause crashes when trying to use that workspace, so for now let's play minimal, * safe change. */ break; @@ -740,7 +742,7 @@ static void id_local_fn(bContext *C, BKE_lib_id_clear_library_data(bmain, tselem->id); } else { - BKE_main_id_clear_newpoins(bmain); + BKE_main_id_newptr_and_tag_clear(bmain); } } else if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id)) { @@ -846,13 +848,13 @@ static void id_override_library_create_fn(bContext *C, te->store_elem->id->tag |= LIB_TAG_DOIT; } success = BKE_lib_override_library_create( - bmain, CTX_data_scene(C), CTX_data_view_layer(C), id_root, id_reference); + bmain, CTX_data_scene(C), CTX_data_view_layer(C), id_root, id_reference, NULL); } else if (ID_IS_OVERRIDABLE_LIBRARY(id_root)) { success = BKE_lib_override_library_create_from_id(bmain, id_root, true) != NULL; /* Cleanup. */ - BKE_main_id_clear_newpoins(bmain); + BKE_main_id_newptr_and_tag_clear(bmain); BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); } @@ -930,8 +932,14 @@ static void id_override_library_resync_fn(bContext *C, te->store_elem->id->tag |= LIB_TAG_DOIT; } - BKE_lib_override_library_resync( - bmain, scene, CTX_data_view_layer(C), id_root, NULL, do_hierarchy_enforce, true, reports); + BKE_lib_override_library_resync(bmain, + scene, + CTX_data_view_layer(C), + id_root, + NULL, + do_hierarchy_enforce, + true, + &(struct BlendFileReadReport){.reports = reports}); WM_event_add_notifier(C, NC_WINDOW, NULL); } diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index bed7683703f..c5ec656080a 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1,4 +1,4 @@ -/* +/* * 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 @@ -62,6 +62,7 @@ #include "BLT_translation.h" #include "BKE_armature.h" +#include "BKE_deform.h" #include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" @@ -312,12 +313,8 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, outliner_add_element(space_outliner, &te->subtree, ob, te, TSE_ANIM_DATA, 0); } - outliner_add_element(space_outliner, - &te->subtree, - ob->poselib, - te, - TSE_SOME_ID, - 0); /* XXX FIXME.. add a special type for this. */ + /* FIXME: add a special type for this. */ + outliner_add_element(space_outliner, &te->subtree, ob->poselib, te, TSE_SOME_ID, 0); if (ob->proxy && !ID_IS_LINKED(ob)) { outliner_add_element(space_outliner, &te->subtree, ob->proxy, te, TSE_PROXY, 0); @@ -556,17 +553,20 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, } /* vertex groups */ - if (!BLI_listbase_is_empty(&ob->defbase)) { - TreeElement *tenla = outliner_add_element( - space_outliner, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0); - tenla->name = IFACE_("Vertex Groups"); + if (ELEM(ob->type, OB_MESH, OB_GPENCIL, OB_LATTICE)) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + if (!BLI_listbase_is_empty(defbase)) { + TreeElement *tenla = outliner_add_element( + space_outliner, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0); + tenla->name = IFACE_("Vertex Groups"); - 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; + int index; + LISTBASE_FOREACH_INDEX (bDeformGroup *, defgroup, defbase, index) { + TreeElement *ten = outliner_add_element( + space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, index); + ten->name = defgroup->name; + ten->directdata = defgroup; + } } } @@ -592,7 +592,7 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, switch (GS(id->name)) { case ID_LI: case ID_SCE: - BLI_assert(!"ID type expected to be expanded through new tree-element design"); + BLI_assert_msg(0, "ID type expected to be expanded through new tree-element design"); break; case ID_OB: { outliner_add_object_contents(space_outliner, te, tselem, (Object *)id); @@ -905,12 +905,13 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } else if (type == TSE_SOME_ID) { if (!te->type) { - BLI_assert(!"Expected this ID type to be ported to new Outliner tree-element design"); + BLI_assert_msg(0, "Expected this ID type to be ported to new Outliner tree-element design"); } } else if (ELEM(type, TSE_LIBRARY_OVERRIDE_BASE, TSE_LIBRARY_OVERRIDE)) { if (!te->type) { - BLI_assert(!"Expected override types to be ported to new Outliner tree-element design"); + BLI_assert_msg(0, + "Expected override types to be ported to new Outliner tree-element design"); } } else { @@ -1324,7 +1325,7 @@ static void outliner_sort(ListBase *lb) } TreeStoreElem *tselem = TREESTORE(te); - /* sorting rules; only object lists, ID lists, or deformgroups */ + /* Sorting rules; only object lists, ID lists, or deform-groups. */ if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB))) { int totelem = BLI_listbase_count(lb); @@ -1925,5 +1926,5 @@ void outliner_build_tree(Main *mainvar, outliner_filter_tree(space_outliner, view_layer); outliner_restore_scrolling_position(space_outliner, region, &focus); - BKE_main_id_clear_newpoins(mainvar); + BKE_main_id_newptr_and_tag_clear(mainvar); } diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 728be1ccaaf..205f0117e6a 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -179,7 +179,7 @@ static void outliner_main_region_listener(const wmRegionListenerParams *params) } break; case NC_GROUP: - /* all actions now, todo: check outliner view mode? */ + /* All actions now, TODO: check outliner view mode? */ ED_region_tag_redraw(region); break; case NC_LAMP: @@ -331,6 +331,7 @@ static SpaceLink *outliner_create(const ScrArea *UNUSED(area), const Scene *UNUS 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; + space_outliner->filter = SO_FILTER_NO_VIEW_LAYERS; /* header */ region = MEM_callocN(sizeof(ARegion), "header for outliner"); diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh index f089a149805..96af8258010 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.hh +++ b/source/blender/editors/space_outliner/tree/tree_display.hh @@ -86,7 +86,7 @@ class TreeDisplayViewLayer final : public AbstractTreeDisplay { ListBase buildTree(const TreeSourceData &source_data) override; private: - void add_view_layer(ListBase &, TreeElement &); + void add_view_layer(Scene &, ListBase &, TreeElement *); void add_layer_collections_recursive(ListBase &, ListBase &, TreeElement &); void add_layer_collection_objects(ListBase &, LayerCollection &, TreeElement &); void add_layer_collection_objects_children(TreeElement &); diff --git a/source/blender/editors/space_outliner/tree/tree_display_libraries.cc b/source/blender/editors/space_outliner/tree/tree_display_libraries.cc index 91b690d35fa..c6b700318dd 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_libraries.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_libraries.cc @@ -138,8 +138,8 @@ TreeElement *TreeDisplayLibraries::add_library_contents(Main &mainvar, } } - /* We always want to create an entry for libraries, even if/when we have no more IDs from - * them. This invalid state is important to show to user as well.*/ + /* We always want to create an entry for libraries, even if/when we have no more IDs from them. + * This invalid state is important to show to user as well. */ if (id != nullptr || is_library) { if (!tenlib) { /* Create library tree element on demand, depending if there are any data-blocks. */ diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library.cc index 3059f8bfe0c..a17bf174a74 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_override_library.cc @@ -150,27 +150,25 @@ TreeElement *TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar, } /* Create data-block list parent element on demand. */ - if (id != nullptr) { - TreeElement *ten; + TreeElement *ten; - if (filter_id_type) { - ten = tenlib; - } - else { - ten = outliner_add_element( - &space_outliner_, &tenlib->subtree, lbarray[a], nullptr, TSE_ID_BASE, 0); - ten->directdata = lbarray[a]; - ten->name = outliner_idcode_to_plural(GS(id->name)); - } + if (filter_id_type) { + ten = tenlib; + } + else { + ten = outliner_add_element( + &space_outliner_, &tenlib->subtree, lbarray[a], nullptr, TSE_ID_BASE, 0); + ten->directdata = lbarray[a]; + ten->name = outliner_idcode_to_plural(GS(id->name)); + } - for (ID *id : List<ID>(lbarray[a])) { - if (override_library_id_filter_poll(lib, id)) { - TreeElement *override_tree_element = outliner_add_element( - &space_outliner_, &ten->subtree, id, ten, TSE_LIBRARY_OVERRIDE_BASE, 0); + for (ID *id : List<ID>(lbarray[a])) { + if (override_library_id_filter_poll(lib, id)) { + TreeElement *override_tree_element = outliner_add_element( + &space_outliner_, &ten->subtree, id, ten, TSE_LIBRARY_OVERRIDE_BASE, 0); - if (BLI_listbase_is_empty(&override_tree_element->subtree)) { - outliner_free_tree_element(override_tree_element, &ten->subtree); - } + if (BLI_listbase_is_empty(&override_tree_element->subtree)) { + outliner_free_tree_element(override_tree_element, &ten->subtree); } } } diff --git a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc index f00cf3c34c0..c3d0aecd3cb 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc @@ -70,17 +70,42 @@ TreeDisplayViewLayer::TreeDisplayViewLayer(SpaceOutliner &space_outliner) ListBase TreeDisplayViewLayer::buildTree(const TreeSourceData &source_data) { ListBase tree = {nullptr}; - - view_layer_ = source_data.view_layer; + Scene *scene = source_data.scene; show_objects_ = !(space_outliner_.filter & SO_FILTER_NO_OBJECT); + for (auto *view_layer : ListBaseWrapper<ViewLayer>(scene->view_layers)) { + view_layer_ = view_layer; + + if (space_outliner_.filter & SO_FILTER_NO_VIEW_LAYERS) { + if (view_layer != source_data.view_layer) { + continue; + } + + add_view_layer(*scene, tree, (TreeElement *)nullptr); + } + else { + TreeElement &te_view_layer = *outliner_add_element( + &space_outliner_, &tree, scene, nullptr, TSE_R_LAYER, 0); + TREESTORE(&te_view_layer)->flag &= ~TSE_CLOSED; + te_view_layer.name = view_layer->name; + te_view_layer.directdata = view_layer; + + add_view_layer(*scene, te_view_layer.subtree, &te_view_layer); + } + } + + return tree; +} + +void TreeDisplayViewLayer::add_view_layer(Scene &scene, ListBase &tree, TreeElement *parent) +{ const bool show_children = (space_outliner_.filter & SO_FILTER_NO_CHILDREN) == 0; if (space_outliner_.filter & SO_FILTER_NO_COLLECTION) { /* Show objects in the view layer. */ for (Base *base : List<Base>(view_layer_->object_bases)) { TreeElement *te_object = outliner_add_element( - &space_outliner_, &tree, base->object, nullptr, TSE_SOME_ID, 0); + &space_outliner_, &tree, base->object, parent, TSE_SOME_ID, 0); te_object->directdata = base; } @@ -91,31 +116,24 @@ ListBase TreeDisplayViewLayer::buildTree(const TreeSourceData &source_data) else { /* Show collections in the view layer. */ TreeElement &ten = *outliner_add_element( - &space_outliner_, &tree, source_data.scene, nullptr, TSE_VIEW_COLLECTION_BASE, 0); + &space_outliner_, &tree, &scene, parent, TSE_VIEW_COLLECTION_BASE, 0); ten.name = IFACE_("Scene Collection"); TREESTORE(&ten)->flag &= ~TSE_CLOSED; - add_view_layer(ten.subtree, ten); + /* First layer collection is for master collection, don't show it. */ + LayerCollection *lc = static_cast<LayerCollection *>(view_layer_->layer_collections.first); + if (lc == nullptr) { + return; + } + + add_layer_collections_recursive(ten.subtree, lc->layer_collections, ten); + if (show_objects_) { + add_layer_collection_objects(ten.subtree, *lc, ten); + } if (show_children) { add_layer_collection_objects_children(ten); } } - - return tree; -} - -void TreeDisplayViewLayer::add_view_layer(ListBase &tree, TreeElement &parent) -{ - /* First layer collection is for master collection, don't show it. */ - LayerCollection *lc = static_cast<LayerCollection *>(view_layer_->layer_collections.first); - if (lc == nullptr) { - return; - } - - add_layer_collections_recursive(tree, lc->layer_collections, parent); - if (show_objects_) { - add_layer_collection_objects(tree, *lc, parent); - } } void TreeDisplayViewLayer::add_layer_collections_recursive(ListBase &tree, @@ -149,8 +167,9 @@ void TreeDisplayViewLayer::add_layer_collections_recursive(ListBase &tree, add_layer_collection_objects(ten->subtree, *lc, *ten); } - const bool lib_overrides_visible = !SUPPORT_FILTER_OUTLINER(&space_outliner_) || - ((space_outliner_.filter & SO_FILTER_NO_LIB_OVERRIDE) == 0); + const bool lib_overrides_visible = !exclude && (!SUPPORT_FILTER_OUTLINER(&space_outliner_) || + ((space_outliner_.filter & + SO_FILTER_NO_LIB_OVERRIDE) == 0)); if (lib_overrides_visible && ID_IS_OVERRIDE_LIBRARY_REAL(&lc->collection->id)) { outliner_add_element( diff --git a/source/blender/editors/space_outliner/tree/tree_element_id.cc b/source/blender/editors/space_outliner/tree/tree_element_id.cc index ce99b954204..7ff5a3285f1 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_id.cc +++ b/source/blender/editors/space_outliner/tree/tree_element_id.cc @@ -85,7 +85,7 @@ TreeElementID *TreeElementID::createFromID(TreeElement &legacy_te, ID &id) return new TreeElementID(legacy_te, id); /* Deprecated */ case ID_IP: - BLI_assert(!"Outliner trying to build tree-element for deprecated ID type"); + BLI_assert_msg(0, "Outliner trying to build tree-element for deprecated ID type"); return nullptr; } diff --git a/source/blender/editors/space_outliner/tree/tree_element_overrides.cc b/source/blender/editors/space_outliner/tree/tree_element_overrides.cc index c5d254242c6..731beb3956e 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_overrides.cc +++ b/source/blender/editors/space_outliner/tree/tree_element_overrides.cc @@ -94,9 +94,7 @@ void TreeElementOverridesBase::expand(SpaceOutliner &space_outliner) const TreeElementOverridesProperty::TreeElementOverridesProperty(TreeElement &legacy_te, TreeElementOverridesData &override_data) - : AbstractTreeElement(legacy_te), - id_(override_data.id), - override_prop_(override_data.override_property) + : AbstractTreeElement(legacy_te), override_prop_(override_data.override_property) { BLI_assert(legacy_te.store_elem->type == TSE_LIBRARY_OVERRIDE); diff --git a/source/blender/editors/space_outliner/tree/tree_element_overrides.hh b/source/blender/editors/space_outliner/tree/tree_element_overrides.hh index c3caab8e268..0067db6ea56 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_overrides.hh +++ b/source/blender/editors/space_outliner/tree/tree_element_overrides.hh @@ -40,7 +40,6 @@ class TreeElementOverridesBase final : public AbstractTreeElement { }; class TreeElementOverridesProperty final : public AbstractTreeElement { - ID &id_; IDOverrideLibraryProperty &override_prop_; public: diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c index 4ce0e454df8..11bee36e914 100644 --- a/source/blender/editors/space_script/space_script.c +++ b/source/blender/editors/space_script/space_script.c @@ -81,7 +81,7 @@ static void script_free(SpaceLink *sl) SpaceScript *sscript = (SpaceScript *)sl; #ifdef WITH_PYTHON - /*free buttons references*/ + /* Free buttons references. */ if (sscript->but_refs) { sscript->but_refs = NULL; } @@ -156,7 +156,7 @@ static void script_header_region_draw(const bContext *C, ARegion *region) static void script_main_region_listener(const wmRegionListenerParams *UNUSED(params)) { -/* XXX - Todo, need the ScriptSpace accessible to get the python script to run. */ +/* XXX: Todo, need the ScriptSpace accessible to get the python script to run. */ #if 0 BPY_run_script_space_listener() #endif diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index cd75bc98b15..1239286d4da 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -158,7 +158,7 @@ static void sequencer_generic_props__internal(wmOperatorType *ot, int flag) ot->prop = RNA_def_boolean(ot->srna, "set_view_transform", true, - "Set view transform", + "Set View Transform", "Set appropriate view transform based on media colorspace"); } } @@ -260,7 +260,7 @@ static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wm RNA_PROP_BEGIN (op->ptr, itemptr, prop) { char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); BLI_strncpy(load_data->name, filename, sizeof(load_data->name)); - BLI_snprintf(load_data->path, sizeof(load_data->path), "%s%s", directory, filename); + BLI_join_dirfile(load_data->path, sizeof(load_data->path), directory, filename); MEM_freeN(filename); break; } @@ -1081,8 +1081,7 @@ static int sequencer_add_image_strip_invoke(bContext *C, sequencer_disable_one_time_properties(C, op); - const SequencerToolSettings *tool_settings = scene->toolsettings->sequencer_tool_settings; - RNA_enum_set(op->ptr, "fit_method", tool_settings->fit_method); + RNA_enum_set(op->ptr, "fit_method", SEQ_tool_settings_fit_method_get(scene)); /* Name set already by drag and drop. */ if (RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) { diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c index 11614d94862..1e0ecfd890e 100644 --- a/source/blender/editors/space_sequencer/sequencer_buttons.c +++ b/source/blender/editors/space_sequencer/sequencer_buttons.c @@ -111,10 +111,10 @@ void sequencer_buttons_register(ARegionType *art) pt = MEM_callocN(sizeof(PanelType), "spacetype sequencer panel metadata"); strcpy(pt->idname, "SEQUENCER_PT_metadata"); strcpy(pt->label, N_("Metadata")); + strcpy(pt->category, "Metadata"); strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); pt->poll = metadata_panel_context_poll; pt->draw = metadata_panel_context_draw; - pt->flag |= PANEL_TYPE_DEFAULT_CLOSED; pt->order = 10; BLI_addtail(&art->paneltypes, pt); } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index b55c8035fa3..cdbe5bc63ce 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -101,7 +101,7 @@ #define SEQ_SCROLLER_TEXT_OFFSET 8 #define MUTE_ALPHA 120 -/* Note, Don't use SEQ_ALL_BEGIN/SEQ_ALL_END while drawing! +/* NOTE: Don't use SEQ_ALL_BEGIN/SEQ_ALL_END while drawing! * it messes up transform. */ #undef SEQ_ALL_BEGIN #undef SEQ_ALL_END @@ -367,8 +367,6 @@ static void draw_seq_waveform_overlay(View2D *v2d, static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, float x2, float y2) { - /* Don't use SEQ_ALL_BEGIN/SEQ_ALL_END here, - * because it changes seq->depth, which is needed for transform. */ Sequence *seq; uchar col[4]; @@ -455,13 +453,13 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, GPU_blend(GPU_BLEND_NONE); } -/* Get handle width in pixels. */ +/* Get handle width in 2d-View space. */ float sequence_handle_size_get_clamped(Sequence *seq, const float pixelx) { const float maxhandle = (pixelx * SEQ_HANDLE_SIZE) * U.pixelsize; - /* Ensure that handle is not wider, than half of strip. */ - return min_ff(maxhandle, ((float)(seq->enddisp - seq->startdisp) / 2.0f) / pixelx); + /* Ensure that handle is not wider, than quarter of strip. */ + return min_ff(maxhandle, ((float)(seq->enddisp - seq->startdisp) / 4.0f)); } /* Draw a handle, on left or right side of strip. */ @@ -870,9 +868,9 @@ static void draw_seq_background(Scene *scene, /* Draw the main strip body. */ if (is_single_image) { immRectf(pos, - SEQ_transform_get_left_handle_frame(seq, false), + SEQ_transform_get_left_handle_frame(seq), y1, - SEQ_transform_get_right_handle_frame(seq, false), + SEQ_transform_get_right_handle_frame(seq), y2); } else { @@ -1058,7 +1056,7 @@ static void draw_seq_fcurve_overlay( continue; } - /* If some frames were skipped above, we need to close the shape. */ + /* If some frames were skipped above, we need to close the shape. */ if (skip) { fcurve_batch_add_verts( vbo, y1, y2, y_height, timeline_frame - eval_step, prev_val, &vert_count); @@ -1558,7 +1556,7 @@ static void *sequencer_OCIO_transform_ibuf(const bContext *C, *r_format = GPU_RGB16F; } else { - BLI_assert(!"Incompatible number of channels for float buffer in sequencer"); + BLI_assert_msg(0, "Incompatible number of channels for float buffer in sequencer"); *r_format = GPU_RGBA16F; display_buffer = NULL; } @@ -2365,6 +2363,31 @@ static void draw_cache_view(const bContext *C) } /* Draw sequencer timeline. */ +static void draw_overlap_frame_indicator(const struct Scene *scene, const View2D *v2d) +{ + int overlap_frame = (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) ? + scene->ed->over_cfra : + scene->r.cfra + scene->ed->over_ofs; + + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + /* Shader may have color set from past usage - reset it. */ + immUniform1i("colors_len", 0); + immUniform1f("dash_width", 20.0f * U.pixelsize); + immUniform1f("dash_factor", 0.5f); + immUniformThemeColor(TH_CFRAME); + + immBegin(GPU_PRIM_LINES, 2); + immVertex2f(pos, overlap_frame, v2d->cur.ymin); + immVertex2f(pos, overlap_frame, v2d->cur.ymax); + immEnd(); + + immUnbindProgram(); +} + void draw_timeline_seq(const bContext *C, ARegion *region) { Scene *scene = CTX_data_scene(C); @@ -2424,31 +2447,6 @@ void draw_timeline_seq(const bContext *C, ARegion *region) cfra_flag |= DRAWCFRA_UNIT_SECONDS; } - /* Draw overlap frame frame indicator. */ - if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) { - int overlap_frame = (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) ? - scene->ed->over_cfra : - scene->r.cfra + scene->ed->over_ofs; - - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - /* Shader may have color set from past usage - reset it. */ - immUniform1i("colors_len", 0); - immUniform1f("dash_width", 20.0f * U.pixelsize); - immUniform1f("dash_factor", 0.5f); - immUniformThemeColor(TH_CFRAME); - - immBegin(GPU_PRIM_LINES, 2); - immVertex2f(pos, overlap_frame, v2d->cur.ymin); - immVertex2f(pos, overlap_frame, v2d->cur.ymax); - immEnd(); - - immUnbindProgram(); - } - UI_view2d_view_orthoSpecial(region, v2d, 1); int marker_draw_flag = DRAW_MARKERS_MARGIN; if (sseq->flag & SEQ_SHOW_MARKERS) { @@ -2456,11 +2454,6 @@ void draw_timeline_seq(const bContext *C, ARegion *region) } UI_view2d_view_ortho(v2d); - - if (ed) { - draw_cache_view(C); - } - ANIM_draw_previewrange(C, v2d, 1); /* Draw registered callbacks. */ @@ -2486,6 +2479,15 @@ void draw_timeline_seq_display(const bContext *C, ARegion *region) const SpaceSeq *sseq = CTX_wm_space_seq(C); View2D *v2d = ®ion->v2d; + if (scene->ed != NULL) { + UI_view2d_view_ortho(v2d); + draw_cache_view(C); + if (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) { + draw_overlap_frame_indicator(scene, v2d); + } + UI_view2d_view_restore(C); + } + ED_time_scrub_draw_current_frame(region, scene, !(sseq->flag & SEQ_DRAWFRAMES), true); UI_view2d_scrollers_draw(v2d, NULL); } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 1a1ba5a0754..75cf8542f67 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -34,6 +34,7 @@ #include "BLT_translation.h" +#include "DNA_anim_types.h" #include "DNA_scene_types.h" #include "DNA_sound_types.h" @@ -138,6 +139,48 @@ bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq) ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF)); } +static bool sequencer_fcurves_targets_color_strip(const FCurve *fcurve) +{ + if (!BLI_str_startswith(fcurve->rna_path, "sequence_editor.sequences_all[\"")) { + return false; + } + + if (!BLI_str_endswith(fcurve->rna_path, "\"].color")) { + return false; + } + + return true; +} + +/* + * Check if there is animation shown during playback. + * + * - Colors of color strips are displayed on the strip itself. + * - Backdrop is drawn. + */ +bool ED_space_sequencer_has_playback_animation(const struct SpaceSeq *sseq, + const struct Scene *scene) +{ + if (sseq->draw_flag & SEQ_DRAW_BACKDROP) { + return true; + } + + if (!scene->adt) { + return false; + } + if (!scene->adt->action) { + return false; + } + + LISTBASE_FOREACH (FCurve *, fcurve, &scene->adt->action->curves) { + if (sequencer_fcurves_targets_color_strip(fcurve)) { + return true; + } + } + + return false; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -292,7 +335,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) /* Check meta-strips. */ for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK) && + if (seq->flag & SELECT && !(seq->flag & SEQ_LOCK) && SEQ_transform_sequence_can_be_translated(seq)) { if ((seq->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) { SEQ_transform_translate_sequence( @@ -314,7 +357,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) /* Test for effects and overlap. */ for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK)) { + if (seq->flag & SELECT && !(seq->flag & SEQ_LOCK)) { seq->flag &= ~SEQ_OVERLAP; if (SEQ_transform_test_overlap(ed->seqbasep, seq)) { SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene); @@ -348,7 +391,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) } } - SEQ_sort(scene); + SEQ_sort(SEQ_active_seqbase_get(ed)); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -557,7 +600,7 @@ static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset) seq->endofs = endframe - seq->enddisp; changed = true; } - else if (endframe <= seq->enddisp) { + else { seq->endstill = seq->enddisp - endframe; seq->endofs = 0; changed = true; @@ -568,7 +611,7 @@ static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset) seq->startofs = 0; changed = true; } - else if (seq->start <= seq->startdisp) { + else { seq->startstill = 0; seq->startofs = seq->startdisp - seq->start; changed = true; @@ -1443,7 +1486,7 @@ static int sequencer_split_exec(bContext *C, wmOperator *op) } } - SEQ_sort(scene); + SEQ_sort(SEQ_active_seqbase_get(ed)); } if (changed) { WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -1577,38 +1620,35 @@ void SEQUENCER_OT_split(struct wmOperatorType *ot) /** \name Duplicate Strips Operator * \{ */ -static int apply_unique_name_fn(Sequence *seq, void *arg_pt) -{ - Scene *scene = (Scene *)arg_pt; - char name[sizeof(seq->name) - 2]; - - BLI_strncpy_utf8(name, seq->name + 2, sizeof(name)); - SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); - SEQ_dupe_animdata(scene, name, seq->name + 2); - return 1; -} - static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); Editing *ed = SEQ_editing_get(scene, false); - ListBase nseqbase = {NULL, NULL}; - if (ed == NULL) { return OPERATOR_CANCELLED; } - SEQ_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT, 0); + Sequence *active_seq = SEQ_select_active_get(scene); + ListBase duplicated = {NULL, NULL}; - if (nseqbase.first) { - Sequence *seq = nseqbase.first; + SEQ_sequence_base_dupli_recursive(scene, scene, &duplicated, ed->seqbasep, 0, 0); + ED_sequencer_deselect_all(scene); + + if (duplicated.first) { + Sequence *seq = duplicated.first; /* Rely on the nseqbase list being added at the end. * Their UUIDs has been re-generated by the SEQ_sequence_base_dupli_recursive(), */ - BLI_movelisttolist(ed->seqbasep, &nseqbase); + BLI_movelisttolist(ed->seqbasep, &duplicated); + /* Handle duplicated strips: set active, select, ensure unique name and duplicate animation + * data. */ for (; seq; seq = seq->next) { - SEQ_recursive_apply(seq, apply_unique_name_fn, scene); + if (active_seq != NULL && STREQ(seq->name, active_seq->name)) { + SEQ_select_active_set(scene, seq); + } + seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL + SEQ_LOCK); + SEQ_ensure_unique_name(seq, scene); } WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -1776,11 +1816,11 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op) /* Remove seq so overlap tests don't conflict, * see seq_free_sequence below for the real freeing. */ BLI_remlink(ed->seqbasep, seq); - /* if (seq->ipo) id_us_min(&seq->ipo->id); */ - /* XXX, remove fcurve and assign to split image strips */ + /* TODO: remove f-curve and assign to split image strips. + * The old animation system would remove the user of `seq->ipo`. */ - start_ofs = timeline_frame = SEQ_transform_get_left_handle_frame(seq, false); - frame_end = SEQ_transform_get_right_handle_frame(seq, false); + start_ofs = timeline_frame = SEQ_transform_get_left_handle_frame(seq); + frame_end = SEQ_transform_get_right_handle_frame(seq); while (timeline_frame < frame_end) { /* New seq. */ @@ -1829,7 +1869,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op) } } - SEQ_sort(scene); + SEQ_sort(SEQ_active_seqbase_get(ed)); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -1943,7 +1983,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op) seqm->machine = active_seq ? active_seq->machine : channel_max; strcpy(seqm->name + 2, "MetaStrip"); - SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seqm); + SEQ_sequence_base_unique_name_recursive(scene, &ed->seqbase, seqm); seqm->start = meta_start_frame; seqm->len = meta_end_frame - meta_start_frame; SEQ_time_update_sequence(scene, seqm); @@ -2014,7 +2054,7 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op)) } } - SEQ_sort(scene); + SEQ_sort(active_seqbase); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -2147,7 +2187,7 @@ static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, i seq = ed->seqbasep->first; while (seq) { - if ((seq != test) && (test->machine == seq->machine) && (test->depth == seq->depth) && + if ((seq != test) && (test->machine == seq->machine) && ((sel == -1) || (sel == (seq->flag & SELECT)))) { dist = MAXFRAME * 2; @@ -2218,7 +2258,7 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op) break; } - /* XXX - Should be a generic function. */ + /* XXX: Should be a generic function. */ for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) { if ((iseq->type & SEQ_TYPE_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) { @@ -2237,7 +2277,7 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op) } } - SEQ_sort(scene); + SEQ_sort(SEQ_active_seqbase_get(ed)); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -2374,6 +2414,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op) (LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_FREE_NO_MAIN)); seqbase_clipboard_frame = scene->r.cfra; + SEQ_clipboard_active_seq_name_store(scene); /* Remove anything that references the current scene. */ LISTBASE_FOREACH (Sequence *, seq, &seqbase_clipboard) { @@ -2446,7 +2487,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op) min_seq_startdisp = seq->startdisp; } } - /* Paste strips after playhead. */ + /* Paste strips relative to the current-frame. */ ofs = scene->r.cfra - min_seq_startdisp; } @@ -2464,8 +2505,12 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op) BLI_movelisttolist(ed->seqbasep, &nseqbase); for (iseq = iseq_first; iseq; iseq = iseq->next) { + if (SEQ_clipboard_pasted_seq_was_active(iseq)) { + SEQ_select_active_set(scene, iseq); + } + /* Make sure, that pasted strips have unique names. */ - SEQ_recursive_apply(iseq, apply_unique_name_fn, scene); + SEQ_ensure_unique_name(iseq, scene); /* Translate after name has been changed, otherwise this will affect animdata of original * strip. */ SEQ_transform_translate_sequence(scene, iseq, ofs); @@ -2499,7 +2544,11 @@ void SEQUENCER_OT_paste(wmOperatorType *ot) /* Properties. */ PropertyRNA *prop = RNA_def_boolean( - ot->srna, "keep_offset", false, "Keep Offset", "Keep strip offset to playhead when pasting"); + ot->srna, + "keep_offset", + false, + "Keep Offset", + "Keep strip offset relative to the current frame when pasting"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } @@ -2760,9 +2809,9 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "directory", directory); if (is_relative_path) { - /* TODO, shouldn't this already be relative from the filesel? + /* TODO(campbell): shouldn't this already be relative from the filesel? * (as the 'filepath' is) for now just make relative here, - * but look into changing after 2.60 - campbell */ + * but look into changing after 2.60. */ BLI_path_rel(directory, BKE_main_blendfile_path(bmain)); } BLI_strncpy(seq->strip->dir, directory, sizeof(seq->strip->dir)); @@ -2785,7 +2834,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) RNA_END; } - /* Reset these else we wont see all the images. */ + /* Reset these else we won't see all the images. */ seq->anim_startofs = seq->anim_endofs = 0; /* Correct start/end frames so we don't move. @@ -2940,8 +2989,10 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + /* Only text strips that are not muted and don't end with negative frame. */ SEQ_ALL_BEGIN (ed, seq) { - if (seq->type == SEQ_TYPE_TEXT) { + if ((seq->type == SEQ_TYPE_TEXT) && ((seq->flag & SEQ_MUTE) == 0) && + (seq->enddisp > scene->r.sfra)) { BLI_addtail(&text_seq, MEM_dupallocN(seq)); } } @@ -2962,16 +3013,17 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op) char timecode_str_start[32]; char timecode_str_end[32]; + /* Write time-code relative to start frame of scene. Don't allow negative time-codes. */ BLI_timecode_string_from_time(timecode_str_start, sizeof(timecode_str_start), -2, - FRA2TIME(seq->startdisp), + FRA2TIME(max_ii(seq->startdisp - scene->r.sfra, 0)), FPS, USER_TIMECODE_SUBRIP); BLI_timecode_string_from_time(timecode_str_end, sizeof(timecode_str_end), -2, - FRA2TIME(seq->enddisp), + FRA2TIME(seq->enddisp - scene->r.sfra), FPS, USER_TIMECODE_SUBRIP); @@ -3064,7 +3116,7 @@ static int sequencer_set_range_to_strips_exec(bContext *C, wmOperator *op) scene->r.efra = efra; } - WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); + WM_event_add_notifier(C, NC_SCENE | ND_FRAME_RANGE, scene); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_sequencer/sequencer_proxy.c b/source/blender/editors/space_sequencer/sequencer_proxy.c index df84772aa8c..2dcc2d389d9 100644 --- a/source/blender/editors/space_sequencer/sequencer_proxy.c +++ b/source/blender/editors/space_sequencer/sequencer_proxy.c @@ -99,7 +99,7 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports) return; } - if (selected && !WM_jobs_is_running(wm_job)) { + if (!WM_jobs_is_running(wm_job)) { G.is_break = false; WM_jobs_start(CTX_wm_manager(C), wm_job); } diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index 16768e09cb8..5d857f62b47 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -32,8 +32,8 @@ #include "sequencer_intern.h" -/* XXX, why is this function better than BLI_math version? - * only difference is it does some normalize after, need to double check on this - campbell */ +/* XXX(campbell): why is this function better than BLI_math version? + * only difference is it does some normalize after, need to double check on this. */ static void rgb_to_yuv_normalized(const float rgb[3], float yuv[3]) { yuv[0] = 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2]; @@ -624,8 +624,6 @@ static void vectorscope_put_cross(uchar r, uchar g, uchar b, char *tgt, int w, i { float rgb[3], yuv[3]; char *p; - int x = 0; - int y = 0; rgb[0] = (float)r / 255.0f; rgb[1] = (float)g / 255.0f; @@ -638,8 +636,8 @@ static void vectorscope_put_cross(uchar r, uchar g, uchar b, char *tgt, int w, i r = 255; } - for (y = -size; y <= size; y++) { - for (x = -size; x <= size; x++) { + for (int y = -size; y <= size; y++) { + for (int x = -size; x <= size; x++) { char *q = p + 4 * (y * w + x); q[0] = r; q[1] = g; diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index e08af8f0977..5980bfe37cd 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -42,6 +42,7 @@ #include "SEQ_iterator.h" #include "SEQ_select.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" #include "SEQ_transform.h" /* For menu, popup, icons, etc. */ @@ -533,7 +534,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op) seq = find_nearest_seq(scene, v2d, &hand, mval); - /* XXX - not nice, Ctrl+RMB needs to do side_of_frame only when not over a strip */ + /* XXX: not nice, Ctrl+RMB needs to do side_of_frame only when not over a strip. */ if (seq && linked_time) { side_of_frame = false; } @@ -807,7 +808,7 @@ static bool select_linked_internal(Scene *scene) bool changed = false; LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { - if ((seq->flag & SELECT) != 0) { + if ((seq->flag & SELECT) == 0) { continue; } /* Only get unselected neighbors. */ @@ -1186,8 +1187,8 @@ static int sequencer_select_side_of_frame_exec(bContext *C, wmOperator *op) case 1: test = (timeline_frame <= seq->startdisp); break; - case 0: - test = (timeline_frame <= seq->enddisp) && (timeline_frame >= seq->startdisp); + case 2: + test = SEQ_time_strip_intersects_frame(seq, timeline_frame); break; } @@ -1209,6 +1210,7 @@ void SEQUENCER_OT_select_side_of_frame(wmOperatorType *ot) static const EnumPropertyItem sequencer_select_left_right_types[] = { {-1, "LEFT", 0, "Left", "Select to the left of the current frame"}, {1, "RIGHT", 0, "Right", "Select to the right of the current frame"}, + {2, "CURRENT", 0, "Current Frame", "Select intersecting with the current frame"}, {0, NULL, 0, NULL, NULL}, }; @@ -1621,37 +1623,6 @@ static bool select_grouped_time_overlap(Editing *ed, Sequence *actseq) return changed; } -/* Query all effect strips that are directly or indirectly connected to seq_reference. */ -static void query_strip_effect_chain(Sequence *seq_reference, - ListBase *seqbase, - SeqCollection *collection) -{ - if (!SEQ_collection_append_strip(seq_reference, collection)) { - return; /* Strip is already in set, so all effects connected to it are as well. */ - } - - /* Find all strips that seq_reference is connected to. */ - if (seq_reference->type & SEQ_TYPE_EFFECT) { - if (seq_reference->seq1) { - query_strip_effect_chain(seq_reference->seq1, seqbase, collection); - } - if (seq_reference->seq2) { - query_strip_effect_chain(seq_reference->seq2, seqbase, collection); - } - if (seq_reference->seq3) { - query_strip_effect_chain(seq_reference->seq3, seqbase, collection); - } - } - - /* Find all strips connected to seq_reference. */ - LISTBASE_FOREACH (Sequence *, seq_test, seqbase) { - if (seq_test->seq1 == seq_reference || seq_test->seq2 == seq_reference || - seq_test->seq3 == seq_reference) { - query_strip_effect_chain(seq_test, seqbase, collection); - } - } -} - /* Query strips that are in lower channel and intersect in time with seq_reference. */ static void query_lower_channel_strips(Sequence *seq_reference, ListBase *seqbase, @@ -1681,7 +1652,7 @@ static bool select_grouped_effect_link(Editing *ed, SeqCollection *collection = SEQ_query_selected_strips(seqbase); const int selected_strip_count = BLI_gset_len(collection->set); SEQ_collection_expand(seqbase, collection, query_lower_channel_strips); - SEQ_collection_expand(seqbase, collection, query_strip_effect_chain); + SEQ_collection_expand(seqbase, collection, SEQ_query_strip_effect_chain); /* Check if other strips will be affected. */ const bool changed = BLI_gset_len(collection->set) > selected_strip_count; diff --git a/source/blender/editors/space_spreadsheet/CMakeLists.txt b/source/blender/editors/space_spreadsheet/CMakeLists.txt index b2a0905d4a2..e903feeec1b 100644 --- a/source/blender/editors/space_spreadsheet/CMakeLists.txt +++ b/source/blender/editors/space_spreadsheet/CMakeLists.txt @@ -20,12 +20,14 @@ set(INC ../../blenfont ../../blenkernel ../../blenlib + ../../blentranslation ../../bmesh ../../depsgraph ../../functions ../../gpu ../../makesdna ../../makesrna + ../../nodes ../../windowmanager ../../../../intern/glew-mx ../../../../intern/guardedalloc @@ -33,23 +35,31 @@ set(INC set(SRC space_spreadsheet.cc - spreadsheet_context.cc spreadsheet_column.cc + spreadsheet_context.cc spreadsheet_data_source.cc spreadsheet_data_source_geometry.cc + spreadsheet_dataset_draw.cc + spreadsheet_dataset_layout.cc spreadsheet_draw.cc spreadsheet_layout.cc spreadsheet_ops.cc + spreadsheet_row_filter.cc + spreadsheet_row_filter_ui.cc - spreadsheet_context.hh spreadsheet_cell_value.hh spreadsheet_column.hh spreadsheet_column_values.hh + spreadsheet_context.hh spreadsheet_data_source.hh spreadsheet_data_source_geometry.hh + spreadsheet_dataset_draw.hh + spreadsheet_dataset_layout.hh spreadsheet_draw.hh spreadsheet_intern.hh spreadsheet_layout.hh + spreadsheet_row_filter.hh + spreadsheet_row_filter_ui.hh ) set(LIB diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc index 1f0b5d5d13e..fcc92345bea 100644 --- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc +++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc @@ -47,8 +47,11 @@ #include "spreadsheet_context.hh" #include "spreadsheet_data_source_geometry.hh" +#include "spreadsheet_dataset_draw.hh" #include "spreadsheet_intern.hh" #include "spreadsheet_layout.hh" +#include "spreadsheet_row_filter.hh" +#include "spreadsheet_row_filter_ui.hh" using namespace blender; using namespace blender::ed::spreadsheet; @@ -59,6 +62,8 @@ static SpaceLink *spreadsheet_create(const ScrArea *UNUSED(area), const Scene *U "spreadsheet space"); spreadsheet_space->spacetype = SPACE_SPREADSHEET; + spreadsheet_space->filter_flag = SPREADSHEET_FILTER_ENABLE; + { /* Header. */ ARegion *region = (ARegion *)MEM_callocN(sizeof(ARegion), "spreadsheet header"); @@ -76,6 +81,24 @@ static SpaceLink *spreadsheet_create(const ScrArea *UNUSED(area), const Scene *U } { + /* Dataset Region */ + ARegion *region = (ARegion *)MEM_callocN(sizeof(ARegion), "spreadsheet dataset region"); + BLI_addtail(&spreadsheet_space->regionbase, region); + region->regiontype = RGN_TYPE_CHANNELS; + region->alignment = RGN_ALIGN_LEFT; + region->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM); + } + + { + /* Properties region. */ + ARegion *region = (ARegion *)MEM_callocN(sizeof(ARegion), "spreadsheet right region"); + BLI_addtail(&spreadsheet_space->regionbase, region); + region->regiontype = RGN_TYPE_UI; + region->alignment = RGN_ALIGN_RIGHT; + region->flag = RGN_FLAG_HIDDEN; + } + + { /* Main window. */ ARegion *region = (ARegion *)MEM_callocN(sizeof(ARegion), "spreadsheet main region"); BLI_addtail(&spreadsheet_space->regionbase, region); @@ -88,8 +111,12 @@ static SpaceLink *spreadsheet_create(const ScrArea *UNUSED(area), const Scene *U static void spreadsheet_free(SpaceLink *sl) { SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; + MEM_SAFE_FREE(sspreadsheet->runtime); + LISTBASE_FOREACH_MUTABLE (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) { + spreadsheet_row_filter_free(row_filter); + } LISTBASE_FOREACH_MUTABLE (SpreadsheetColumn *, column, &sspreadsheet->columns) { spreadsheet_column_free(column); } @@ -113,6 +140,11 @@ static SpaceLink *spreadsheet_duplicate(SpaceLink *sl) SpaceSpreadsheet *sspreadsheet_new = (SpaceSpreadsheet *)MEM_dupallocN(sspreadsheet_old); sspreadsheet_new->runtime = (SpaceSpreadsheet_Runtime *)MEM_dupallocN(sspreadsheet_old->runtime); + BLI_listbase_clear(&sspreadsheet_new->row_filters); + LISTBASE_FOREACH (const SpreadsheetRowFilter *, src_filter, &sspreadsheet_old->row_filters) { + SpreadsheetRowFilter *new_filter = spreadsheet_row_filter_copy(src_filter); + BLI_addtail(&sspreadsheet_new->row_filters, new_filter); + } BLI_listbase_clear(&sspreadsheet_new->columns); LISTBASE_FOREACH (SpreadsheetColumn *, src_column, &sspreadsheet_old->columns) { SpreadsheetColumn *new_column = spreadsheet_column_copy(src_column); @@ -128,8 +160,10 @@ static SpaceLink *spreadsheet_duplicate(SpaceLink *sl) return (SpaceLink *)sspreadsheet_new; } -static void spreadsheet_keymap(wmKeyConfig *UNUSED(keyconf)) +static void spreadsheet_keymap(wmKeyConfig *keyconf) { + /* Entire editor only. */ + WM_keymap_ensure(keyconf, "Spreadsheet Generic", SPACE_SPREADSHEET, 0); } static void spreadsheet_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id) @@ -160,11 +194,18 @@ static void spreadsheet_main_region_init(wmWindowManager *wm, ARegion *region) UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy); - wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0); - WM_event_add_keymap_handler(®ion->handlers, keymap); + { + wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0); + WM_event_add_keymap_handler(®ion->handlers, keymap); + } + { + wmKeyMap *keymap = WM_keymap_ensure( + wm->defaultconf, "Spreadsheet Generic", SPACE_SPREADSHEET, 0); + WM_event_add_keymap_handler(®ion->handlers, keymap); + } } -ID *ED_spreadsheet_get_current_id(struct SpaceSpreadsheet *sspreadsheet) +ID *ED_spreadsheet_get_current_id(const struct SpaceSpreadsheet *sspreadsheet) { if (BLI_listbase_is_empty(&sspreadsheet->context_path)) { return nullptr; @@ -181,24 +222,11 @@ ID *ED_spreadsheet_get_current_id(struct SpaceSpreadsheet *sspreadsheet) static void update_pinned_context_path_if_outdated(const bContext *C) { SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); - - /* Currently, this only checks if the object has been deleted. In the future we can have a more - * sophisticated check for the entire context (including modifier and nodes). */ - LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) { - if (context->type == SPREADSHEET_CONTEXT_OBJECT) { - SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context; - if (object_context->object == nullptr) { - ED_spreadsheet_context_path_clear(sspreadsheet); - break; - } - } - } - if (BLI_listbase_is_empty(&sspreadsheet->context_path)) { - Object *active_object = CTX_data_active_object(C); - if (active_object != nullptr) { - SpreadsheetContext *new_context = spreadsheet_context_new(SPREADSHEET_CONTEXT_OBJECT); - ((SpreadsheetContextObject *)new_context)->object = active_object; - BLI_addtail(&sspreadsheet->context_path, new_context); + Main *bmain = CTX_data_main(C); + if (!ED_spreadsheet_context_path_exists(bmain, sspreadsheet)) { + ED_spreadsheet_context_path_guess(C, sspreadsheet); + if (ED_spreadsheet_context_path_update_tag(sspreadsheet)) { + ED_area_tag_redraw(CTX_wm_area(C)); } } @@ -211,28 +239,15 @@ static void update_pinned_context_path_if_outdated(const bContext *C) static void update_context_path_from_context(const bContext *C) { SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); - Object *active_object = CTX_data_active_object(C); - if (active_object == nullptr) { - ED_spreadsheet_context_path_clear(sspreadsheet); - return; - } - if (!BLI_listbase_is_empty(&sspreadsheet->context_path)) { - SpreadsheetContext *root_context = (SpreadsheetContext *)sspreadsheet->context_path.first; - if (root_context->type == SPREADSHEET_CONTEXT_OBJECT) { - SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)root_context; - if (object_context->object != active_object) { - ED_spreadsheet_context_path_clear(sspreadsheet); - } + if (!ED_spreadsheet_context_path_is_active(C, sspreadsheet)) { + ED_spreadsheet_context_path_guess(C, sspreadsheet); + if (ED_spreadsheet_context_path_update_tag(sspreadsheet)) { + ED_area_tag_redraw(CTX_wm_area(C)); } } - if (BLI_listbase_is_empty(&sspreadsheet->context_path)) { - SpreadsheetContext *new_context = spreadsheet_context_new(SPREADSHEET_CONTEXT_OBJECT); - ((SpreadsheetContextObject *)new_context)->object = active_object; - BLI_addtail(&sspreadsheet->context_path, new_context); - } } -static void update_context_path(const bContext *C) +void spreadsheet_update_context_path(const bContext *C) { SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); if (sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) { @@ -243,28 +258,40 @@ static void update_context_path(const bContext *C) } } -static std::unique_ptr<DataSource> get_data_source(const bContext *C) +Object *spreadsheet_get_object_eval(const SpaceSpreadsheet *sspreadsheet, + const Depsgraph *depsgraph) { - Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); ID *used_id = ED_spreadsheet_get_current_id(sspreadsheet); if (used_id == nullptr) { - return {}; + return nullptr; } const ID_Type id_type = GS(used_id->name); if (id_type != ID_OB) { - return {}; + return nullptr; } Object *object_orig = (Object *)used_id; if (!ELEM(object_orig->type, OB_MESH, OB_POINTCLOUD, OB_VOLUME)) { - return {}; + return nullptr; } + Object *object_eval = DEG_get_evaluated_object(depsgraph, object_orig); if (object_eval == nullptr) { - return {}; + return nullptr; } - return data_source_from_geometry(C, object_eval); + return object_eval; +} + +static std::unique_ptr<DataSource> get_data_source(const bContext *C) +{ + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); + + Object *object_eval = spreadsheet_get_object_eval(sspreadsheet, depsgraph); + if (object_eval) { + return data_source_from_geometry(C, object_eval); + } + return {}; } static float get_column_width(const ColumnValues &values) @@ -327,7 +354,7 @@ static void update_visible_columns(ListBase &columns, DataSource &data_source) static void spreadsheet_main_region_draw(const bContext *C, ARegion *region) { SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); - update_context_path(C); + spreadsheet_update_context_path(C); std::unique_ptr<DataSource> data_source = get_data_source(C); if (!data_source) { @@ -346,24 +373,14 @@ static void spreadsheet_main_region_draw(const bContext *C, ARegion *region) const ColumnValues *values = scope.add(std::move(values_ptr), __func__); const int width = get_column_width_in_pixels(*values); spreadsheet_layout.columns.append({values, width}); + + spreadsheet_column_assign_runtime_data(column, values->type(), values->name()); } const int tot_rows = data_source->tot_rows(); spreadsheet_layout.index_column_width = get_index_column_width(tot_rows); - spreadsheet_layout.row_indices = IndexRange(tot_rows).as_span(); - - if (const GeometryDataSource *geometry_data_source = dynamic_cast<const GeometryDataSource *>( - data_source.get())) { - Object *object_eval = geometry_data_source->object_eval(); - Object *object_orig = DEG_get_original_object(object_eval); - if (object_orig->type == OB_MESH) { - if (object_orig->mode == OB_MODE_EDIT) { - if (sspreadsheet->filter_flag & SPREADSHEET_FILTER_SELECTED_ONLY) { - spreadsheet_layout.row_indices = geometry_data_source->get_selected_element_indices(); - } - } - } - } + spreadsheet_layout.row_indices = spreadsheet_filter_rows( + *sspreadsheet, spreadsheet_layout, *data_source, scope); sspreadsheet->runtime->tot_columns = spreadsheet_layout.columns.size(); sspreadsheet->runtime->tot_rows = tot_rows; @@ -372,9 +389,11 @@ static void spreadsheet_main_region_draw(const bContext *C, ARegion *region) std::unique_ptr<SpreadsheetDrawer> drawer = spreadsheet_drawer_from_layout(spreadsheet_layout); draw_spreadsheet_in_region(C, region, *drawer); - /* Tag footer for redraw, because the main region updates data for the footer. */ + /* Tag other regions for redraw, because the main region updates data for them. */ ARegion *footer = BKE_area_find_region_type(CTX_wm_area(C), RGN_TYPE_FOOTER); ED_region_tag_redraw(footer); + ARegion *sidebar = BKE_area_find_region_type(CTX_wm_area(C), RGN_TYPE_UI); + ED_region_tag_redraw(sidebar); } static void spreadsheet_main_region_listener(const wmRegionListenerParams *params) @@ -419,7 +438,7 @@ static void spreadsheet_header_region_init(wmWindowManager *UNUSED(wm), ARegion static void spreadsheet_header_region_draw(const bContext *C, ARegion *region) { - update_context_path(C); + spreadsheet_update_context_path(C); ED_region_header(C, region); } @@ -511,6 +530,77 @@ static void spreadsheet_footer_region_listener(const wmRegionListenerParams *UNU { } +static void spreadsheet_dataset_region_listener(const wmRegionListenerParams *params) +{ + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + + switch (wmn->category) { + case NC_SCENE: { + switch (wmn->data) { + case ND_FRAME: + ED_region_tag_redraw(region); + break; + } + break; + } + case NC_TEXTURE: + ED_region_tag_redraw(region); + break; + } + + spreadsheet_header_region_listener(params); +} + +static void spreadsheet_dataset_region_init(wmWindowManager *wm, ARegion *region) +{ + region->v2d.scroll |= V2D_SCROLL_RIGHT; + region->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP | V2D_SCROLL_BOTTOM); + region->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE; + region->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE; + + UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy); + + wmKeyMap *keymap = WM_keymap_ensure( + wm->defaultconf, "Spreadsheet Generic", SPACE_SPREADSHEET, 0); + WM_event_add_keymap_handler(®ion->handlers, keymap); +} + +static void spreadsheet_dataset_region_draw(const bContext *C, ARegion *region) +{ + spreadsheet_update_context_path(C); + + View2D *v2d = ®ion->v2d; + UI_view2d_view_ortho(v2d); + UI_ThemeClearColor(TH_BACK); + + draw_dataset_in_region(C, region); + + /* reset view matrix */ + UI_view2d_view_restore(C); + + /* scrollers */ + UI_view2d_scrollers_draw(v2d, nullptr); +} + +static void spreadsheet_sidebar_init(wmWindowManager *wm, ARegion *region) +{ + UI_panel_category_active_set_default(region, "Filters"); + ED_region_panels_init(wm, region); + + wmKeyMap *keymap = WM_keymap_ensure( + wm->defaultconf, "Spreadsheet Generic", SPACE_SPREADSHEET, 0); + WM_event_add_keymap_handler(®ion->handlers, keymap); +} + +static void spreadsheet_right_region_free(ARegion *UNUSED(region)) +{ +} + +static void spreadsheet_right_region_listener(const wmRegionListenerParams *UNUSED(params)) +{ +} + void ED_spacetype_spreadsheet(void) { SpaceType *st = (SpaceType *)MEM_callocN(sizeof(SpaceType), "spacetype spreadsheet"); @@ -563,5 +653,30 @@ void ED_spacetype_spreadsheet(void) art->listener = spreadsheet_footer_region_listener; BLI_addhead(&st->regiontypes, art); + /* regions: right panel buttons */ + art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spacetype spreadsheet right region"); + art->regionid = RGN_TYPE_UI; + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; + + art->init = spreadsheet_sidebar_init; + art->layout = ED_region_panels_layout; + art->draw = ED_region_panels_draw; + art->free = spreadsheet_right_region_free; + art->listener = spreadsheet_right_region_listener; + BLI_addhead(&st->regiontypes, art); + + register_row_filter_panels(*art); + + /* regions: channels */ + art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spreadsheet dataset region"); + art->regionid = RGN_TYPE_CHANNELS; + art->prefsizex = 200 + V2D_SCROLL_WIDTH; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D; + art->init = spreadsheet_dataset_region_init; + art->draw = spreadsheet_dataset_region_draw; + art->listener = spreadsheet_dataset_region_listener; + BLI_addhead(&st->regiontypes, art); + BKE_spacetype_register(st); } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh index d1e80f1d87e..c9b73aabf96 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh @@ -50,7 +50,7 @@ class CellValue { std::optional<bool> value_bool; std::optional<float2> value_float2; std::optional<float3> value_float3; - std::optional<Color4f> value_color; + std::optional<ColorGeometry4f> value_color; std::optional<ObjectCellValue> value_object; std::optional<CollectionCellValue> value_collection; }; diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_column.cc b/source/blender/editors/space_spreadsheet/spreadsheet_column.cc index de40545fdae..ee08c86b29f 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_column.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_column.cc @@ -56,16 +56,29 @@ SpreadsheetColumn *spreadsheet_column_new(SpreadsheetColumnID *column_id) return column; } +void spreadsheet_column_assign_runtime_data(SpreadsheetColumn *column, + const eSpreadsheetColumnValueType data_type, + const StringRefNull display_name) +{ + column->data_type = data_type; + MEM_SAFE_FREE(column->display_name); + column->display_name = BLI_strdup(display_name.c_str()); +} + SpreadsheetColumn *spreadsheet_column_copy(const SpreadsheetColumn *src_column) { SpreadsheetColumnID *new_column_id = spreadsheet_column_id_copy(src_column->id); SpreadsheetColumn *new_column = spreadsheet_column_new(new_column_id); + if (src_column->display_name != nullptr) { + new_column->display_name = BLI_strdup(src_column->display_name); + } return new_column; } void spreadsheet_column_free(SpreadsheetColumn *column) { spreadsheet_column_id_free(column->id); + MEM_SAFE_FREE(column->display_name); MEM_freeN(column); } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_column.hh b/source/blender/editors/space_spreadsheet/spreadsheet_column.hh index bb245851d55..1a03278acad 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_column.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_column.hh @@ -43,6 +43,9 @@ void spreadsheet_column_id_free(SpreadsheetColumnID *column_id); SpreadsheetColumn *spreadsheet_column_new(SpreadsheetColumnID *column_id); SpreadsheetColumn *spreadsheet_column_copy(const SpreadsheetColumn *src_column); +void spreadsheet_column_assign_runtime_data(SpreadsheetColumn *column, + const eSpreadsheetColumnValueType data_type, + const StringRefNull display_name); void spreadsheet_column_free(SpreadsheetColumn *column); } // namespace blender::ed::spreadsheet diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh b/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh index 373c988a41c..68370cf6a44 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh @@ -16,6 +16,8 @@ #pragma once +#include "DNA_space_types.h" + #include "BLI_string_ref.hh" #include "spreadsheet_cell_value.hh" @@ -28,11 +30,13 @@ namespace blender::ed::spreadsheet { */ class ColumnValues { protected: + eSpreadsheetColumnValueType type_; std::string name_; int size_; public: - ColumnValues(std::string name, const int size) : name_(std::move(name)), size_(size) + ColumnValues(const eSpreadsheetColumnValueType type, std::string name, const int size) + : type_(type), name_(std::move(name)), size_(size) { } @@ -40,6 +44,11 @@ class ColumnValues { virtual void get_value(int index, CellValue &r_cell_value) const = 0; + eSpreadsheetColumnValueType type() const + { + return type_; + } + StringRefNull name() const { return name_; @@ -60,8 +69,11 @@ template<typename GetValueF> class LambdaColumnValues : public ColumnValues { GetValueF get_value_; public: - LambdaColumnValues(std::string name, int size, GetValueF get_value) - : ColumnValues(std::move(name), size), get_value_(std::move(get_value)) + LambdaColumnValues(const eSpreadsheetColumnValueType type, + std::string name, + int size, + GetValueF get_value) + : ColumnValues(type, std::move(name), size), get_value_(std::move(get_value)) { } @@ -73,13 +85,14 @@ template<typename GetValueF> class LambdaColumnValues : public ColumnValues { /* Utility function that simplifies creating a spreadsheet column from a lambda function. */ template<typename GetValueF> -std::unique_ptr<ColumnValues> column_values_from_function(std::string name, +std::unique_ptr<ColumnValues> column_values_from_function(const eSpreadsheetColumnValueType type, + std::string name, const int size, GetValueF get_value, const float default_width = 0.0f) { std::unique_ptr<ColumnValues> column_values = std::make_unique<LambdaColumnValues<GetValueF>>( - std::move(name), size, std::move(get_value)); + type, std::move(name), size, std::move(get_value)); column_values->default_width = default_width; return column_values; } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_context.cc b/source/blender/editors/space_spreadsheet/spreadsheet_context.cc index 3eb43338908..1ac2075e281 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_context.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_context.cc @@ -24,16 +24,28 @@ #include "BLI_utildefines.h" #include "BLI_vector.hh" +#include "ED_screen.h" #include "ED_spreadsheet.h" #include "DEG_depsgraph.h" +#include "BKE_context.h" #include "BKE_main.h" #include "BKE_modifier.h" +#include "BKE_node.h" #include "BKE_object.h" +#include "BKE_workspace.h" + +#include "DNA_modifier_types.h" +#include "DNA_windowmanager_types.h" #include "spreadsheet_context.hh" +using blender::IndexRange; +using blender::Span; +using blender::StringRef; +using blender::Vector; + namespace blender::ed::spreadsheet { static SpreadsheetContextObject *spreadsheet_context_object_new() @@ -206,28 +218,30 @@ void spreadsheet_context_free(SpreadsheetContext *context) /** * Tag any data relevant to the spreadsheet's context for recalculation in order to collect * information to display in the editor, which may be cached during evaluation. + * \return True when any data has been tagged for update. */ -static void spreadsheet_context_update_tag(SpaceSpreadsheet *sspreadsheet) +static bool spreadsheet_context_update_tag(SpaceSpreadsheet *sspreadsheet) { using namespace blender; Vector<const SpreadsheetContext *> context_path = sspreadsheet->context_path; if (context_path.is_empty()) { - return; + return false; } if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) { - return; + return false; } SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context_path[0]; Object *object = object_context->object; if (object == nullptr) { - return; + return false; } if (context_path.size() == 1) { /* No need to reevaluate, when the final or original object is viewed. */ - return; + return false; } DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY); + return true; } } // namespace blender::ed::spreadsheet @@ -250,30 +264,47 @@ void ED_spreadsheet_context_path_clear(struct SpaceSpreadsheet *sspreadsheet) BLI_listbase_clear(&sspreadsheet->context_path); } -void ED_spreadsheet_context_path_update_tag(SpaceSpreadsheet *sspreadsheet) +bool ED_spreadsheet_context_path_update_tag(SpaceSpreadsheet *sspreadsheet) { - blender::ed::spreadsheet::spreadsheet_context_update_tag(sspreadsheet); + return blender::ed::spreadsheet::spreadsheet_context_update_tag(sspreadsheet); } -uint64_t ED_spreadsheet_context_path_hash(SpaceSpreadsheet *sspreadsheet) +uint64_t ED_spreadsheet_context_path_hash(const SpaceSpreadsheet *sspreadsheet) { BLI_HashMurmur2A mm2; BLI_hash_mm2a_init(&mm2, 1234); - LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) { + LISTBASE_FOREACH (const SpreadsheetContext *, context, &sspreadsheet->context_path) { blender::ed::spreadsheet::spreadsheet_context_hash(context, &mm2); } return BLI_hash_mm2a_end(&mm2); } -void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsheet, - struct SpaceNode *snode, - struct bNode *node) +void ED_spreadsheet_context_path_set_geometry_node(struct SpaceSpreadsheet *sspreadsheet, + struct SpaceNode *snode, + struct bNode *node) { using namespace blender::ed::spreadsheet; - ED_spreadsheet_context_path_clear(sspreadsheet); Object *object = (Object *)snode->id; + /* Try to find the modifier the node tree belongs to. */ ModifierData *modifier = BKE_object_active_modifier(object); + if (modifier && modifier->type != eModifierType_Nodes) { + modifier = nullptr; + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + if (md->type == eModifierType_Nodes) { + NodesModifierData *nmd = (NodesModifierData *)md; + if (nmd->node_group == snode->nodetree) { + modifier = md; + break; + } + } + } + } + if (modifier == nullptr) { + return; + } + + ED_spreadsheet_context_path_clear(sspreadsheet); { SpreadsheetContextObject *context = spreadsheet_context_object_new(); @@ -302,5 +333,251 @@ void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsh BLI_addtail(&sspreadsheet->context_path, context); } - sspreadsheet->object_eval_state = SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED; + sspreadsheet->object_eval_state = SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE; +} + +void ED_spreadsheet_context_paths_set_geometry_node(Main *bmain, SpaceNode *snode, bNode *node) +{ + wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; + if (wm == nullptr) { + return; + } + LISTBASE_FOREACH (wmWindow *, window, &wm->windows) { + bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + SpaceLink *sl = (SpaceLink *)area->spacedata.first; + if (sl->spacetype == SPACE_SPREADSHEET) { + SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; + if ((sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) == 0) { + const uint64_t context_hash_before = ED_spreadsheet_context_path_hash(sspreadsheet); + ED_spreadsheet_context_path_set_geometry_node(sspreadsheet, snode, node); + const uint64_t context_hash_after = ED_spreadsheet_context_path_hash(sspreadsheet); + if (context_hash_before != context_hash_after) { + ED_spreadsheet_context_path_update_tag(sspreadsheet); + } + ED_area_tag_redraw(area); + } + } + } + } +} + +void ED_spreadsheet_context_path_set_evaluated_object(SpaceSpreadsheet *sspreadsheet, + Object *object) +{ + using namespace blender::ed::spreadsheet; + ED_spreadsheet_context_path_clear(sspreadsheet); + + SpreadsheetContextObject *context = spreadsheet_context_object_new(); + context->object = object; + BLI_addtail(&sspreadsheet->context_path, context); +} + +void ED_spreadsheet_context_path_guess(const bContext *C, SpaceSpreadsheet *sspreadsheet) +{ + ED_spreadsheet_context_path_clear(sspreadsheet); + + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; + if (wm == nullptr) { + return; + } + + if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) { + LISTBASE_FOREACH (wmWindow *, window, &wm->windows) { + bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + SpaceLink *sl = (SpaceLink *)area->spacedata.first; + if (sl->spacetype == SPACE_NODE) { + SpaceNode *snode = (SpaceNode *)sl; + if (snode->edittree != nullptr) { + if (snode->edittree->type == NTREE_GEOMETRY) { + LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { + if (node->type == GEO_NODE_VIEWER) { + if (node->flag & NODE_DO_OUTPUT) { + ED_spreadsheet_context_path_set_geometry_node(sspreadsheet, snode, node); + return; + } + } + } + } + } + } + } + } + } + + Object *active_object = CTX_data_active_object(C); + if (active_object != nullptr) { + ED_spreadsheet_context_path_set_evaluated_object(sspreadsheet, active_object); + return; + } +} + +bool ED_spreadsheet_context_path_is_active(const bContext *C, SpaceSpreadsheet *sspreadsheet) +{ + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; + if (wm == nullptr) { + return false; + } + Vector<SpreadsheetContext *> context_path = sspreadsheet->context_path; + if (context_path.is_empty()) { + return false; + } + if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) { + return false; + } + Object *object = ((SpreadsheetContextObject *)context_path[0])->object; + if (object == nullptr) { + return false; + } + if (context_path.size() == 1) { + if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) { + return false; + } + Object *active_object = CTX_data_active_object(C); + return object == active_object; + } + if (sspreadsheet->object_eval_state != SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) { + return false; + } + if (context_path[1]->type != SPREADSHEET_CONTEXT_MODIFIER) { + return false; + } + const char *modifier_name = ((SpreadsheetContextModifier *)context_path[1])->modifier_name; + const ModifierData *modifier = BKE_modifiers_findby_name(object, modifier_name); + if (modifier == nullptr) { + return false; + } + if (!(modifier->flag & eModifierFlag_Active)) { + return false; + } + if (modifier->type != eModifierType_Nodes) { + return false; + } + bNodeTree *root_node_tree = ((NodesModifierData *)modifier)->node_group; + if (root_node_tree == nullptr) { + return false; + } + const Span<SpreadsheetContext *> node_context_path = context_path.as_span().drop_front(2); + if (node_context_path.is_empty()) { + return false; + } + + LISTBASE_FOREACH (wmWindow *, window, &wm->windows) { + bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + SpaceLink *sl = (SpaceLink *)area->spacedata.first; + if (sl->spacetype != SPACE_NODE) { + continue; + } + SpaceNode *snode = (SpaceNode *)sl; + if (snode->nodetree != root_node_tree) { + continue; + } + if (snode->id != &object->id) { + continue; + } + Vector<bNodeTreePath *> tree_path = snode->treepath; + if (node_context_path.size() != tree_path.size()) { + continue; + } + int valid_count = 0; + for (const int i : IndexRange(tree_path.size() - 1)) { + if (node_context_path[i]->type != SPREADSHEET_CONTEXT_NODE) { + break; + } + SpreadsheetContextNode *node_context = (SpreadsheetContextNode *)node_context_path[i]; + if (!STREQ(node_context->node_name, tree_path[i]->node_name)) { + break; + } + valid_count++; + } + if (valid_count != tree_path.size() - 1) { + continue; + } + SpreadsheetContext *last_context = node_context_path.last(); + if (last_context->type != SPREADSHEET_CONTEXT_NODE) { + return false; + } + const char *node_name = ((SpreadsheetContextNode *)last_context)->node_name; + bNode *node = nodeFindNodebyName(snode->edittree, node_name); + if (node == nullptr) { + return false; + } + if (node->type != GEO_NODE_VIEWER) { + return false; + } + if (!(node->flag & NODE_DO_OUTPUT)) { + return false; + } + return true; + } + } + return false; +} + +bool ED_spreadsheet_context_path_exists(Main *UNUSED(bmain), SpaceSpreadsheet *sspreadsheet) +{ + Vector<SpreadsheetContext *> context_path = sspreadsheet->context_path; + if (context_path.is_empty()) { + return false; + } + if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) { + return false; + } + Object *object = ((SpreadsheetContextObject *)context_path[0])->object; + if (object == nullptr) { + return false; + } + if (context_path.size() == 1) { + return true; + } + if (context_path[1]->type != SPREADSHEET_CONTEXT_MODIFIER) { + return false; + } + const char *modifier_name = ((SpreadsheetContextModifier *)context_path[1])->modifier_name; + const ModifierData *modifier = BKE_modifiers_findby_name(object, modifier_name); + if (modifier == nullptr) { + return false; + } + if (modifier->type != eModifierType_Nodes) { + return false; + } + bNodeTree *root_node_tree = ((NodesModifierData *)modifier)->node_group; + if (root_node_tree == nullptr) { + return false; + } + const Span<SpreadsheetContext *> node_context_path = context_path.as_span().drop_front(2); + if (node_context_path.is_empty()) { + return false; + } + bNodeTree *node_tree = root_node_tree; + for (const int i : node_context_path.index_range()) { + if (node_context_path[i]->type != SPREADSHEET_CONTEXT_NODE) { + return false; + } + const char *node_name = ((SpreadsheetContextNode *)node_context_path[i])->node_name; + bNode *node = nodeFindNodebyName(node_tree, node_name); + if (node == nullptr) { + return false; + } + if (node->type == GEO_NODE_VIEWER) { + if (i == node_context_path.index_range().last()) { + return true; + } + return false; + } + if (node->id != nullptr) { + if (GS(node->id->name) != ID_NT) { + return false; + } + node_tree = (bNodeTree *)node->id; + } + else { + return false; + } + } + return false; } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source.hh b/source/blender/editors/space_spreadsheet/spreadsheet_data_source.hh index de47109a144..2ea7fb5809f 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source.hh @@ -54,6 +54,15 @@ class DataSource { } /** + * Returns true if the data source has the ability to limit visible rows + * by user interface selection status. + */ + virtual bool has_selection_filter() const + { + return false; + } + + /** * Returns the number of rows in columns returned by #get_column_values. */ virtual int tot_rows() const diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index 02ffa1259fc..e38c70afd0f 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -31,11 +31,15 @@ #include "ED_spreadsheet.h" +#include "NOD_geometry_nodes_eval_log.hh" + #include "bmesh.h" #include "spreadsheet_data_source_geometry.hh" #include "spreadsheet_intern.hh" +namespace geo_log = blender::nodes::geometry_nodes_eval_log; + namespace blender::ed::spreadsheet { void GeometryDataSource::foreach_default_column_ids( @@ -69,28 +73,35 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( const CustomDataType type = bke::cpp_type_to_custom_data_type(varray->type()); switch (type) { case CD_PROP_FLOAT: - return column_values_from_function( - column_id.name, domain_size, [varray](int index, CellValue &r_cell_value) { - float value; - varray->get(index, &value); - r_cell_value.value_float = value; - }); + return column_values_from_function(SPREADSHEET_VALUE_TYPE_FLOAT, + column_id.name, + domain_size, + [varray](int index, CellValue &r_cell_value) { + float value; + varray->get(index, &value); + r_cell_value.value_float = value; + }); case CD_PROP_INT32: - return column_values_from_function( - column_id.name, domain_size, [varray](int index, CellValue &r_cell_value) { - int value; - varray->get(index, &value); - r_cell_value.value_int = value; - }); + return column_values_from_function(SPREADSHEET_VALUE_TYPE_INT32, + column_id.name, + domain_size, + [varray](int index, CellValue &r_cell_value) { + int value; + varray->get(index, &value); + r_cell_value.value_int = value; + }); case CD_PROP_BOOL: - return column_values_from_function( - column_id.name, domain_size, [varray](int index, CellValue &r_cell_value) { - bool value; - varray->get(index, &value); - r_cell_value.value_bool = value; - }); + return column_values_from_function(SPREADSHEET_VALUE_TYPE_BOOL, + column_id.name, + domain_size, + [varray](int index, CellValue &r_cell_value) { + bool value; + varray->get(index, &value); + r_cell_value.value_bool = value; + }); case CD_PROP_FLOAT2: { return column_values_from_function( + SPREADSHEET_VALUE_TYPE_FLOAT2, column_id.name, domain_size, [varray](int index, CellValue &r_cell_value) { @@ -102,6 +113,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( } case CD_PROP_FLOAT3: { return column_values_from_function( + SPREADSHEET_VALUE_TYPE_FLOAT3, column_id.name, domain_size, [varray](int index, CellValue &r_cell_value) { @@ -113,10 +125,11 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( } case CD_PROP_COLOR: { return column_values_from_function( + SPREADSHEET_VALUE_TYPE_COLOR, column_id.name, domain_size, [varray](int index, CellValue &r_cell_value) { - Color4f value; + ColorGeometry4f value; varray->get(index, &value); r_cell_value.value_color = value; }, @@ -137,55 +150,63 @@ using IsVertexSelectedFn = FunctionRef<bool(int vertex_index)>; static void get_selected_vertex_indices(const Mesh &mesh, const IsVertexSelectedFn is_vertex_selected_fn, - Vector<int64_t> &r_vertex_indices) + MutableSpan<bool> selection) { for (const int i : IndexRange(mesh.totvert)) { - if (is_vertex_selected_fn(i)) { - r_vertex_indices.append(i); + if (!selection[i]) { + continue; + } + if (!is_vertex_selected_fn(i)) { + selection[i] = false; } } } static void get_selected_corner_indices(const Mesh &mesh, const IsVertexSelectedFn is_vertex_selected_fn, - Vector<int64_t> &r_corner_indices) + MutableSpan<bool> selection) { for (const int i : IndexRange(mesh.totloop)) { const MLoop &loop = mesh.mloop[i]; - if (is_vertex_selected_fn(loop.v)) { - r_corner_indices.append(i); + if (!selection[i]) { + continue; + } + if (!is_vertex_selected_fn(loop.v)) { + selection[i] = false; } } } static void get_selected_face_indices(const Mesh &mesh, const IsVertexSelectedFn is_vertex_selected_fn, - Vector<int64_t> &r_face_indices) + MutableSpan<bool> selection) { for (const int poly_index : IndexRange(mesh.totpoly)) { + if (!selection[poly_index]) { + continue; + } const MPoly &poly = mesh.mpoly[poly_index]; - bool is_selected = true; for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { const MLoop &loop = mesh.mloop[loop_index]; if (!is_vertex_selected_fn(loop.v)) { - is_selected = false; + selection[poly_index] = false; break; } } - if (is_selected) { - r_face_indices.append(poly_index); - } } } static void get_selected_edge_indices(const Mesh &mesh, const IsVertexSelectedFn is_vertex_selected_fn, - Vector<int64_t> &r_edge_indices) + MutableSpan<bool> selection) { for (const int i : IndexRange(mesh.totedge)) { + if (!selection[i]) { + continue; + } const MEdge &edge = mesh.medge[i]; - if (is_vertex_selected_fn(edge.v1) && is_vertex_selected_fn(edge.v2)) { - r_edge_indices.append(i); + if (!is_vertex_selected_fn(edge.v1) || !is_vertex_selected_fn(edge.v2)) { + selection[i] = false; } } } @@ -193,30 +214,48 @@ static void get_selected_edge_indices(const Mesh &mesh, static void get_selected_indices_on_domain(const Mesh &mesh, const AttributeDomain domain, const IsVertexSelectedFn is_vertex_selected_fn, - Vector<int64_t> &r_indices) + MutableSpan<bool> selection) { switch (domain) { case ATTR_DOMAIN_POINT: - return get_selected_vertex_indices(mesh, is_vertex_selected_fn, r_indices); + return get_selected_vertex_indices(mesh, is_vertex_selected_fn, selection); case ATTR_DOMAIN_FACE: - return get_selected_face_indices(mesh, is_vertex_selected_fn, r_indices); + return get_selected_face_indices(mesh, is_vertex_selected_fn, selection); case ATTR_DOMAIN_CORNER: - return get_selected_corner_indices(mesh, is_vertex_selected_fn, r_indices); + return get_selected_corner_indices(mesh, is_vertex_selected_fn, selection); case ATTR_DOMAIN_EDGE: - return get_selected_edge_indices(mesh, is_vertex_selected_fn, r_indices); + return get_selected_edge_indices(mesh, is_vertex_selected_fn, selection); default: return; } } -Span<int64_t> GeometryDataSource::get_selected_element_indices() const +/** + * Only data sets corresponding to mesh objects in edit mode currently support selection filtering. + */ +bool GeometryDataSource::has_selection_filter() const +{ + Object *object_orig = DEG_get_original_object(object_eval_); + if (object_orig->type != OB_MESH) { + return false; + } + if (object_orig->mode != OB_MODE_EDIT) { + return false; + } + if (component_->type() != GEO_COMPONENT_TYPE_MESH) { + return false; + } + + return true; +} + +void GeometryDataSource::apply_selection_filter(MutableSpan<bool> rows_included) const { std::lock_guard lock{mutex_}; BLI_assert(object_eval_->mode == OB_MODE_EDIT); BLI_assert(component_->type() == GEO_COMPONENT_TYPE_MESH); Object *object_orig = DEG_get_original_object(object_eval_); - Vector<int64_t> &indices = scope_.construct<Vector<int64_t>>(__func__); const MeshComponent *mesh_component = static_cast<const MeshComponent *>(component_); const Mesh *mesh_eval = mesh_component->get_for_read(); Mesh *mesh_orig = (Mesh *)object_orig->data; @@ -237,7 +276,7 @@ Span<int64_t> GeometryDataSource::get_selected_element_indices() const BMVert *vert = bm->vtable[i_orig]; return BM_elem_flag_test(vert, BM_ELEM_SELECT); }; - get_selected_indices_on_domain(*mesh_eval, domain_, is_vertex_selected, indices); + get_selected_indices_on_domain(*mesh_eval, domain_, is_vertex_selected, rows_included); } else if (mesh_eval->totvert == bm->totvert) { /* Use a simple heuristic to match original vertices to evaluated ones. */ @@ -245,10 +284,8 @@ Span<int64_t> GeometryDataSource::get_selected_element_indices() const BMVert *vert = bm->vtable[vertex_index]; return BM_elem_flag_test(vert, BM_ELEM_SELECT); }; - get_selected_indices_on_domain(*mesh_eval, domain_, is_vertex_selected, indices); + get_selected_indices_on_domain(*mesh_eval, domain_, is_vertex_selected, rows_included); } - - return indices; } void InstancesDataSource::foreach_default_column_ids( @@ -279,7 +316,10 @@ std::unique_ptr<ColumnValues> InstancesDataSource::get_column_values( Span<int> reference_handles = component_->instance_reference_handles(); Span<InstanceReference> references = component_->references(); std::unique_ptr<ColumnValues> values = column_values_from_function( - "Name", size, [reference_handles, references](int index, CellValue &r_cell_value) { + SPREADSHEET_VALUE_TYPE_INSTANCES, + "Name", + size, + [reference_handles, references](int index, CellValue &r_cell_value) { const InstanceReference &reference = references[reference_handles[index]]; switch (reference.type()) { case InstanceReference::Type::Object: { @@ -303,6 +343,7 @@ std::unique_ptr<ColumnValues> InstancesDataSource::get_column_values( Span<float4x4> transforms = component_->instance_transforms(); if (STREQ(column_id.name, "Position")) { return column_values_from_function( + SPREADSHEET_VALUE_TYPE_FLOAT3, column_id.name, size, [transforms](int index, CellValue &r_cell_value) { @@ -312,6 +353,7 @@ std::unique_ptr<ColumnValues> InstancesDataSource::get_column_values( } if (STREQ(column_id.name, "Rotation")) { return column_values_from_function( + SPREADSHEET_VALUE_TYPE_FLOAT3, column_id.name, size, [transforms](int index, CellValue &r_cell_value) { @@ -321,6 +363,7 @@ std::unique_ptr<ColumnValues> InstancesDataSource::get_column_values( } if (STREQ(column_id.name, "Scale")) { return column_values_from_function( + SPREADSHEET_VALUE_TYPE_FLOAT3, column_id.name, size, [transforms](int index, CellValue &r_cell_value) { @@ -332,6 +375,7 @@ std::unique_ptr<ColumnValues> InstancesDataSource::get_column_values( if (STREQ(column_id.name, "ID")) { /* Make the column a bit wider by default, since the IDs tend to be large numbers. */ return column_values_from_function( + SPREADSHEET_VALUE_TYPE_INT32, column_id.name, size, [ids](int index, CellValue &r_cell_value) { r_cell_value.value_int = ids[index]; }, @@ -345,9 +389,9 @@ int InstancesDataSource::tot_rows() const return component_->instances_amount(); } -static GeometrySet get_display_geometry_set(SpaceSpreadsheet *sspreadsheet, - Object *object_eval, - const GeometryComponentType used_component_type) +GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspreadsheet, + Object *object_eval, + const GeometryComponentType used_component_type) { GeometrySet geometry_set; if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL) { @@ -370,7 +414,6 @@ static GeometrySet get_display_geometry_set(SpaceSpreadsheet *sspreadsheet, Mesh *mesh = (Mesh *)object_orig->data; mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly); } - mesh_component.copy_vertex_group_names_from_object(*object_orig); } else if (object_orig->type == OB_POINTCLOUD) { PointCloud *pointcloud = (PointCloud *)object_orig->data; @@ -379,7 +422,7 @@ static GeometrySet get_display_geometry_set(SpaceSpreadsheet *sspreadsheet, pointcloud_component.replace(pointcloud, GeometryOwnershipType::ReadOnly); } } - else if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED) { + else { if (used_component_type == GEO_COMPONENT_TYPE_MESH && object_eval->mode == OB_MODE_EDIT) { Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object_eval, false); if (mesh == nullptr) { @@ -388,7 +431,6 @@ static GeometrySet get_display_geometry_set(SpaceSpreadsheet *sspreadsheet, BKE_mesh_wrapper_ensure_mdata(mesh); MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly); - mesh_component.copy_vertex_group_names_from_object(*object_eval); } else { if (BLI_listbase_count(&sspreadsheet->context_path) == 1) { @@ -398,13 +440,18 @@ static GeometrySet get_display_geometry_set(SpaceSpreadsheet *sspreadsheet, } } else { - if (object_eval->runtime.geometry_set_previews != nullptr) { - GHash *ghash = (GHash *)object_eval->runtime.geometry_set_previews; - const uint64_t key = ED_spreadsheet_context_path_hash(sspreadsheet); - GeometrySet *geometry_set_preview = (GeometrySet *)BLI_ghash_lookup_default( - ghash, POINTER_FROM_UINT(key), nullptr); - if (geometry_set_preview != nullptr) { - geometry_set = *geometry_set_preview; + const geo_log::NodeLog *node_log = + geo_log::ModifierLog::find_node_by_spreadsheet_editor_context(*sspreadsheet); + if (node_log != nullptr) { + for (const geo_log::SocketLog &input_log : node_log->input_logs()) { + if (const geo_log::GeometryValueLog *geo_value_log = + dynamic_cast<const geo_log::GeometryValueLog *>(input_log.value())) { + const GeometrySet *full_geometry = geo_value_log->full_geometry(); + if (full_geometry != nullptr) { + geometry_set = *full_geometry; + break; + } + } } } } @@ -430,7 +477,8 @@ std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); const AttributeDomain domain = (AttributeDomain)sspreadsheet->attribute_domain; const GeometryComponentType component_type = get_display_component_type(C, object_eval); - GeometrySet geometry_set = get_display_geometry_set(sspreadsheet, object_eval, component_type); + GeometrySet geometry_set = spreadsheet_get_display_geometry_set( + sspreadsheet, object_eval, component_type); if (!geometry_set.has(component_type)) { return {}; diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh index 273d39f27bf..d1b5dc6845e 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh @@ -58,7 +58,8 @@ class GeometryDataSource : public DataSource { return object_eval_; } - Span<int64_t> get_selected_element_indices() const; + bool has_selection_filter() const override; + void apply_selection_filter(MutableSpan<bool> rows_included) const; void foreach_default_column_ids( FunctionRef<void(const SpreadsheetColumnID &)> fn) const override; diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc new file mode 100644 index 00000000000..2b31ce7d03c --- /dev/null +++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc @@ -0,0 +1,287 @@ +/* + * 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. + */ + +#include <array> + +#include "DNA_space_types.h" +#include "DNA_windowmanager_types.h" + +#include "BKE_context.h" + +#include "BLF_api.h" + +#include "BLI_rect.h" + +#include "RNA_access.h" + +#include "UI_interface.h" +#include "UI_view2d.h" + +#include "WM_types.h" + +#include "spreadsheet_dataset_draw.hh" +#include "spreadsheet_draw.hh" +#include "spreadsheet_intern.hh" + +static int is_component_row_selected(struct uiBut *but, const void *arg) +{ + SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)arg; + + GeometryComponentType component = (GeometryComponentType)UI_but_datasetrow_component_get(but); + AttributeDomain domain = (AttributeDomain)UI_but_datasetrow_domain_get(but); + + const bool is_component_selected = (GeometryComponentType) + sspreadsheet->geometry_component_type == component; + const bool is_domain_selected = (AttributeDomain)sspreadsheet->attribute_domain == domain; + bool is_selected = is_component_selected && is_domain_selected; + + if (component == GEO_COMPONENT_TYPE_INSTANCES) { + is_selected = is_component_selected; + } + + return is_selected; +} + +namespace blender::ed::spreadsheet { + +/* -------------------------------------------------------------------- */ +/* Draw Context */ + +class DatasetDrawContext { + std::array<int, 2> mval_; + + public: + const SpaceSpreadsheet *sspreadsheet; + Object *object_eval; + /* Current geometry set, changes per component. */ + GeometrySet current_geometry_set; + + DatasetDrawContext(const bContext *C); + + GeometrySet geometry_set_from_component(GeometryComponentType component); + const std::array<int, 2> &cursor_mval() const; +}; + +DatasetDrawContext::DatasetDrawContext(const bContext *C) + : sspreadsheet(CTX_wm_space_spreadsheet(C)), + object_eval(spreadsheet_get_object_eval(sspreadsheet, CTX_data_depsgraph_pointer(C))) +{ + const wmWindow *win = CTX_wm_window(C); + const ARegion *region = CTX_wm_region(C); + mval_ = {win->eventstate->x - region->winrct.xmin, win->eventstate->y - region->winrct.ymin}; +} + +GeometrySet DatasetDrawContext::geometry_set_from_component(GeometryComponentType component) +{ + return spreadsheet_get_display_geometry_set(sspreadsheet, object_eval, component); +} + +const std::array<int, 2> &DatasetDrawContext::cursor_mval() const +{ + return mval_; +} + +/* -------------------------------------------------------------------- */ +/* Drawer */ + +DatasetRegionDrawer::DatasetRegionDrawer(const ARegion *region, + uiBlock &block, + DatasetDrawContext &draw_context) + : row_height(UI_UNIT_Y), + xmin(region->v2d.cur.xmin), + xmax(region->v2d.cur.xmax), + block(block), + v2d(region->v2d), + draw_context(draw_context) +{ +} + +void DatasetRegionDrawer::draw_hierarchy(const DatasetLayoutHierarchy &layout) +{ + for (const DatasetComponentLayoutInfo &component : layout.components) { + draw_context.current_geometry_set = draw_context.geometry_set_from_component(component.type); + + draw_component_row(component); + + /* Iterate attribute domains, skip unset ones (storage has to be in a enum-based, fixed size + * array so uses optionals to support skipping enum values that shouldn't be displayed for a + * component). */ + for (const auto &optional_domain : component.attr_domains) { + if (!optional_domain) { + continue; + } + + const DatasetAttrDomainLayoutInfo &domain_info = *optional_domain; + draw_attribute_domain_row(component, domain_info); + } + } +} + +static int element_count_from_instances(const GeometrySet &geometry_set) +{ + if (geometry_set.has_instances()) { + const InstancesComponent *instances_component = + geometry_set.get_component_for_read<InstancesComponent>(); + return instances_component->instances_amount(); + } + return 0; +} + +static int element_count_from_component_domain(const GeometrySet &geometry_set, + GeometryComponentType component, + AttributeDomain domain) +{ + if (geometry_set.has_mesh() && component == GEO_COMPONENT_TYPE_MESH) { + const MeshComponent *mesh_component = geometry_set.get_component_for_read<MeshComponent>(); + return mesh_component->attribute_domain_size(domain); + } + + if (geometry_set.has_pointcloud() && component == GEO_COMPONENT_TYPE_POINT_CLOUD) { + const PointCloudComponent *point_cloud_component = + geometry_set.get_component_for_read<PointCloudComponent>(); + return point_cloud_component->attribute_domain_size(domain); + } + + if (geometry_set.has_volume() && component == GEO_COMPONENT_TYPE_VOLUME) { + const VolumeComponent *volume_component = + geometry_set.get_component_for_read<VolumeComponent>(); + return volume_component->attribute_domain_size(domain); + } + + if (geometry_set.has_curve() && component == GEO_COMPONENT_TYPE_CURVE) { + const CurveComponent *curve_component = geometry_set.get_component_for_read<CurveComponent>(); + return curve_component->attribute_domain_size(domain); + } + + return 0; +} + +void DatasetRegionDrawer::draw_dataset_row(const int indentation, + const GeometryComponentType component, + const std::optional<AttributeDomain> domain, + BIFIconID icon, + const char *label, + const bool is_active) +{ + + const float row_height = UI_UNIT_Y; + const float padding_x = UI_UNIT_X * 0.25f; + + const rctf rect = {float(xmin) + padding_x, + float(xmax) - V2D_SCROLL_HANDLE_WIDTH, + ymin_offset - row_height, + ymin_offset}; + + char element_count[7]; + if (component == GEO_COMPONENT_TYPE_INSTANCES) { + BLI_str_format_attribute_domain_size( + element_count, element_count_from_instances(draw_context.current_geometry_set)); + } + else { + BLI_str_format_attribute_domain_size( + element_count, + domain ? element_count_from_component_domain( + draw_context.current_geometry_set, component, *domain) : + 0); + } + + std::string label_and_element_count = label; + label_and_element_count += UI_SEP_CHAR; + label_and_element_count += element_count; + + uiBut *bt = uiDefIconTextButO(&block, + UI_BTYPE_DATASETROW, + "SPREADSHEET_OT_change_spreadsheet_data_source", + 0, + icon, + label, + rect.xmin, + rect.ymin, + BLI_rctf_size_x(&rect), + BLI_rctf_size_y(&rect), + nullptr); + + UI_but_datasetrow_indentation_set(bt, indentation); + + if (is_active) { + UI_but_hint_drawstr_set(bt, element_count); + UI_but_datasetrow_component_set(bt, component); + if (domain) { + UI_but_datasetrow_domain_set(bt, *domain); + } + UI_but_func_pushed_state_set(bt, &is_component_row_selected, draw_context.sspreadsheet); + + PointerRNA *but_ptr = UI_but_operator_ptr_get((uiBut *)bt); + RNA_int_set(but_ptr, "component_type", component); + if (domain) { + RNA_int_set(but_ptr, "attribute_domain_type", *domain); + } + } + + ymin_offset -= row_height; +} + +void DatasetRegionDrawer::draw_component_row(const DatasetComponentLayoutInfo &component_info) +{ + if (component_info.type == GEO_COMPONENT_TYPE_INSTANCES) { + draw_dataset_row( + 0, component_info.type, std::nullopt, component_info.icon, component_info.label, true); + } + else { + draw_dataset_row( + 0, component_info.type, std::nullopt, component_info.icon, component_info.label, false); + } +} + +void DatasetRegionDrawer::draw_attribute_domain_row( + const DatasetComponentLayoutInfo &component_info, + const DatasetAttrDomainLayoutInfo &domain_info) +{ + draw_dataset_row( + 1, component_info.type, domain_info.type, domain_info.icon, domain_info.label, true); +} + +/* -------------------------------------------------------------------- */ +/* Drawer */ + +void draw_dataset_in_region(const bContext *C, ARegion *region) +{ + DatasetDrawContext draw_context{C}; + if (!draw_context.object_eval) { + /* No object means nothing to display. Keep the region empty. */ + return; + } + + uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS); + + DatasetRegionDrawer drawer{region, *block, draw_context}; + + /* Start with an offset to align buttons to spreadsheet rows. Use spreadsheet drawing info for + * that. */ + drawer.ymin_offset = -SpreadsheetDrawer().top_row_height + drawer.row_height; + + const DatasetLayoutHierarchy hierarchy = dataset_layout_hierarchy(); + drawer.draw_hierarchy(hierarchy); +#ifndef NDEBUG + dataset_layout_hierarchy_sanity_check(hierarchy); +#endif + + UI_block_end(C, block); + UI_view2d_totRect_set(®ion->v2d, region->winx, abs(drawer.ymin_offset)); + UI_block_draw(C, block); +} + +} // namespace blender::ed::spreadsheet diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh new file mode 100644 index 00000000000..d9e6d882c2a --- /dev/null +++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh @@ -0,0 +1,64 @@ +/* + * 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. + */ + +#pragma once + +#include <array> + +#include "BKE_geometry_set.hh" +#include "UI_interface.h" +#include "spreadsheet_dataset_layout.hh" + +struct ARegion; +struct uiBlock; +struct View2D; +struct bContext; + +namespace blender::ed::spreadsheet { + +class DatasetDrawContext; + +class DatasetRegionDrawer { + public: + const int row_height; + float ymin_offset = 0; + + int xmin; + int xmax; + uiBlock █ + const View2D &v2d; + DatasetDrawContext &draw_context; + + DatasetRegionDrawer(const ARegion *region, uiBlock &block, DatasetDrawContext &draw_context); + + void draw_hierarchy(const DatasetLayoutHierarchy &layout); + + void draw_attribute_domain_row(const DatasetComponentLayoutInfo &component, + const DatasetAttrDomainLayoutInfo &domain_info); + void draw_component_row(const DatasetComponentLayoutInfo &component_info); + + private: + void draw_dataset_row(const int indentation, + const GeometryComponentType component, + const std::optional<AttributeDomain> domain, + const BIFIconID icon, + const char *label, + const bool is_active); +}; + +void draw_dataset_in_region(const bContext *C, ARegion *region); + +} // namespace blender::ed::spreadsheet diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc new file mode 100644 index 00000000000..abbad8c7088 --- /dev/null +++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc @@ -0,0 +1,112 @@ +/* + * 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. + */ + +#include <optional> + +#include "BLI_span.hh" + +#include "BLT_translation.h" + +#include "spreadsheet_dataset_layout.hh" + +namespace blender::ed::spreadsheet { + +#define ATTR_INFO(type, label, icon) \ + std::optional<DatasetAttrDomainLayoutInfo> \ + { \ + std::in_place, type, label, icon \ + } +#define ATTR_INFO_NONE(type) \ + { \ + std::nullopt \ + } + +/** + * Definition for the component->attribute-domain hierarchy. + * Constructed at compile time. + * + * \warning Order of attribute-domains matters! It __must__ match the #AttributeDomain + * definition and fill gaps with unset optionals (i.e. `std::nullopt`). Would be nice to use + * array designators for this (which C++ doesn't support). + */ +constexpr DatasetComponentLayoutInfo DATASET_layout_hierarchy[] = { + { + GEO_COMPONENT_TYPE_MESH, + N_("Mesh"), + ICON_MESH_DATA, + { + ATTR_INFO(ATTR_DOMAIN_POINT, N_("Vertex"), ICON_VERTEXSEL), + ATTR_INFO(ATTR_DOMAIN_EDGE, N_("Edge"), ICON_EDGESEL), + ATTR_INFO(ATTR_DOMAIN_FACE, N_("Face"), ICON_FACESEL), + ATTR_INFO(ATTR_DOMAIN_CORNER, N_("Face Corner"), ICON_NODE_CORNER), + }, + }, + { + GEO_COMPONENT_TYPE_CURVE, + N_("Curves"), + ICON_CURVE_DATA, + { + ATTR_INFO(ATTR_DOMAIN_POINT, N_("Control Point"), ICON_CURVE_BEZCIRCLE), + ATTR_INFO_NONE(ATTR_DOMAIN_EDGE), + ATTR_INFO_NONE(ATTR_DOMAIN_CORNER), + ATTR_INFO_NONE(ATTR_DOMAIN_FACE), + ATTR_INFO(ATTR_DOMAIN_CURVE, N_("Spline"), ICON_CURVE_PATH), + }, + }, + { + GEO_COMPONENT_TYPE_POINT_CLOUD, + N_("Point Cloud"), + ICON_POINTCLOUD_DATA, + { + ATTR_INFO(ATTR_DOMAIN_POINT, N_("Point"), ICON_PARTICLE_POINT), + }, + }, + { + GEO_COMPONENT_TYPE_INSTANCES, + N_("Instances"), + ICON_EMPTY_AXIS, + {}, + }, +}; + +#undef ATTR_INFO +#undef ATTR_INFO_LABEL + +DatasetLayoutHierarchy dataset_layout_hierarchy() +{ + return DatasetLayoutHierarchy{ + Span{DATASET_layout_hierarchy, ARRAY_SIZE(DATASET_layout_hierarchy)}}; +} + +#ifndef NDEBUG +/** + * Debug-only sanity check for correct attribute domain initialization (order/indices must + * match AttributeDomain). This doesn't check for all possible missuses, but should catch the most + * likely mistakes. + */ +void dataset_layout_hierarchy_sanity_check(const DatasetLayoutHierarchy &hierarchy) +{ + for (const DatasetComponentLayoutInfo &component : hierarchy.components) { + for (uint i = 0; i < component.attr_domains.size(); i++) { + if (component.attr_domains[i]) { + BLI_assert(component.attr_domains[i]->type == static_cast<AttributeDomain>(i)); + } + } + } +} +#endif + +} // namespace blender::ed::spreadsheet diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.hh b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.hh new file mode 100644 index 00000000000..d463739a0fa --- /dev/null +++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.hh @@ -0,0 +1,68 @@ +/* + * 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. + */ + +#pragma once + +#include <array> +#include <optional> + +/* Enum definitions... */ +#include "BKE_attribute.h" +#include "BKE_geometry_set.h" + +#include "BLI_span.hh" + +/* More enum definitions... */ +#include "UI_resources.h" + +#pragma once + +namespace blender::ed::spreadsheet { + +struct DatasetAttrDomainLayoutInfo { + AttributeDomain type; + const char *label; + BIFIconID icon; + + constexpr DatasetAttrDomainLayoutInfo(AttributeDomain type, const char *label, BIFIconID icon) + : type(type), label(label), icon(icon) + { + } +}; + +struct DatasetComponentLayoutInfo { + GeometryComponentType type; + const char *label; + BIFIconID icon; + /** Array of attribute-domains. Has to be fixed size based on #AttributeDomain enum, but not all + * values need displaying for all parent components. Hence the optional use. */ + using AttrDomainArray = std::array<std::optional<DatasetAttrDomainLayoutInfo>, ATTR_DOMAIN_NUM>; + const AttrDomainArray attr_domains; +}; + +struct DatasetLayoutHierarchy { + /** The components for display (with layout info like icon and label). Each component stores + * the attribute domains it wants to display (also with layout info like icon and label). */ + const Span<DatasetComponentLayoutInfo> components; +}; + +DatasetLayoutHierarchy dataset_layout_hierarchy(); + +#ifndef NDEBUG +void dataset_layout_hierarchy_sanity_check(const DatasetLayoutHierarchy &hierarchy); +#endif + +} // namespace blender::ed::spreadsheet diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_intern.hh b/source/blender/editors/space_spreadsheet/spreadsheet_intern.hh index 7e3b79a6706..8be5283fd63 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_intern.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_intern.hh @@ -16,10 +16,23 @@ #pragma once +#include "BKE_geometry_set.hh" + typedef struct SpaceSpreadsheet_Runtime { int visible_rows; int tot_rows; int tot_columns; } SpaceSpreadsheet_Runtime; +struct bContext; + void spreadsheet_operatortypes(void); +void spreadsheet_update_context_path(const bContext *C); +Object *spreadsheet_get_object_eval(const SpaceSpreadsheet *sspreadsheet, + const Depsgraph *depsgraph); + +namespace blender::ed::spreadsheet { +GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspreadsheet, + Object *object_eval, + const GeometryComponentType used_component_type); +} diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc index f1ca65817f6..8079763a339 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc @@ -170,7 +170,7 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer { this->draw_float_vector(params, Span(&value.x, 3)); } else if (cell_value.value_color.has_value()) { - const Color4f value = *cell_value.value_color; + const ColorGeometry4f value = *cell_value.value_color; this->draw_float_vector(params, Span(&value.r, 4)); } else if (cell_value.value_object.has_value()) { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_ops.cc b/source/blender/editors/space_spreadsheet/spreadsheet_ops.cc index 770bd207e8d..11ed88b7dc9 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_ops.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_ops.cc @@ -13,9 +13,137 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "BKE_screen.h" + +#include "DNA_space_types.h" + +#include "ED_screen.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "BLI_listbase.h" + +#include "MEM_guardedalloc.h" + +#include "BKE_context.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "ED_screen.h" + +#include "WM_api.h" +#include "WM_types.h" #include "spreadsheet_intern.hh" +#include "spreadsheet_row_filter.hh" + +using namespace blender::ed::spreadsheet; + +static int row_filter_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); + + SpreadsheetRowFilter *row_filter = spreadsheet_row_filter_new(); + BLI_addtail(&sspreadsheet->row_filters, row_filter); + + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SPREADSHEET, sspreadsheet); + + return OPERATOR_FINISHED; +} + +static void SPREADSHEET_OT_add_row_filter_rule(wmOperatorType *ot) +{ + ot->name = "Add Row Filter"; + ot->description = "Add a filter to remove rows from the displayed data"; + ot->idname = "SPREADSHEET_OT_add_row_filter_rule"; + + ot->exec = row_filter_add_exec; + ot->poll = ED_operator_spreadsheet_active; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int row_filter_remove_exec(bContext *C, wmOperator *op) +{ + SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); + + SpreadsheetRowFilter *row_filter = (SpreadsheetRowFilter *)BLI_findlink( + &sspreadsheet->row_filters, RNA_int_get(op->ptr, "index")); + if (row_filter == nullptr) { + return OPERATOR_CANCELLED; + } + + BLI_remlink(&sspreadsheet->row_filters, row_filter); + spreadsheet_row_filter_free(row_filter); + + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SPREADSHEET, sspreadsheet); + + return OPERATOR_FINISHED; +} + +static void SPREADSHEET_OT_remove_row_filter_rule(wmOperatorType *ot) +{ + ot->name = "Remove Row Filter"; + ot->description = "Remove a row filter from the rules"; + ot->idname = "SPREADSHEET_OT_remove_row_filter_rule"; + + ot->exec = row_filter_remove_exec; + ot->poll = ED_operator_spreadsheet_active; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX); +} + +static int select_component_domain_invoke(bContext *C, + wmOperator *op, + const wmEvent *UNUSED(event)) +{ + GeometryComponentType component_type = static_cast<GeometryComponentType>( + RNA_int_get(op->ptr, "component_type")); + AttributeDomain attribute_domain = static_cast<AttributeDomain>( + RNA_int_get(op->ptr, "attribute_domain_type")); + + SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); + sspreadsheet->geometry_component_type = component_type; + sspreadsheet->attribute_domain = attribute_domain; + + /* Refresh header and main region. */ + WM_main_add_notifier(NC_SPACE | ND_SPACE_SPREADSHEET, nullptr); + + return OPERATOR_FINISHED; +} + +static void SPREADSHEET_OT_change_spreadsheet_data_source(wmOperatorType *ot) +{ + ot->name = "Change Visible Data Source"; + ot->description = "Change visible data source in the spreadsheet"; + ot->idname = "SPREADSHEET_OT_change_spreadsheet_data_source"; + + ot->invoke = select_component_domain_invoke; + + RNA_def_int(ot->srna, "component_type", 0, 0, INT16_MAX, "Component Type", "", 0, INT16_MAX); + RNA_def_int(ot->srna, + "attribute_domain_type", + 0, + 0, + INT16_MAX, + "Attribute Domain Type", + "", + 0, + INT16_MAX); + + ot->flag = OPTYPE_INTERNAL; +} void spreadsheet_operatortypes() { + WM_operatortype_append(SPREADSHEET_OT_add_row_filter_rule); + WM_operatortype_append(SPREADSHEET_OT_remove_row_filter_rule); + WM_operatortype_append(SPREADSHEET_OT_change_spreadsheet_data_source); } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc new file mode 100644 index 00000000000..ae336edfead --- /dev/null +++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc @@ -0,0 +1,366 @@ +/* + * 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. + */ + +#include <cstring> + +#include "BLI_listbase.h" + +#include "DNA_collection_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" + +#include "DEG_depsgraph_query.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "RNA_access.h" + +#include "spreadsheet_intern.hh" + +#include "spreadsheet_data_source_geometry.hh" +#include "spreadsheet_intern.hh" +#include "spreadsheet_layout.hh" +#include "spreadsheet_row_filter.hh" + +namespace blender::ed::spreadsheet { + +template<typename OperationFn> +static void apply_filter_operation(const ColumnValues &values, + OperationFn check_fn, + MutableSpan<bool> rows_included) +{ + for (const int i : rows_included.index_range()) { + if (!rows_included[i]) { + continue; + } + CellValue cell_value; + values.get_value(i, cell_value); + if (!check_fn(cell_value)) { + rows_included[i] = false; + } + } +} + +static void apply_row_filter(const SpreadsheetLayout &spreadsheet_layout, + const SpreadsheetRowFilter &row_filter, + MutableSpan<bool> rows_included) +{ + for (const ColumnLayout &column : spreadsheet_layout.columns) { + const ColumnValues &values = *column.values; + if (values.name() != row_filter.column_name) { + continue; + } + + switch (values.type()) { + case SPREADSHEET_VALUE_TYPE_INT32: { + const int value = row_filter.value_int; + switch (row_filter.operation) { + case SPREADSHEET_ROW_FILTER_EQUAL: { + apply_filter_operation( + values, + [value](const CellValue &cell_value) -> bool { + return *cell_value.value_int == value; + }, + rows_included); + break; + } + case SPREADSHEET_ROW_FILTER_GREATER: { + apply_filter_operation( + values, + [value](const CellValue &cell_value) -> bool { + return *cell_value.value_int > value; + }, + rows_included); + break; + } + case SPREADSHEET_ROW_FILTER_LESS: { + apply_filter_operation( + values, + [value](const CellValue &cell_value) -> bool { + return *cell_value.value_int < value; + }, + rows_included); + break; + } + } + break; + } + case SPREADSHEET_VALUE_TYPE_FLOAT: { + const float value = row_filter.value_float; + switch (row_filter.operation) { + case SPREADSHEET_ROW_FILTER_EQUAL: { + const float threshold = row_filter.threshold; + apply_filter_operation( + values, + [value, threshold](const CellValue &cell_value) -> bool { + return std::abs(*cell_value.value_float - value) < threshold; + }, + rows_included); + break; + } + case SPREADSHEET_ROW_FILTER_GREATER: { + apply_filter_operation( + values, + [value](const CellValue &cell_value) -> bool { + return *cell_value.value_float > value; + }, + rows_included); + break; + } + case SPREADSHEET_ROW_FILTER_LESS: { + apply_filter_operation( + values, + [value](const CellValue &cell_value) -> bool { + return *cell_value.value_float < value; + }, + rows_included); + break; + } + } + break; + } + case SPREADSHEET_VALUE_TYPE_FLOAT2: { + const float2 value = row_filter.value_float2; + switch (row_filter.operation) { + case SPREADSHEET_ROW_FILTER_EQUAL: { + const float threshold_squared = row_filter.threshold * row_filter.threshold; + apply_filter_operation( + values, + [value, threshold_squared](const CellValue &cell_value) -> bool { + return float2::distance_squared(*cell_value.value_float2, value) < + threshold_squared; + }, + rows_included); + break; + } + case SPREADSHEET_ROW_FILTER_GREATER: { + apply_filter_operation( + values, + [value](const CellValue &cell_value) -> bool { + return cell_value.value_float2->x > value.x && + cell_value.value_float2->y > value.y; + }, + rows_included); + break; + } + case SPREADSHEET_ROW_FILTER_LESS: { + apply_filter_operation( + values, + [value](const CellValue &cell_value) -> bool { + return cell_value.value_float2->x < value.x && + cell_value.value_float2->y < value.y; + }, + rows_included); + break; + } + } + break; + } + case SPREADSHEET_VALUE_TYPE_FLOAT3: { + const float3 value = row_filter.value_float3; + switch (row_filter.operation) { + case SPREADSHEET_ROW_FILTER_EQUAL: { + const float threshold_squared = row_filter.threshold * row_filter.threshold; + apply_filter_operation( + values, + [value, threshold_squared](const CellValue &cell_value) -> bool { + return float3::distance_squared(*cell_value.value_float3, value) < + threshold_squared; + }, + rows_included); + break; + } + case SPREADSHEET_ROW_FILTER_GREATER: { + apply_filter_operation( + values, + [value](const CellValue &cell_value) -> bool { + return cell_value.value_float3->x > value.x && + cell_value.value_float3->y > value.y && + cell_value.value_float3->z > value.z; + }, + rows_included); + break; + } + case SPREADSHEET_ROW_FILTER_LESS: { + apply_filter_operation( + values, + [value](const CellValue &cell_value) -> bool { + return cell_value.value_float3->x < value.x && + cell_value.value_float3->y < value.y && + cell_value.value_float3->z < value.z; + }, + rows_included); + break; + } + } + break; + } + case SPREADSHEET_VALUE_TYPE_COLOR: { + const ColorGeometry4f value = row_filter.value_color; + switch (row_filter.operation) { + case SPREADSHEET_ROW_FILTER_EQUAL: { + const float threshold_squared = row_filter.threshold * row_filter.threshold; + apply_filter_operation( + values, + [value, threshold_squared](const CellValue &cell_value) -> bool { + return len_squared_v4v4(value, *cell_value.value_color) < threshold_squared; + }, + rows_included); + break; + } + } + break; + } + case SPREADSHEET_VALUE_TYPE_BOOL: { + const bool value = (row_filter.flag & SPREADSHEET_ROW_FILTER_BOOL_VALUE) != 0; + apply_filter_operation( + values, + [value](const CellValue &cell_value) -> bool { + return *cell_value.value_bool == value; + }, + rows_included); + break; + } + case SPREADSHEET_VALUE_TYPE_INSTANCES: { + const StringRef value = row_filter.value_string; + apply_filter_operation( + values, + [value](const CellValue &cell_value) -> bool { + const ID *id = nullptr; + if (cell_value.value_object) { + id = &cell_value.value_object->object->id; + } + else if (cell_value.value_collection) { + id = &cell_value.value_collection->collection->id; + } + if (id == nullptr) { + return false; + } + + return value == id->name + 2; + }, + rows_included); + break; + } + default: + break; + } + + /* Only one column should have this name. */ + break; + } +} + +static void index_vector_from_bools(Span<bool> selection, Vector<int64_t> &indices) +{ + for (const int i : selection.index_range()) { + if (selection[i]) { + indices.append(i); + } + } +} + +static bool use_row_filters(const SpaceSpreadsheet &sspreadsheet) +{ + if (!(sspreadsheet.filter_flag & SPREADSHEET_FILTER_ENABLE)) { + return false; + } + if (BLI_listbase_is_empty(&sspreadsheet.row_filters)) { + return false; + } + return true; +} + +static bool use_selection_filter(const SpaceSpreadsheet &sspreadsheet, + const DataSource &data_source) +{ + if (!(sspreadsheet.filter_flag & SPREADSHEET_FILTER_SELECTED_ONLY)) { + return false; + } + if (!data_source.has_selection_filter()) { + return false; + } + return true; +} + +Span<int64_t> spreadsheet_filter_rows(const SpaceSpreadsheet &sspreadsheet, + const SpreadsheetLayout &spreadsheet_layout, + const DataSource &data_source, + ResourceScope &scope) +{ + const int tot_rows = data_source.tot_rows(); + + const bool use_selection = use_selection_filter(sspreadsheet, data_source); + const bool use_filters = use_row_filters(sspreadsheet); + + /* Avoid allocating an array if no row filtering is necessary. */ + if (!(use_filters || use_selection)) { + return IndexRange(tot_rows).as_span(); + } + + Array<bool> rows_included(tot_rows, true); + + if (use_filters) { + LISTBASE_FOREACH (const SpreadsheetRowFilter *, row_filter, &sspreadsheet.row_filters) { + if (row_filter->flag & SPREADSHEET_ROW_FILTER_ENABLED) { + apply_row_filter(spreadsheet_layout, *row_filter, rows_included); + } + } + } + + if (use_selection) { + const GeometryDataSource *geometry_data_source = dynamic_cast<const GeometryDataSource *>( + &data_source); + geometry_data_source->apply_selection_filter(rows_included); + } + + Vector<int64_t> &indices = scope.construct<Vector<int64_t>>(__func__); + index_vector_from_bools(rows_included, indices); + + return indices; +} + +SpreadsheetRowFilter *spreadsheet_row_filter_new() +{ + SpreadsheetRowFilter *row_filter = (SpreadsheetRowFilter *)MEM_callocN( + sizeof(SpreadsheetRowFilter), __func__); + row_filter->flag = (SPREADSHEET_ROW_FILTER_UI_EXPAND | SPREADSHEET_ROW_FILTER_ENABLED); + row_filter->operation = SPREADSHEET_ROW_FILTER_LESS; + row_filter->threshold = 0.01f; + row_filter->column_name[0] = '\0'; + + return row_filter; +} + +SpreadsheetRowFilter *spreadsheet_row_filter_copy(const SpreadsheetRowFilter *src_row_filter) +{ + SpreadsheetRowFilter *new_filter = spreadsheet_row_filter_new(); + + memcpy(new_filter, src_row_filter, sizeof(SpreadsheetRowFilter)); + new_filter->next = nullptr; + new_filter->prev = nullptr; + + return new_filter; +} + +void spreadsheet_row_filter_free(SpreadsheetRowFilter *row_filter) +{ + MEM_SAFE_FREE(row_filter->value_string); + MEM_freeN(row_filter); +} + +} // namespace blender::ed::spreadsheet diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.hh b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.hh new file mode 100644 index 00000000000..0a5783e318d --- /dev/null +++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.hh @@ -0,0 +1,35 @@ +/* + * 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. + */ + +#pragma once + +#include "BLI_resource_scope.hh" + +#include "spreadsheet_data_source.hh" +#include "spreadsheet_layout.hh" + +namespace blender::ed::spreadsheet { + +Span<int64_t> spreadsheet_filter_rows(const SpaceSpreadsheet &sspreadsheet, + const SpreadsheetLayout &spreadsheet_layout, + const DataSource &data_source, + ResourceScope &scope); + +SpreadsheetRowFilter *spreadsheet_row_filter_new(); +SpreadsheetRowFilter *spreadsheet_row_filter_copy(const SpreadsheetRowFilter *src_row_filter); +void spreadsheet_row_filter_free(SpreadsheetRowFilter *row_filter); + +} // namespace blender::ed::spreadsheet diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc new file mode 100644 index 00000000000..219d03c1dcd --- /dev/null +++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc @@ -0,0 +1,347 @@ +/* + * 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. + */ + +#include <cstring> + +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_string_ref.hh" + +#include "DNA_screen_types.h" +#include "DNA_space_types.h" + +#include "BKE_screen.h" + +#include "RNA_access.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "BLT_translation.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "spreadsheet_column.hh" +#include "spreadsheet_intern.hh" +#include "spreadsheet_row_filter.hh" +#include "spreadsheet_row_filter_ui.hh" + +using namespace blender; +using namespace blender::ed::spreadsheet; + +static void filter_panel_id_fn(void *UNUSED(row_filter_v), char *r_name) +{ + /* All row filters use the same panel ID. */ + BLI_snprintf(r_name, BKE_ST_MAXNAME, "SPREADSHEET_PT_filter"); +} + +static std::string operation_string(const eSpreadsheetColumnValueType data_type, + const eSpreadsheetFilterOperation operation) +{ + if (ELEM(data_type, + SPREADSHEET_VALUE_TYPE_BOOL, + SPREADSHEET_VALUE_TYPE_INSTANCES, + SPREADSHEET_VALUE_TYPE_COLOR)) { + return "="; + } + + switch (operation) { + case SPREADSHEET_ROW_FILTER_EQUAL: + return "="; + case SPREADSHEET_ROW_FILTER_GREATER: + return ">"; + case SPREADSHEET_ROW_FILTER_LESS: + return "<"; + } + BLI_assert_unreachable(); + return ""; +} + +static std::string value_string(const SpreadsheetRowFilter &row_filter, + const eSpreadsheetColumnValueType data_type) +{ + switch (data_type) { + case SPREADSHEET_VALUE_TYPE_INT32: + return std::to_string(row_filter.value_int); + case SPREADSHEET_VALUE_TYPE_FLOAT: { + std::ostringstream result; + result.precision(3); + result << std::fixed << row_filter.value_float; + return result.str(); + } + case SPREADSHEET_VALUE_TYPE_FLOAT2: { + std::ostringstream result; + result.precision(3); + result << std::fixed << "(" << row_filter.value_float2[0] << ", " + << row_filter.value_float2[1] << ")"; + return result.str(); + } + case SPREADSHEET_VALUE_TYPE_FLOAT3: { + std::ostringstream result; + result.precision(3); + result << std::fixed << "(" << row_filter.value_float3[0] << ", " + << row_filter.value_float3[1] << ", " << row_filter.value_float3[2] << ")"; + return result.str(); + } + case SPREADSHEET_VALUE_TYPE_BOOL: + return (row_filter.flag & SPREADSHEET_ROW_FILTER_BOOL_VALUE) ? IFACE_("True") : + IFACE_("False"); + case SPREADSHEET_VALUE_TYPE_INSTANCES: + if (row_filter.value_string != nullptr) { + return row_filter.value_string; + } + return ""; + case SPREADSHEET_VALUE_TYPE_COLOR: + std::ostringstream result; + result.precision(3); + result << std::fixed << "(" << row_filter.value_color[0] << ", " << row_filter.value_color[1] + << ", " << row_filter.value_color[2] << ", " << row_filter.value_color[3] << ")"; + return result.str(); + } + BLI_assert_unreachable(); + return ""; +} + +static SpreadsheetColumn *lookup_visible_column_for_filter(const SpaceSpreadsheet &sspreadsheet, + const StringRef column_name) +{ + LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet.columns) { + if (column->display_name == column_name) { + return column; + } + } + return nullptr; +} + +static void spreadsheet_filter_panel_draw_header(const bContext *C, Panel *panel) +{ + uiLayout *layout = panel->layout; + SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); + PointerRNA *filter_ptr = UI_panel_custom_data_get(panel); + const SpreadsheetRowFilter *filter = (SpreadsheetRowFilter *)filter_ptr->data; + const StringRef column_name = filter->column_name; + const eSpreadsheetFilterOperation operation = (eSpreadsheetFilterOperation)filter->operation; + + const SpreadsheetColumn *column = lookup_visible_column_for_filter(*sspreadsheet, column_name); + if (!(sspreadsheet->filter_flag & SPREADSHEET_FILTER_ENABLE) || + (column == nullptr && !column_name.is_empty())) { + uiLayoutSetActive(layout, false); + } + + uiLayout *row = uiLayoutRow(layout, true); + uiLayoutSetEmboss(row, UI_EMBOSS_NONE); + uiItemR(row, filter_ptr, "enabled", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); + + if (column_name.is_empty()) { + uiItemL(row, IFACE_("Filter"), ICON_NONE); + } + else if (column == nullptr) { + uiItemL(row, column_name.data(), ICON_NONE); + } + else { + const eSpreadsheetColumnValueType data_type = (eSpreadsheetColumnValueType)column->data_type; + std::stringstream ss; + ss << column_name; + ss << " "; + ss << operation_string(data_type, operation); + ss << " "; + ss << value_string(*filter, data_type); + uiItemL(row, ss.str().c_str(), ICON_NONE); + } + + row = uiLayoutRow(layout, true); + uiLayoutSetEmboss(row, UI_EMBOSS_NONE); + const int current_index = BLI_findindex(&sspreadsheet->row_filters, filter); + uiItemIntO(row, "", ICON_X, "SPREADSHEET_OT_remove_row_filter_rule", "index", current_index); + + /* Some padding so the X isn't too close to the drag icon. */ + uiItemS_ex(layout, 0.25f); +} + +static void spreadsheet_filter_panel_draw(const bContext *C, Panel *panel) +{ + uiLayout *layout = panel->layout; + SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); + PointerRNA *filter_ptr = UI_panel_custom_data_get(panel); + SpreadsheetRowFilter *filter = (SpreadsheetRowFilter *)filter_ptr->data; + const StringRef column_name = filter->column_name; + const eSpreadsheetFilterOperation operation = (eSpreadsheetFilterOperation)filter->operation; + + const SpreadsheetColumn *column = lookup_visible_column_for_filter(*sspreadsheet, column_name); + if (!(sspreadsheet->filter_flag & SPREADSHEET_FILTER_ENABLE) || + !(filter->flag & SPREADSHEET_ROW_FILTER_ENABLED) || + (column == nullptr && !column_name.is_empty())) { + uiLayoutSetActive(layout, false); + } + + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + + uiItemR(layout, filter_ptr, "column_name", 0, IFACE_("Column"), ICON_NONE); + + /* Don't draw settings for filters with no corresponding visible column. */ + if (column == nullptr || column_name.is_empty()) { + return; + } + + switch (static_cast<eSpreadsheetColumnValueType>(column->data_type)) { + case SPREADSHEET_VALUE_TYPE_INT32: + uiItemR(layout, filter_ptr, "operation", 0, nullptr, ICON_NONE); + uiItemR(layout, filter_ptr, "value_int", 0, IFACE_("Value"), ICON_NONE); + break; + case SPREADSHEET_VALUE_TYPE_FLOAT: + uiItemR(layout, filter_ptr, "operation", 0, nullptr, ICON_NONE); + uiItemR(layout, filter_ptr, "value_float", 0, IFACE_("Value"), ICON_NONE); + if (operation == SPREADSHEET_ROW_FILTER_EQUAL) { + uiItemR(layout, filter_ptr, "threshold", 0, nullptr, ICON_NONE); + } + break; + case SPREADSHEET_VALUE_TYPE_FLOAT2: + uiItemR(layout, filter_ptr, "operation", 0, nullptr, ICON_NONE); + uiItemR(layout, filter_ptr, "value_float2", 0, IFACE_("Value"), ICON_NONE); + if (operation == SPREADSHEET_ROW_FILTER_EQUAL) { + uiItemR(layout, filter_ptr, "threshold", 0, nullptr, ICON_NONE); + } + break; + case SPREADSHEET_VALUE_TYPE_FLOAT3: + uiItemR(layout, filter_ptr, "operation", 0, nullptr, ICON_NONE); + uiItemR(layout, filter_ptr, "value_float3", 0, IFACE_("Value"), ICON_NONE); + if (operation == SPREADSHEET_ROW_FILTER_EQUAL) { + uiItemR(layout, filter_ptr, "threshold", 0, nullptr, ICON_NONE); + } + break; + case SPREADSHEET_VALUE_TYPE_BOOL: + uiItemR(layout, filter_ptr, "value_boolean", 0, IFACE_("Value"), ICON_NONE); + break; + case SPREADSHEET_VALUE_TYPE_INSTANCES: + uiItemR(layout, filter_ptr, "value_string", 0, IFACE_("Value"), ICON_NONE); + break; + case SPREADSHEET_VALUE_TYPE_COLOR: + uiItemR(layout, filter_ptr, "value_color", 0, IFACE_("Value"), ICON_NONE); + uiItemR(layout, filter_ptr, "threshold", 0, nullptr, ICON_NONE); + break; + } +} + +static void spreadsheet_row_filters_layout(const bContext *C, Panel *panel) +{ + uiLayout *layout = panel->layout; + ARegion *region = CTX_wm_region(C); + bScreen *screen = CTX_wm_screen(C); + SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); + ListBase *row_filters = &sspreadsheet->row_filters; + + if (!(sspreadsheet->filter_flag & SPREADSHEET_FILTER_ENABLE)) { + uiLayoutSetActive(layout, false); + } + + uiItemO(layout, nullptr, ICON_ADD, "SPREADSHEET_OT_add_row_filter_rule"); + + const bool panels_match = UI_panel_list_matches_data(region, row_filters, filter_panel_id_fn); + + if (!panels_match) { + UI_panels_free_instanced(C, region); + LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, row_filters) { + char panel_idname[MAX_NAME]; + filter_panel_id_fn(row_filter, panel_idname); + + PointerRNA *filter_ptr = (PointerRNA *)MEM_mallocN(sizeof(PointerRNA), "panel customdata"); + RNA_pointer_create(&screen->id, &RNA_SpreadsheetRowFilter, row_filter, filter_ptr); + + UI_panel_add_instanced(C, region, ®ion->panels, panel_idname, filter_ptr); + } + } + else { + /* Assuming there's only one group of instanced panels, update the custom data pointers. */ + Panel *panel_iter = (Panel *)region->panels.first; + LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, row_filters) { + + /* Move to the next instanced panel corresponding to the next filter. */ + while ((panel_iter->type == nullptr) || !(panel_iter->type->flag & PANEL_TYPE_INSTANCED)) { + panel_iter = panel_iter->next; + BLI_assert(panel_iter != nullptr); /* There shouldn't be fewer panels than filters. */ + } + + PointerRNA *filter_ptr = (PointerRNA *)MEM_mallocN(sizeof(PointerRNA), "panel customdata"); + RNA_pointer_create(&screen->id, &RNA_SpreadsheetRowFilter, row_filter, filter_ptr); + UI_panel_custom_data_set(panel_iter, filter_ptr); + + panel_iter = panel_iter->next; + } + } +} + +static void filter_reorder(bContext *C, Panel *panel, int new_index) +{ + SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); + ListBase *row_filters = &sspreadsheet->row_filters; + PointerRNA *filter_ptr = UI_panel_custom_data_get(panel); + SpreadsheetRowFilter *filter = (SpreadsheetRowFilter *)filter_ptr->data; + + int current_index = BLI_findindex(row_filters, filter); + BLI_assert(current_index >= 0); + BLI_assert(new_index >= 0); + + BLI_listbase_link_move(row_filters, filter, new_index - current_index); +} + +static short get_filter_expand_flag(const bContext *UNUSED(C), Panel *panel) +{ + PointerRNA *filter_ptr = UI_panel_custom_data_get(panel); + SpreadsheetRowFilter *filter = (SpreadsheetRowFilter *)filter_ptr->data; + + return (short)filter->flag & SPREADSHEET_ROW_FILTER_UI_EXPAND; +} + +static void set_filter_expand_flag(const bContext *UNUSED(C), Panel *panel, short expand_flag) +{ + PointerRNA *filter_ptr = UI_panel_custom_data_get(panel); + SpreadsheetRowFilter *filter = (SpreadsheetRowFilter *)filter_ptr->data; + + SET_FLAG_FROM_TEST(filter->flag, + expand_flag & SPREADSHEET_ROW_FILTER_UI_EXPAND, + SPREADSHEET_ROW_FILTER_UI_EXPAND); +} + +void register_row_filter_panels(ARegionType ®ion_type) +{ + { + PanelType *panel_type = (PanelType *)MEM_callocN(sizeof(PanelType), __func__); + strcpy(panel_type->idname, "SPREADSHEET_PT_row_filters"); + strcpy(panel_type->label, N_("Filters")); + strcpy(panel_type->category, "Filters"); + strcpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + panel_type->flag = PANEL_TYPE_NO_HEADER; + panel_type->draw = spreadsheet_row_filters_layout; + BLI_addtail(®ion_type.paneltypes, panel_type); + } + + { + PanelType *panel_type = (PanelType *)MEM_callocN(sizeof(PanelType), __func__); + strcpy(panel_type->idname, "SPREADSHEET_PT_filter"); + strcpy(panel_type->label, ""); + strcpy(panel_type->category, "Filters"); + strcpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + panel_type->flag = PANEL_TYPE_INSTANCED | PANEL_TYPE_DRAW_BOX | PANEL_TYPE_HEADER_EXPAND; + panel_type->draw_header = spreadsheet_filter_panel_draw_header; + panel_type->draw = spreadsheet_filter_panel_draw; + panel_type->get_list_data_expand_flag = get_filter_expand_flag; + panel_type->set_list_data_expand_flag = set_filter_expand_flag; + panel_type->reorder = filter_reorder; + BLI_addtail(®ion_type.paneltypes, panel_type); + } +} diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.hh b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.hh new file mode 100644 index 00000000000..e22178b63ea --- /dev/null +++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.hh @@ -0,0 +1,21 @@ +/* + * 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. + */ + +#pragma once + +struct ARegionType; + +void register_row_filter_panels(ARegionType ®ion_type); diff --git a/source/blender/editors/space_statusbar/space_statusbar.c b/source/blender/editors/space_statusbar/space_statusbar.c index 0b4f483c114..bf2a5534e0b 100644 --- a/source/blender/editors/space_statusbar/space_statusbar.c +++ b/source/blender/editors/space_statusbar/space_statusbar.c @@ -39,7 +39,7 @@ #include "WM_message.h" #include "WM_types.h" -/* ******************** default callbacks for statusbar space ******************** */ +/* ******************** default callbacks for statusbar space ******************** */ static SpaceLink *statusbar_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 17831c95575..1d8bc427212 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -938,7 +938,7 @@ static void calc_text_rcts(SpaceText *st, ARegion *region, rcti *scroll, rcti *b hlstart = barstart + barheight; } else if (lhlend > st->top && lhlstart < st->top && hlstart > barstart) { - /*fill out start */ + /* Fill out start. */ hlstart = barstart; } diff --git a/source/blender/editors/space_text/text_format_pov.c b/source/blender/editors/space_text/text_format_pov.c index a68632c0d56..1200dda7533 100644 --- a/source/blender/editors/space_text/text_format_pov.c +++ b/source/blender/editors/space_text/text_format_pov.c @@ -644,7 +644,7 @@ static int txtfmt_pov_find_specialvar(const char *string) } else if (STR_LITERAL_STARTSWITH(string, "ratio", len)) { i = len; } else if (STR_LITERAL_STARTSWITH(string, "open", len)) { i = len; } else if (STR_LITERAL_STARTSWITH(string, "ior", len)) { i = len; - /* Light Types and options*/ + /* Light Types and options. */ } else if (STR_LITERAL_STARTSWITH(string, "area_light", len)) { i = len; } else if (STR_LITERAL_STARTSWITH(string, "looks_like", len)) { i = len; } else if (STR_LITERAL_STARTSWITH(string, "fade_power", len)) { i = len; @@ -654,7 +654,7 @@ static int txtfmt_pov_find_specialvar(const char *string) } else if (STR_LITERAL_STARTSWITH(string, "point_at", len)) { i = len; } else if (STR_LITERAL_STARTSWITH(string, "falloff", len)) { i = len; } else if (STR_LITERAL_STARTSWITH(string, "radius", len)) { i = len; - /* Camera Types and options*/ + /* Camera Types and options. */ } else if (STR_LITERAL_STARTSWITH(string, "omni_directional_stereo", len)) { i = len; } else if (STR_LITERAL_STARTSWITH(string, "lambert_cylindrical", len)) { i = len; } else if (STR_LITERAL_STARTSWITH(string, "miller_cylindrical", len)) { i = len; diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c index 31177c53d6a..2717c0bf5b0 100644 --- a/source/blender/editors/space_text/text_format_py.c +++ b/source/blender/editors/space_text/text_format_py.c @@ -290,7 +290,7 @@ static int txtfmt_py_literal_numeral(const char *string, char prev_fmt) return 1 + txtfmt_py_find_numeral_inner(string + 1); } /* Previous was a number; if immediately followed by '.' it's a floating point decimal number. - * Note: keep the decimal point, it's needed to allow leading zeros. */ + * NOTE: keep the decimal point, it's needed to allow leading zeros. */ if (first == '.') { return txtfmt_py_find_numeral_inner(string); } diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 9ec759ce4ae..b98dae0cd57 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -745,7 +745,7 @@ void TEXT_OT_save_as(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_DEFAULT); /* XXX TODO, relative_path. */ + FILE_SORT_DEFAULT); /* XXX TODO: relative_path. */ } /** \} */ @@ -2782,8 +2782,7 @@ void TEXT_OT_scroll(wmOperatorType *ot) /* identifiers */ ot->name = "Scroll"; /* don't really see the difference between this and - * scroll_bar. Both do basically the same thing (aside - * from keymaps).*/ + * scroll_bar. Both do basically the same thing (aside from key-maps). */ ot->idname = "TEXT_OT_scroll"; /* api callbacks */ @@ -2889,8 +2888,7 @@ void TEXT_OT_scroll_bar(wmOperatorType *ot) /* identifiers */ ot->name = "Scrollbar"; /* don't really see the difference between this and - * scroll. Both do basically the same thing (aside - * from keymaps).*/ + * scroll. Both do basically the same thing (aside from key-maps). */ ot->idname = "TEXT_OT_scroll_bar"; /* api callbacks */ @@ -3470,7 +3468,7 @@ static int text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event) { int ret; - /* Note, the "text" property is always set from key-map, + /* NOTE: the "text" property is always set from key-map, * so we can't use #RNA_struct_property_is_set, check the length instead. */ if (!RNA_string_length(op->ptr, "text")) { /* if alt/ctrl/super are pressed pass through except for utf8 character event diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c index f55db8c3cc9..80af7d8c9f6 100644 --- a/source/blender/editors/space_text/text_undo.c +++ b/source/blender/editors/space_text/text_undo.c @@ -265,7 +265,7 @@ void ED_text_undosys_type(UndoType *ut) ut->step_foreach_ID_ref = text_undosys_foreach_ID_ref; - ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE; + ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE | UNDOTYPE_FLAG_DECODE_ACTIVE_STEP; ut->step_size = sizeof(TextUndoStep); } diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index 9242fc15021..fe84a3b8ae9 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -46,7 +46,6 @@ set(SRC view3d_camera_control.c view3d_draw.c view3d_edit.c - view3d_fly.c view3d_gizmo_armature.c view3d_gizmo_camera.c view3d_gizmo_empty.c @@ -60,6 +59,8 @@ set(SRC view3d_gizmo_tool_generic.c view3d_header.c view3d_iterators.c + view3d_navigate_fly.c + view3d_navigate_walk.c view3d_ops.c view3d_placement.c view3d_project.c @@ -67,7 +68,6 @@ set(SRC view3d_snap.c view3d_utils.c view3d_view.c - view3d_walk.c view3d_intern.h ) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 660ae9da506..6b9da431510 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -117,10 +117,10 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, return; } - Mesh *me = ob->data; + const Mesh *me = ob->data; { Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); if (me_eval != NULL) { me = me_eval; } @@ -160,7 +160,7 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, const MPoly *mp; int i; if (me->runtime.looptris.array) { - MLoopTri *mlt = me->runtime.looptris.array; + const MLoopTri *mlt = me->runtime.looptris.array; for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) { if (facemap_data[i] == facemap) { for (int j = 2; j < mp->totloop; j++) { diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index b5274c2357e..54f10e259f9 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -187,7 +187,7 @@ bool ED_view3d_area_user_region(const ScrArea *area, const View3D *v3d, ARegion * view3d_project_short_clip and view3d_project_short_noclip in cases where * these functions are not used during draw_object */ -void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d) +void ED_view3d_init_mats_rv3d(const struct Object *ob, struct RegionView3D *rv3d) { /* local viewmat and persmat, to calculate projections */ mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat); @@ -197,7 +197,7 @@ void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d) ED_view3d_clipping_local(rv3d, ob->obmat); } -void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d) +void ED_view3d_init_mats_rv3d_gl(const struct Object *ob, struct RegionView3D *rv3d) { ED_view3d_init_mats_rv3d(ob, rv3d); @@ -331,6 +331,8 @@ static void view3d_free(SpaceLink *sl) MEM_freeN(vd->localvd); } + MEM_SAFE_FREE(vd->runtime.local_stats); + if (vd->runtime.properties_storage) { MEM_freeN(vd->runtime.properties_storage); } @@ -346,19 +348,25 @@ static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area)) { } +static void view3d_exit(wmWindowManager *UNUSED(wm), ScrArea *area) +{ + BLI_assert(area->spacetype == SPACE_VIEW3D); + View3D *v3d = area->spacedata.first; + MEM_SAFE_FREE(v3d->runtime.local_stats); +} + static SpaceLink *view3d_duplicate(SpaceLink *sl) { View3D *v3do = (View3D *)sl; View3D *v3dn = MEM_dupallocN(sl); + memset(&v3dn->runtime, 0x0, sizeof(v3dn->runtime)); + /* clear or remove stuff from old */ if (v3dn->localvd) { v3dn->localvd = NULL; - v3dn->runtime.properties_storage = NULL; } - /* Only one View3D is allowed to have this flag! */ - v3dn->runtime.flag &= ~V3D_RUNTIME_XR_SESSION_ROOT; v3dn->local_collections_uuid = 0; v3dn->flag &= ~(V3D_LOCAL_COLLECTIONS | V3D_XR_SESSION_MIRROR); @@ -373,8 +381,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) /* copy or clear inside new stuff */ - v3dn->runtime.properties_storage = NULL; - return (SpaceLink *)v3dn; } @@ -625,6 +631,7 @@ static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop) ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, ID_OB); RNA_string_set(drop->ptr, "name", id->name + 2); + RNA_boolean_set(drop->ptr, "duplicate", false); } static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop) @@ -779,12 +786,6 @@ static void view3d_main_region_free(ARegion *region) RE_engine_free(rv3d->render_engine); } - if (rv3d->depths) { - if (rv3d->depths->depths) { - MEM_freeN(rv3d->depths->depths); - } - MEM_freeN(rv3d->depths); - } if (rv3d->sms) { MEM_freeN(rv3d->sms); } @@ -808,7 +809,6 @@ static void *view3d_main_region_duplicate(void *poin) new->clipbb = MEM_dupallocN(rv3d->clipbb); } - new->depths = NULL; new->render_engine = NULL; new->sms = NULL; new->smooth_timer = NULL; @@ -1096,7 +1096,7 @@ static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeP ScrArea *area = params->area; ARegion *region = params->region; - /* Developer note: there are many properties that impact 3D view drawing, + /* 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. * @@ -1583,7 +1583,7 @@ static void space_view3d_listener(const wmSpaceTypeListenerParams *params) } } -static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(area)) +static void space_view3d_refresh(const bContext *C, ScrArea *area) { Scene *scene = CTX_data_scene(C); LightCache *lcache = scene->eevee.light_cache_data; @@ -1592,6 +1592,9 @@ static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(area)) lcache->flag &= ~LIGHTCACHE_UPDATE_AUTO; view3d_lightcache_update((bContext *)C); } + + View3D *v3d = (View3D *)area->spacedata.first; + MEM_SAFE_FREE(v3d->runtime.local_stats); } const char *view3d_context_dir[] = { @@ -1614,7 +1617,7 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes * 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. + * many of 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 @@ -1699,6 +1702,7 @@ void ED_spacetype_view3d(void) st->create = view3d_create; st->free = view3d_free; st->init = view3d_init; + st->exit = view3d_exit; st->listener = space_view3d_listener; st->refresh = space_view3d_refresh; st->duplicate = view3d_duplicate; diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index e42f6b5faac..3428a738dde 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -39,6 +39,8 @@ #include "BLT_translation.h" +#include "BLI_array_utils.h" +#include "BLI_bitmap.h" #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -112,10 +114,94 @@ typedef struct { float ob_dims[3]; /* Floats only (treated as an array). */ TransformMedian ve_median, median; + bool tag_for_update; } TransformProperties; #define TRANSFORM_MEDIAN_ARRAY_LEN (sizeof(TransformMedian) / sizeof(float)) +static TransformProperties *v3d_transform_props_ensure(View3D *v3d); + +/* -------------------------------------------------------------------- */ +/** \name Edit Mesh Partial Updates + * \{ */ + +static void *editmesh_partial_update_begin_fn(struct bContext *UNUSED(C), + const struct uiBlockInteraction_Params *params, + void *arg1) +{ + const int retval_test = B_TRANSFORM_PANEL_MEDIAN; + if (BLI_array_findindex( + params->unique_retval_ids, params->unique_retval_ids_len, &retval_test) == -1) { + return NULL; + } + + BMEditMesh *em = arg1; + + int verts_mask_count = 0; + BMIter iter; + BMVert *eve; + int i; + + BLI_bitmap *verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); + BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { + if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + continue; + } + BLI_BITMAP_ENABLE(verts_mask, i); + verts_mask_count += 1; + } + + BMPartialUpdate *bmpinfo = BM_mesh_partial_create_from_verts_group_single( + em->bm, + &(BMPartialUpdate_Params){ + .do_tessellate = true, + .do_normals = true, + }, + verts_mask, + verts_mask_count); + + MEM_freeN(verts_mask); + + return bmpinfo; +} + +static void editmesh_partial_update_end_fn(struct bContext *UNUSED(C), + const struct uiBlockInteraction_Params *UNUSED(params), + void *UNUSED(arg1), + void *user_data) +{ + BMPartialUpdate *bmpinfo = user_data; + if (bmpinfo == NULL) { + return; + } + BM_mesh_partial_destroy(bmpinfo); +} + +static void editmesh_partial_update_update_fn( + struct bContext *C, + const struct uiBlockInteraction_Params *UNUSED(params), + void *arg1, + void *user_data) +{ + BMPartialUpdate *bmpinfo = user_data; + if (bmpinfo == NULL) { + return; + } + + View3D *v3d = CTX_wm_view3d(C); + TransformProperties *tfp = v3d_transform_props_ensure(v3d); + if (tfp->tag_for_update == false) { + return; + } + tfp->tag_for_update = false; + + BMEditMesh *em = arg1; + + BKE_editmesh_looptri_and_normals_calc_with_partial(em, bmpinfo); +} + +/** \} */ + /* Helper function to compute a median changed value, * when the value should be clamped in [0.0, 1.0]. * Returns either 0.0, 1.0 (both can be applied directly), a positive scale factor @@ -840,6 +926,20 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } UI_block_align_end(block); + + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_mesh; + if (em != NULL) { + UI_block_interaction_set(block, + &(uiBlockInteraction_CallbackData){ + .begin_fn = editmesh_partial_update_begin_fn, + .end_fn = editmesh_partial_update_end_fn, + .update_fn = editmesh_partial_update_update_fn, + .arg1 = em, + }); + } + } } else { /* apply */ memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median)); @@ -927,7 +1027,8 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } if (apply_vcos) { - EDBM_mesh_normals_update(em); + /* Tell the update callback to run. */ + tfp->tag_for_update = true; } /* Edges */ @@ -1150,7 +1251,7 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event) ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = view_layer->basact->object; ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); } @@ -1209,7 +1310,9 @@ static void view3d_panel_vgroup(const bContext *C, Panel *panel) vgroup_validmap = BKE_object_defgroup_subset_from_select_type( ob, subset_type, &vgroup_tot, &subset_count); - for (i = 0, dg = ob->defbase.first; dg; i++, dg = dg->next) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + + for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) { bool locked = (dg->flag & DG_LOCK_WEIGHT) != 0; if (vgroup_validmap[i]) { MDeformWeight *dw = BKE_defvert_find_index(dv, i); @@ -1235,7 +1338,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *panel) but_ptr = UI_but_operator_ptr_get(but); RNA_int_set(but_ptr, "weight_group", i); UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT); - if (ob->actdef != i + 1) { + if (BKE_object_defgroup_active_index_get(ob) != i + 1) { UI_but_flag_enable(but, UI_BUT_INACTIVE); } xco += x; @@ -1462,7 +1565,7 @@ static void v3d_posearmature_buts(uiLayout *layout, Object *ob) /* XXX: RNA buts show data in native types (i.e. quats, 4-component axis/angle, etc.) * but old-school UI shows in eulers always. Do we want to be able to still display in Eulers? - * Maybe needs RNA/ui options to display rotations as different types... */ + * Maybe needs RNA/UI options to display rotations as different types. */ v3d_transform_butsR(col, &pchanptr); } @@ -1566,7 +1669,7 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event case B_TRANSFORM_PANEL_MEDIAN: if (ob) { v3d_editvertex_buts(NULL, v3d, ob, 1.0); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY); } break; case B_TRANSFORM_PANEL_DIMS: diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c index 0edd6aeb2ca..638c8a49ffd 100644 --- a/source/blender/editors/space_view3d/view3d_camera_control.c +++ b/source/blender/editors/space_view3d/view3d_camera_control.c @@ -140,7 +140,7 @@ struct View3DCameraControl *ED_view3d_cameracontrol_acquire(Depsgraph *depsgraph vctrl->persp_backup = rv3d->persp; vctrl->dist_backup = rv3d->dist; - /* check for flying ortho camera - which we cant support well + /* check for flying ortho camera - which we can't support well * we _could_ also check for an ortho camera but this is easier */ if ((rv3d->persp == RV3D_CAMOB) && (rv3d->is_persp == false)) { ((Camera *)v3d->camera->data)->type = CAM_PERSP; @@ -278,7 +278,7 @@ void ED_view3d_cameracontrol_update(View3DCameraControl *vctrl, mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->obmat); if (object_apply_mat4_with_protect(vctrl->root_parent, parent_mat, false, rv3d, view_mat)) { - /* Calculate again since the view locking changes the matrix. */ + /* Calculate again since the view locking changes the matrix. */ ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 1ef37ba4f9b..c97ba7ba7e9 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -140,7 +140,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph, rect_scale[0] = (float)BLI_rcti_size_x(rect) / (float)region->winx; rect_scale[1] = (float)BLI_rcti_size_y(rect) / (float)region->winy; } - /* note: calls BKE_object_where_is_calc for camera... */ + /* NOTE: calls BKE_object_where_is_calc for camera... */ view3d_viewmatrix_set(depsgraph, scene, v3d, rv3d, rect ? rect_scale : NULL); } /* update utility matrices */ @@ -167,7 +167,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph, /* 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])' + /* NOTE: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' * because of float point precision problems at large values T23908. */ float v1[3], v2[3]; float len_px, len_sc; @@ -563,10 +563,10 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region, /* apply offsets so the real 3D camera shows through */ - /* note: quite un-scientific but without this bit extra + /* NOTE: quite un-scientific but without this bit extra * 0.0001 on the lower left the 2D border sometimes * obscures the 3D camera border */ - /* note: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable + /* NOTE: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable * but keep it here in case we need to remove the workaround */ x1i = (int)(x1 - 1.0001f); y1i = (int)(y1 - 1.0001f); @@ -780,7 +780,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region, /* draw */ immUniformThemeColorShadeAlpha(TH_VIEW_OVERLAY, 100, 255); - /* TODO Was using: + /* TODO: Was using: * UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color); * We'll probably need a new imm_draw_line_roundbox_dashed dor that - though in practice the * 2.0f round corner effect was nearly not visible anyway... */ @@ -1159,7 +1159,7 @@ static void view3d_draw_border(const bContext *C, ARegion *region) */ static void view3d_draw_grease_pencil(const bContext *UNUSED(C)) { - /* TODO viewport */ + /* TODO: viewport. */ } /** @@ -1404,7 +1404,7 @@ static void draw_selected_name( /* color depends on whether there is a keyframe */ if (id_frame_has_keyframe( - (ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) { + (ID *)ob, /* BKE_scene_ctime_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) { UI_FontThemeColor(font_id, TH_TIME_KEYFRAME); } else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) { @@ -1537,7 +1537,9 @@ void view3d_draw_region_info(const bContext *C, ARegion *region) } if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_STATS)) { - ED_info_draw_stats(bmain, scene, view_layer, xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT); + View3D *v3d_local = v3d->localvd ? v3d : NULL; + ED_info_draw_stats( + bmain, scene, view_layer, v3d_local, xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT); } BLF_batch_draw_end(); @@ -2022,7 +2024,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph, source_shading_settings = shading_override; } memcpy(&v3d.shading, source_shading_settings, sizeof(View3DShading)); - v3d.shading.type = drawtype; if (drawtype == OB_MATERIAL) { v3d.shading.flag = V3D_SHADING_SCENE_WORLD | V3D_SHADING_SCENE_LIGHTS; @@ -2032,8 +2033,17 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph, v3d.shading.flag = V3D_SHADING_SCENE_WORLD_RENDER | V3D_SHADING_SCENE_LIGHTS_RENDER; v3d.shading.render_pass = SCE_PASS_COMBINED; } + else if (drawtype == OB_TEXTURE) { + drawtype = OB_SOLID; + v3d.shading.light = V3D_LIGHTING_STUDIO; + v3d.shading.color_type = V3D_SHADING_TEXTURE_COLOR; + } + v3d.shading.type = drawtype; v3d.flag2 = V3D_HIDE_OVERLAYS; + /* HACK: When rendering gpencil objects this opacity is used to mix vertex colors in when not in + * render mode. */ + v3d.overlay.gpencil_vertex_paint_opacity = 1.0f; if (draw_flags & V3D_OFSDRAW_SHOW_ANNOTATION) { v3d.flag2 |= V3D_SHOW_ANNOTATION; @@ -2072,7 +2082,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph, return ED_view3d_draw_offscreen_imbuf(depsgraph, scene, - drawtype, + v3d.shading.type, &v3d, ®ion, width, @@ -2211,7 +2221,7 @@ int ED_view3d_backbuf_sample_size_clamp(ARegion *region, const float dist) /** \name Z-Depth Utilities * \{ */ -void view3d_update_depths_rect(ARegion *region, ViewDepths *d, rcti *rect) +void view3d_depths_rect_create(ARegion *region, rcti *rect, ViewDepths *r_d) { /* clamp rect by region */ rcti r = { @@ -2232,70 +2242,44 @@ void view3d_update_depths_rect(ARegion *region, ViewDepths *d, rcti *rect) int h = BLI_rcti_size_y(rect); if (w <= 0 || h <= 0) { - if (d->depths) { - MEM_freeN(d->depths); - } - d->depths = NULL; - - d->damaged = false; + r_d->depths = NULL; + return; } - else if (d->w != w || d->h != h || d->x != x || d->y != y || d->depths == NULL) { - d->x = x; - d->y = y; - d->w = w; - d->h = h; - if (d->depths) { - MEM_freeN(d->depths); - } + r_d->x = x; + r_d->y = y; + r_d->w = w; + r_d->h = h; - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset"); + r_d->depths = MEM_mallocN(sizeof(float) * w * h, "View depths Subset"); - d->damaged = true; - } - - if (d->damaged) { + { GPUViewport *viewport = WM_draw_region_get_viewport(region); - view3d_opengl_read_Z_pixels(viewport, rect, d->depths); + view3d_opengl_read_Z_pixels(viewport, rect, r_d->depths); /* Range is assumed to be this as they are never changed. */ - d->depth_range[0] = 0.0; - d->depth_range[1] = 1.0; - d->damaged = false; + r_d->depth_range[0] = 0.0; + r_d->depth_range[1] = 1.0; } } -/* Note, with nouveau drivers the glReadPixels() is very slow. T24339. */ -static void view3d_depth_cache_update(ARegion *region) +/* NOTE: with nouveau drivers the glReadPixels() is very slow. T24339. */ +static ViewDepths *view3d_depths_create(ARegion *region) { - RegionView3D *rv3d = region->regiondata; + ViewDepths *d = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); + d->w = region->winx; + d->h = region->winy; + d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); - /* Create storage for, and, if necessary, copy depth buffer. */ - if (!rv3d->depths) { - rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); - } - if (rv3d->depths) { - ViewDepths *d = rv3d->depths; - if (d->w != region->winx || d->h != region->winy || !d->depths) { - d->w = region->winx; - d->h = region->winy; - if (d->depths) { - MEM_freeN(d->depths); - } - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); - d->damaged = true; - } - - if (d->damaged) { - GPUViewport *viewport = WM_draw_region_get_viewport(region); - DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); - GPU_framebuffer_read_depth(fbl->depth_only_fb, 0, 0, d->w, d->h, GPU_DATA_FLOAT, d->depths); + { + GPUViewport *viewport = WM_draw_region_get_viewport(region); + DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); + GPU_framebuffer_read_depth(fbl->depth_only_fb, 0, 0, d->w, d->h, GPU_DATA_FLOAT, d->depths); - /* Assumed to be this as they are never changed. */ - d->depth_range[0] = 0.0; - d->depth_range[1] = 1.0; - d->damaged = false; - } + /* Assumed to be this as they are never changed. */ + d->depth_range[0] = 0.0; + d->depth_range[1] = 1.0; } + return d; } /* Utility function to find the closest Z value, use for auto-depth. */ @@ -2335,10 +2319,13 @@ void ED_view3d_depth_override(Depsgraph *depsgraph, View3D *v3d, Object *obact, eV3DDepthOverrideMode mode, - bool update_cache) + ViewDepths **r_depths) { if (v3d->runtime.flag & V3D_RUNTIME_DEPTHBUF_OVERRIDDEN) { - return; + /* Force redraw if `r_depths` is required. */ + if (!r_depths || *r_depths != NULL) { + return; + } } struct bThemeState theme_state; Scene *scene = DEG_get_evaluated_scene(depsgraph); @@ -2380,12 +2367,11 @@ void ED_view3d_depth_override(Depsgraph *depsgraph, break; } - if (rv3d->depths != NULL) { - rv3d->depths->damaged = true; - /* TODO: Clear cache? */ - } - if (update_cache) { - view3d_depth_cache_update(region); + if (r_depths) { + if (*r_depths) { + ED_view3d_depths_free(*r_depths); + } + *r_depths = view3d_depths_create(region); } } @@ -2399,6 +2385,14 @@ void ED_view3d_depth_override(Depsgraph *depsgraph, UI_Theme_Restore(&theme_state); } +void ED_view3d_depths_free(ViewDepths *depths) +{ + if (depths->depths) { + MEM_freeN(depths->depths); + } + MEM_freeN(depths); +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 967ad966320..651ae8a3000 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -392,9 +392,9 @@ enum eViewOpsFlag { /** When enabled, use the depth under the cursor for navigation. */ VIEWOPS_FLAG_DEPTH_NAVIGATE = (1 << 1), /** - * When enabled run #ED_view3d_persp_ensure this may switch out of - * camera view when orbiting or switch from ortho to perspective when auto-persp is enabled. - * Some operations don't require this (view zoom/pan or ndof where subtle rotation is common + * When enabled run #ED_view3d_persp_ensure this may switch out of camera view + * when orbiting or switch from orthographic to perspective when auto-perspective is enabled. + * Some operations don't require this (view zoom/pan or NDOF where subtle rotation is common * so we don't want it to trigger auto-perspective). */ VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2), /** When set, ignore any options that depend on initial cursor location. */ @@ -509,7 +509,7 @@ static void viewops_data_create(bContext *C, negate_v3_v3(my_origin, rv3d->ofs); /* ofs is flipped */ /* Set the dist value to be the distance from this 3d point this means you'll - * always be able to zoom into it and panning wont go bad when dist was zero. */ + * always be able to zoom into it and panning won't go bad when dist was zero. */ /* remove dist value */ upvec[0] = upvec[1] = 0; @@ -611,7 +611,7 @@ enum { VIEWROT_MODAL_SWITCH_ROTATE = 6, }; -/* called in transform_ops.c, on each regeneration of keymaps */ +/* Called in transform_ops.c, on each regeneration of key-maps. */ void viewrotate_modal_keymap(wmKeyConfig *keyconf) { static const EnumPropertyItem modal_items[] = { @@ -813,7 +813,6 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2]) viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat); } else { - /* New turntable view code by John Aughey */ float quat_local_x[4], quat_global_z[4]; float m[3][3]; float m_inv[3][3]; @@ -894,8 +893,8 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2]) * rotation back into the view we calculate with */ copy_qt_qt(rv3d->viewquat, vod->curr.viewquat); - /* check for view snap, - * note: don't apply snap to vod->viewquat so the view wont jam up */ + /* Check for view snap, + * NOTE: don't apply snap to `vod->viewquat` so the view won't jam up. */ if (vod->axis_snap) { viewrotate_apply_snap(vod); } @@ -953,7 +952,6 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else if (event_code == VIEW_CONFIRM) { - ED_view3d_depth_tag_update(vod->rv3d); use_autokey = true; ret = OPERATOR_FINISHED; } @@ -1014,7 +1012,6 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event) } viewrotate_apply(vod, event_xy); - ED_view3d_depth_tag_update(vod->rv3d); viewops_data_free(C, op); @@ -1203,7 +1200,7 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, if (U.ndof_flag & NDOF_TURNTABLE) { float rot[3]; - /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ + /* Turntable view code adapted for 3D mouse use. */ float angle, quat[4]; float xvec[3] = {1, 0, 0}; @@ -1508,7 +1505,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev } } else { - /* Note: based on feedback from T67579, users want to have pan and orbit enabled at once. + /* NOTE: based on feedback from T67579, users want to have pan and orbit enabled at once. * It's arguable that orbit shouldn't pan (since we have a pan only operator), * so if there are users who like to separate orbit/pan operations - it can be a preference. */ const bool is_orbit_around_pivot = (U.ndof_flag & NDOF_MODE_ORBIT) || @@ -1688,7 +1685,7 @@ void VIEW3D_OT_ndof_all(struct wmOperatorType *ot) /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ -/* called in transform_ops.c, on each regeneration of keymaps */ +/* Called in transform_ops.c, on each regeneration of key-maps. */ void viewmove_modal_keymap(wmKeyConfig *keyconf) { static const EnumPropertyItem modal_items[] = { @@ -1799,7 +1796,6 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else if (event_code == VIEW_CONFIRM) { - ED_view3d_depth_tag_update(vod->rv3d); use_autokey = true; ret = OPERATOR_FINISHED; } @@ -1840,7 +1836,6 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (event->type == MOUSEPAN) { /* invert it, trackpad scroll follows same principle as 2d windows this way */ viewmove_apply(vod, 2 * event->x - event->prevx, 2 * event->y - event->prevy); - ED_view3d_depth_tag_update(vod->rv3d); viewops_data_free(C, op); @@ -1885,8 +1880,8 @@ void VIEW3D_OT_move(wmOperatorType *ot) /** \name View Zoom Operator * \{ */ -/* viewdolly_modal_keymap has an exact copy of this, apply fixes to both */ -/* called in transform_ops.c, on each regeneration of keymaps */ +/* #viewdolly_modal_keymap has an exact copy of this, apply fixes to both. */ +/* Called in transform_ops.c, on each regeneration of key-maps. */ void viewzoom_modal_keymap(wmKeyConfig *keyconf) { static const EnumPropertyItem modal_items[] = { @@ -2254,7 +2249,6 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else if (event_code == VIEW_CONFIRM) { - ED_view3d_depth_tag_update(vod->rv3d); use_autokey = true; ret = OPERATOR_FINISHED; } @@ -2341,8 +2335,6 @@ static int viewzoom_exec(bContext *C, wmOperator *op) view3d_boxview_sync(area, region); } - ED_view3d_depth_tag_update(rv3d); - ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true); @@ -2398,8 +2390,6 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event) (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS))); ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true); - ED_view3d_depth_tag_update(vod->rv3d); - viewops_data_free(C, op); return OPERATOR_FINISHED; } @@ -2454,8 +2444,8 @@ void VIEW3D_OT_zoom(wmOperatorType *ot) * which avoids #RegionView3D.dist approaching zero. * \{ */ -/* this is an exact copy of viewzoom_modal_keymap */ -/* called in transform_ops.c, on each regeneration of keymaps */ +/* This is an exact copy of #viewzoom_modal_keymap. */ +/* Called in transform_ops.c, on each regeneration of key-maps. */ void viewdolly_modal_keymap(wmKeyConfig *keyconf) { static const EnumPropertyItem modal_items[] = { @@ -2579,7 +2569,6 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else if (event_code == VIEW_CONFIRM) { - ED_view3d_depth_tag_update(vod->rv3d); use_autokey = true; ret = OPERATOR_FINISHED; } @@ -2636,8 +2625,6 @@ static int viewdolly_exec(bContext *C, wmOperator *op) view3d_boxview_sync(area, region); } - ED_view3d_depth_tag_update(rv3d); - ED_view3d_camera_lock_sync(CTX_data_ensure_evaluated_depsgraph(C), v3d, rv3d); ED_region_tag_redraw(region); @@ -2718,7 +2705,6 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event) event->prevx; } viewdolly_apply(vod, &event->prevx, (U.uiflag & USER_ZOOM_INVERT) == 0); - ED_view3d_depth_tag_update(vod->rv3d); viewops_data_free(C, op); return OPERATOR_FINISHED; @@ -2968,7 +2954,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) if (!changed) { ED_region_tag_redraw(region); - /* TODO - should this be cancel? + /* TODO: should this be cancel? * I think no, because we always move the cursor, with or without * object, but in this case there is no change in the scene, * only the cursor so I choice a ED_region_tag like @@ -3617,7 +3603,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) float depth_close = FLT_MAX; float cent[2], p[3]; - /* note; otherwise opengl won't work */ + /* NOTE: otherwise opengl won't work. */ view3d_operator_needs_opengl(C); /* get box select values using rna */ @@ -3629,13 +3615,13 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) ED_view3d_dist_range_get(v3d, dist_range); ED_view3d_depth_override( - CTX_data_ensure_evaluated_depsgraph(C), region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, false); + CTX_data_ensure_evaluated_depsgraph(C), region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, NULL); { /* avoid allocating the whole depth buffer */ ViewDepths depth_temp = {0}; /* avoid view3d_update_depths() for speed. */ - view3d_update_depths_rect(region, &depth_temp, &rect); + view3d_depths_rect_create(region, &rect, &depth_temp); /* find the closest Z pixel */ depth_close = view3d_depth_near(&depth_temp); @@ -3660,14 +3646,14 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) if (rv3d->is_persp) { float p_corner[3]; - /* no depths to use, we cant do anything! */ + /* no depths to use, we can't do anything! */ if (depth_close == FLT_MAX) { BKE_report(op->reports, RPT_ERROR, "Depth too large"); return OPERATOR_CANCELLED; } /* convert border to 3d coordinates */ - if ((!ED_view3d_unproject(region, cent[0], cent[1], depth_close, p)) || - (!ED_view3d_unproject(region, rect.xmin, rect.ymin, depth_close, p_corner))) { + if ((!ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p)) || + (!ED_view3d_unproject_v3(region, rect.xmin, rect.ymin, depth_close, p_corner))) { return OPERATOR_CANCELLED; } @@ -3690,7 +3676,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) new_dist = rv3d->dist; /* convert the drawn rectangle into 3d space */ - if (depth_close != FLT_MAX && ED_view3d_unproject(region, cent[0], cent[1], depth_close, p)) { + if (depth_close != FLT_MAX && + ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p)) { negate_v3_v3(new_ofs, p); } else { @@ -4432,7 +4419,6 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else if (event_code == VIEW_CONFIRM) { - ED_view3d_depth_tag_update(vod->rv3d); use_autokey = true; ret = OPERATOR_FINISHED; } @@ -4540,7 +4526,6 @@ static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (event->type == MOUSEROTATE) { vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x; viewroll_apply(vod, event->prevx, event->prevy); - ED_view3d_depth_tag_update(vod->rv3d); viewops_data_free(C, op); return OPERATOR_FINISHED; @@ -4637,7 +4622,6 @@ static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event) viewmove_apply(vod, vod->prev.event_xy[0] + x, vod->prev.event_xy[1] + y); - ED_view3d_depth_tag_update(vod->rv3d); viewops_data_free(C, op); return OPERATOR_FINISHED; @@ -4803,7 +4787,7 @@ static bool background_image_add_poll(bContext *C) void VIEW3D_OT_background_image_add(wmOperatorType *ot) { /* identifiers */ - /* note: having key shortcut here is bad practice, + /* NOTE: having key shortcut here is bad practice, * but for now keep because this displays when dragging an image over the 3D viewport */ ot->name = "Add Background Image"; ot->description = "Add a new background image"; @@ -4972,7 +4956,7 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot) * \{ */ /* cursor position in vec, result in vec, mval in region coords */ -/* note: cannot use event->mval here (called by object_add() */ +/* NOTE: cannot use `event->mval` here, called by #object_add(). */ void ED_view3d_cursor3d_position(bContext *C, const int mval[2], const bool use_depth, diff --git a/source/blender/editors/space_view3d/view3d_gizmo_armature.c b/source/blender/editors/space_view3d/view3d_gizmo_armature.c index 4d8102af6ff..83d3286c8b3 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_armature.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_armature.c @@ -86,12 +86,12 @@ static void gizmo_bbone_offset_get(const wmGizmo *UNUSED(gz), if (bh->index == 0) { bh->co[1] = pchan->bone->ease1 / BBONE_SCALE_Y; bh->co[0] = pchan->curve_in_x; - bh->co[2] = pchan->curve_in_y; + bh->co[2] = pchan->curve_in_z; } else { bh->co[1] = -pchan->bone->ease2 / BBONE_SCALE_Y; bh->co[0] = pchan->curve_out_x; - bh->co[2] = pchan->curve_out_y; + bh->co[2] = pchan->curve_out_z; } copy_v3_v3(value, bh->co); } @@ -111,12 +111,12 @@ static void gizmo_bbone_offset_set(const wmGizmo *UNUSED(gz), if (bh->index == 0) { pchan->bone->ease1 = max_ff(0.0f, bh->co[1] * BBONE_SCALE_Y); pchan->curve_in_x = bh->co[0]; - pchan->curve_in_y = bh->co[2]; + pchan->curve_in_z = bh->co[2]; } else { pchan->bone->ease2 = max_ff(0.0f, -bh->co[1] * BBONE_SCALE_Y); pchan->curve_out_x = bh->co[0]; - pchan->curve_out_y = bh->co[2]; + pchan->curve_out_z = bh->co[2]; } } @@ -199,7 +199,7 @@ static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmGizmoGroup mul_m4_m4m4(mat, ob->obmat, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat); copy_m4_m4(gz->matrix_space, mat); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* need to set property here for undo. TODO: would prefer to do this in _init. */ WM_gizmo_target_property_def_func(gz, "offset", &(const struct wmGizmoPropertyFnParams){ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c index 20d766357e8..e1d439bef15 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c @@ -153,7 +153,7 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup) WM_gizmo_set_scale(cagzgroup->dop_dist, ca->drawsize); WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, false); - /* Need to set property here for undo. TODO would prefer to do this in _init */ + /* Need to set property here for undo. TODO: would prefer to do this in _init. */ PointerRNA camera_dof_ptr; RNA_pointer_create(&ca->id, &RNA_CameraDOFSettings, &ca->dof, &camera_dof_ptr); WM_gizmo_target_property_def_rna( @@ -163,7 +163,7 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup) WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, true); } - /* TODO - make focal length/ortho ob_scale_inv widget optional */ + /* TODO: make focal length/ortho ob_scale_inv widget optional. */ const Scene *scene = CTX_data_scene(C); const float aspx = (float)scene->r.xsch * scene->r.xasp; const float aspy = (float)scene->r.ysch * scene->r.yasp; diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c index 5bf105b6775..d92ebfd57a8 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_light.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c @@ -99,7 +99,7 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr WM_gizmo_set_matrix_rotation_from_z_axis(gz, dir); WM_gizmo_set_matrix_location(gz, ob->obmat[3]); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* need to set property here for undo. TODO: would prefer to do this in _init. */ PointerRNA lamp_ptr; const char *propname = "spot_size"; RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr); @@ -212,7 +212,7 @@ static void WIDGETGROUP_light_area_refresh(const bContext *C, wmGizmoGroup *gzgr } RNA_enum_set(gz->ptr, "transform", flag); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* need to set property here for undo. TODO: would prefer to do this in _init. */ WM_gizmo_target_property_def_func(gz, "matrix", &(const struct wmGizmoPropertyFnParams){ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c index 298a2a7a824..07c3b6bd1d8 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c @@ -154,10 +154,10 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int * Only pre-select a vertex when the cursor is really close to it. */ if (eve_test) { BMVert *vert = (BMVert *)eve_test; - float vert_p_co[3], vert_co[3]; + float vert_p_co[2], vert_co[3]; const float mval_f[2] = {UNPACK2(vc.mval)}; mul_v3_m4v3(vert_co, gz_ele->bases[base_index_vert]->object->obmat, vert->co); - ED_view3d_project(vc.region, vert_co, vert_p_co); + ED_view3d_project_v2(vc.region, vert_co, vert_p_co); float len = len_v2v2(vert_p_co, mval_f); if (len < 35) { best.ele = (BMElem *)eve_test; diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c index 0d568363b00..49299d73337 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c @@ -580,7 +580,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz) UI_GetThemeColor3ubv(TH_TEXT, color_text); UI_GetThemeColor3ubv(TH_WIRE, color_wire); - /* Avoid white on white text. (TODO Fix by using theme) */ + /* Avoid white on white text. (TODO: Fix by using theme). */ if ((int)color_text[0] + (int)color_text[1] + (int)color_text[2] > 127 * 3 * 0.6f) { copy_v3_fl(color_back, 0.0f); } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 6f07cb8b44d..ab80928e0c1 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -111,11 +111,11 @@ void view3d_ndof_fly(const struct wmNDOFMotionData *ndof, bool *r_has_rotate); #endif /* WITH_INPUT_NDOF */ -/* view3d_fly.c */ +/* view3d_navigate_fly.c */ void view3d_keymap(struct wmKeyConfig *keyconf); void VIEW3D_OT_fly(struct wmOperatorType *ot); -/* view3d_walk.c */ +/* view3d_navigate_walk.c */ void VIEW3D_OT_walk(struct wmOperatorType *ot); /* view3d_draw.c */ @@ -137,7 +137,7 @@ void ED_view3d_draw_depth_loop(struct Depsgraph *depsgraph, struct ARegion *region, View3D *v3d); -void view3d_update_depths_rect(struct ARegion *region, struct ViewDepths *d, struct rcti *rect); +void view3d_depths_rect_create(struct ARegion *region, struct rcti *rect, struct ViewDepths *r_d); float view3d_depth_near(struct ViewDepths *d); /* view3d_select.c */ diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index bdb2c3874db..c7a4030c402 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -50,15 +50,179 @@ #include "ED_screen.h" #include "ED_view3d.h" +/* -------------------------------------------------------------------- */ +/** \name Internal Clipping Utilities + * \{ */ + +/** + * Calculate clipping planes to use when #V3D_PROJ_TEST_CLIP_CONTENT is enabled. + * + * Planes are selected from the viewpoint using `clip_flag` + * to detect which planes should be applied (maximum 6). + * + * \return The number of planes written into `planes`. + */ +static int content_planes_from_clip_flag(const ARegion *region, + const Object *ob, + const eV3DProjTest clip_flag, + float planes[6][4]) +{ + BLI_assert(clip_flag & V3D_PROJ_TEST_CLIP_CONTENT); + + float *clip_xmin = NULL, *clip_xmax = NULL; + float *clip_ymin = NULL, *clip_ymax = NULL; + float *clip_zmin = NULL, *clip_zmax = NULL; + + int planes_len = 0; + + /* The order of `planes` has been selected based on the likelihood of points being fully + * outside the plane to increase the chance of an early exit in #clip_segment_v3_plane_n. + * With "near" being most likely and "far" being unlikely. + * + * Otherwise the order of axes in `planes` isn't significant. */ + + if (clip_flag & V3D_PROJ_TEST_CLIP_NEAR) { + clip_zmin = planes[planes_len++]; + } + if (clip_flag & V3D_PROJ_TEST_CLIP_WIN) { + clip_xmin = planes[planes_len++]; + clip_xmax = planes[planes_len++]; + clip_ymin = planes[planes_len++]; + clip_ymax = planes[planes_len++]; + } + if (clip_flag & V3D_PROJ_TEST_CLIP_FAR) { + clip_zmax = planes[planes_len++]; + } + + BLI_assert(planes_len <= 6); + if (planes_len != 0) { + RegionView3D *rv3d = region->regiondata; + float projmat[4][4]; + ED_view3d_ob_project_mat_get(rv3d, ob, projmat); + planes_from_projmat(projmat, clip_xmin, clip_xmax, clip_ymin, clip_ymax, clip_zmin, clip_zmax); + } + return planes_len; +} + +/** + * Edge projection is more involved since part of the edge may be behind the view + * or extend beyond the far limits. In the case of single points, these can be ignored. + * However it just may still be visible on screen, so constrained the edge to planes + * defined by the port to ensure both ends of the edge can be projected, see T32214. + * + * \note This is unrelated to #V3D_PROJ_TEST_CLIP_BB which must be checked separately. + */ +static bool view3d_project_segment_to_screen_with_content_clip_planes( + const ARegion *region, + const float v_a[3], + const float v_b[3], + const eV3DProjTest clip_flag, + const rctf *win_rect, + const float content_planes[][4], + const int content_planes_len, + /* Output. */ + float r_screen_co_a[2], + float r_screen_co_b[2]) +{ + /* Clipping already handled, no need to check in projection. */ + eV3DProjTest clip_flag_nowin = clip_flag & ~V3D_PROJ_TEST_CLIP_WIN; + + const eV3DProjStatus status_a = ED_view3d_project_float_object( + region, v_a, r_screen_co_a, clip_flag_nowin); + const eV3DProjStatus status_b = ED_view3d_project_float_object( + region, v_b, r_screen_co_b, clip_flag_nowin); + + if ((status_a == V3D_PROJ_RET_OK) && (status_b == V3D_PROJ_RET_OK)) { + if (clip_flag & V3D_PROJ_TEST_CLIP_WIN) { + if (!BLI_rctf_isect_segment(win_rect, r_screen_co_a, r_screen_co_b)) { + return false; + } + } + } + else { + if (content_planes_len == 0) { + return false; + } + + /* Both too near, ignore. */ + if ((status_a & V3D_PROJ_TEST_CLIP_NEAR) && (status_b & V3D_PROJ_TEST_CLIP_NEAR)) { + return false; + } + + /* Both too far, ignore. */ + if ((status_a & V3D_PROJ_TEST_CLIP_FAR) && (status_b & V3D_PROJ_TEST_CLIP_FAR)) { + return false; + } + + /* Simple cases have been ruled out, clip by viewport planes, then re-project. */ + float v_a_clip[3], v_b_clip[3]; + if (!clip_segment_v3_plane_n( + v_a, v_b, content_planes, content_planes_len, v_a_clip, v_b_clip)) { + return false; + } + + if ((ED_view3d_project_float_object(region, v_a_clip, r_screen_co_a, clip_flag_nowin) != + V3D_PROJ_RET_OK) || + (ED_view3d_project_float_object(region, v_b_clip, r_screen_co_b, clip_flag_nowin) != + V3D_PROJ_RET_OK)) { + return false; + } + + /* No need for #V3D_PROJ_TEST_CLIP_WIN check here, + * clipping the segment by planes handle this. */ + } + + return true; +} + +/** + * Project an edge, points that fail to project are tagged with #IS_CLIPPED. + */ +static bool view3d_project_segment_to_screen_with_clip_tag(const ARegion *region, + const float v_a[3], + const float v_b[3], + const eV3DProjTest clip_flag, + /* Output. */ + float r_screen_co_a[2], + float r_screen_co_b[2]) +{ + int count = 0; + + if (ED_view3d_project_float_object(region, v_a, r_screen_co_a, clip_flag) == V3D_PROJ_RET_OK) { + count++; + } + else { + r_screen_co_a[0] = IS_CLIPPED; /* weak */ + /* screen_co_a[1]: intentionally don't set this so we get errors on misuse */ + } + + if (ED_view3d_project_float_object(region, v_b, r_screen_co_b, clip_flag) == V3D_PROJ_RET_OK) { + count++; + } + else { + r_screen_co_b[0] = IS_CLIPPED; /* weak */ + /* screen_co_b[1]: intentionally don't set this so we get errors on misuse */ + } + + /* Caller may want to know this value, for now it's not needed. */ + return count != 0; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Private User Data Structures + * \{ */ + typedef struct foreachScreenObjectVert_userData { - void (*func)(void *userData, MVert *mv, const float screen_co_b[2], int index); + void (*func)(void *userData, MVert *mv, const float screen_co[2], int index); void *userData; ViewContext vc; eV3DProjTest clip_flag; } foreachScreenObjectVert_userData; typedef struct foreachScreenVert_userData { - void (*func)(void *userData, BMVert *eve, const float screen_co_b[2], int index); + void (*func)(void *userData, BMVert *eve, const float screen_co[2], int index); void *userData; ViewContext vc; eV3DProjTest clip_flag; @@ -73,8 +237,16 @@ typedef struct foreachScreenEdge_userData { int index); void *userData; ViewContext vc; - rctf win_rect; /* copy of: vc.region->winx/winy, use for faster tests, minx/y will always be 0 */ eV3DProjTest clip_flag; + + rctf win_rect; /* copy of: vc.region->winx/winy, use for faster tests, minx/y will always be 0 */ + + /** + * Clip plans defined by the view bounds, + * use when #V3D_PROJ_TEST_CLIP_CONTENT is enabled. + */ + float content_planes[6][4]; + int content_planes_len; } foreachScreenEdge_userData; typedef struct foreachScreenFace_userData { @@ -91,7 +263,11 @@ typedef struct foreachScreenFace_userData { * use the object matrix in the usual way. */ -/* ------------------------------------------------------------------------ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edit-Mesh: For Each Screen Vertex + * \{ */ static void meshobject_foreachScreenVert__mapFunc(void *userData, int index, @@ -120,6 +296,7 @@ void meshobject_foreachScreenVert( void *userData, eV3DProjTest clip_flag) { + BLI_assert((clip_flag & V3D_PROJ_TEST_CLIP_CONTENT) == 0); foreachScreenObjectVert_userData data; Mesh *me; @@ -150,17 +327,17 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, { foreachScreenVert_userData *data = userData; BMVert *eve = BM_vert_at_index(data->vc.em->bm, index); + if (UNLIKELY(BM_elem_flag_test(eve, BM_ELEM_HIDDEN))) { + return; + } - if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - float screen_co[2]; - - if (ED_view3d_project_float_object(data->vc.region, co, screen_co, data->clip_flag) != - V3D_PROJ_RET_OK) { - return; - } - - data->func(data->userData, eve, screen_co, index); + float screen_co[2]; + if (ED_view3d_project_float_object(data->vc.region, co, screen_co, data->clip_flag) != + V3D_PROJ_RET_OK) { + return; } + + data->func(data->userData, eve, screen_co, index); } void mesh_foreachScreenVert( @@ -189,38 +366,37 @@ void mesh_foreachScreenVert( BKE_mesh_foreach_mapped_vert(me, mesh_foreachScreenVert__mapFunc, &data, MESH_FOREACH_NOP); } -/* ------------------------------------------------------------------------ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edit-Mesh: For Each Screen Mesh Edge + * \{ */ static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, - const float v0co[3], - const float v1co[3]) + const float v_a[3], + const float v_b[3]) { foreachScreenEdge_userData *data = userData; BMEdge *eed = BM_edge_at_index(data->vc.em->bm, index); + if (UNLIKELY(BM_elem_flag_test(eed, BM_ELEM_HIDDEN))) { + return; + } - if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { - float screen_co_a[2]; - float screen_co_b[2]; - eV3DProjTest clip_flag_nowin = data->clip_flag & ~V3D_PROJ_TEST_CLIP_WIN; - - if (ED_view3d_project_float_object(data->vc.region, v0co, screen_co_a, clip_flag_nowin) != - V3D_PROJ_RET_OK) { - return; - } - if (ED_view3d_project_float_object(data->vc.region, v1co, screen_co_b, clip_flag_nowin) != - V3D_PROJ_RET_OK) { - return; - } - - if (data->clip_flag & V3D_PROJ_TEST_CLIP_WIN) { - if (!BLI_rctf_isect_segment(&data->win_rect, screen_co_a, screen_co_b)) { - return; - } - } - - data->func(data->userData, eed, screen_co_a, screen_co_b, index); + float screen_co_a[2], screen_co_b[2]; + if (!view3d_project_segment_to_screen_with_content_clip_planes(data->vc.region, + v_a, + v_b, + data->clip_flag, + &data->win_rect, + data->content_planes, + data->content_planes_len, + screen_co_a, + screen_co_b)) { + return; } + + data->func(data->userData, eed, screen_co_a, screen_co_b, index); } void mesh_foreachScreenEdge(ViewContext *vc, @@ -254,11 +430,23 @@ void mesh_foreachScreenEdge(ViewContext *vc, ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ } + if (clip_flag & V3D_PROJ_TEST_CLIP_CONTENT) { + data.content_planes_len = content_planes_from_clip_flag( + vc->region, vc->obedit, clip_flag, data.content_planes); + } + else { + data.content_planes_len = 0; + } + BM_mesh_elem_table_ensure(vc->em->bm, BM_EDGE); BKE_mesh_foreach_mapped_edge(me, mesh_foreachScreenEdge__mapFunc, &data); } -/* ------------------------------------------------------------------------ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edit-Mesh: For Each Screen Edge (Bounding Box Clipped) + * \{ */ /** * Only call for bound-box clipping. @@ -266,46 +454,36 @@ void mesh_foreachScreenEdge(ViewContext *vc, */ static void mesh_foreachScreenEdge_clip_bb_segment__mapFunc(void *userData, int index, - const float v0co[3], - const float v1co[3]) + const float v_a[3], + const float v_b[3]) { foreachScreenEdge_userData *data = userData; BMEdge *eed = BM_edge_at_index(data->vc.em->bm, index); + if (UNLIKELY(BM_elem_flag_test(eed, BM_ELEM_HIDDEN))) { + return; + } BLI_assert(data->clip_flag & V3D_PROJ_TEST_CLIP_BB); - if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { - float v0co_clip[3]; - float v1co_clip[3]; - - if (!clip_segment_v3_plane_n(v0co, v1co, data->vc.rv3d->clip_local, 4, v0co_clip, v1co_clip)) { - return; - } - - float screen_co_a[2]; - float screen_co_b[2]; - - /* Clipping already handled, no need to check in projection. */ - eV3DProjTest clip_flag_nowin = data->clip_flag & - ~(V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_BB); - - if (ED_view3d_project_float_object(data->vc.region, v0co_clip, screen_co_a, clip_flag_nowin) != - V3D_PROJ_RET_OK) { - return; - } - if (ED_view3d_project_float_object(data->vc.region, v1co_clip, screen_co_b, clip_flag_nowin) != - V3D_PROJ_RET_OK) { - return; - } - - if (data->clip_flag & V3D_PROJ_TEST_CLIP_WIN) { - if (!BLI_rctf_isect_segment(&data->win_rect, screen_co_a, screen_co_b)) { - return; - } - } + float v_a_clip[3], v_b_clip[3]; + if (!clip_segment_v3_plane_n(v_a, v_b, data->vc.rv3d->clip_local, 4, v_a_clip, v_b_clip)) { + return; + } - data->func(data->userData, eed, screen_co_a, screen_co_b, index); + float screen_co_a[2], screen_co_b[2]; + if (!view3d_project_segment_to_screen_with_content_clip_planes(data->vc.region, + v_a_clip, + v_b_clip, + data->clip_flag, + &data->win_rect, + data->content_planes, + data->content_planes_len, + screen_co_a, + screen_co_b)) { + return; } + + data->func(data->userData, eed, screen_co_a, screen_co_b, index); } /** @@ -339,6 +517,14 @@ void mesh_foreachScreenEdge_clip_bb_segment(ViewContext *vc, data.userData = userData; data.clip_flag = clip_flag; + if (clip_flag & V3D_PROJ_TEST_CLIP_CONTENT) { + data.content_planes_len = content_planes_from_clip_flag( + vc->region, vc->obedit, clip_flag, data.content_planes); + } + else { + data.content_planes_len = 0; + } + BM_mesh_elem_table_ensure(vc->em->bm, BM_EDGE); if ((clip_flag & V3D_PROJ_TEST_CLIP_BB) && (vc->rv3d->clipbb != NULL)) { @@ -350,7 +536,11 @@ void mesh_foreachScreenEdge_clip_bb_segment(ViewContext *vc, } } -/* ------------------------------------------------------------------------ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edit-Mesh: For Each Screen Face Center + * \{ */ static void mesh_foreachScreenFace__mapFunc(void *userData, int index, @@ -359,14 +549,17 @@ static void mesh_foreachScreenFace__mapFunc(void *userData, { foreachScreenFace_userData *data = userData; BMFace *efa = BM_face_at_index(data->vc.em->bm, index); + if (UNLIKELY(BM_elem_flag_test(efa, BM_ELEM_HIDDEN))) { + return; + } - if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - float screen_co[2]; - if (ED_view3d_project_float_object(data->vc.region, cent, screen_co, data->clip_flag) == - V3D_PROJ_RET_OK) { - data->func(data->userData, efa, screen_co, index); - } + float screen_co[2]; + if (ED_view3d_project_float_object(data->vc.region, cent, screen_co, data->clip_flag) != + V3D_PROJ_RET_OK) { + return; } + + data->func(data->userData, efa, screen_co, index); } void mesh_foreachScreenFace( @@ -375,6 +568,7 @@ void mesh_foreachScreenFace( void *userData, const eV3DProjTest clip_flag) { + BLI_assert((clip_flag & V3D_PROJ_TEST_CLIP_CONTENT) == 0); foreachScreenFace_userData data; Mesh *me = editbmesh_get_eval_cage_from_orig( @@ -398,7 +592,11 @@ void mesh_foreachScreenFace( } } -/* ------------------------------------------------------------------------ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edit-Nurbs: For Each Screen Vertex + * \{ */ void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, @@ -486,7 +684,11 @@ void nurbs_foreachScreenVert(ViewContext *vc, } } -/* ------------------------------------------------------------------------ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edit-Meta: For Each Screen Meta-Element + * \{ */ /* ED_view3d_init_mats_rv3d must be called first */ void mball_foreachScreenElem(struct ViewContext *vc, @@ -510,7 +712,11 @@ void mball_foreachScreenElem(struct ViewContext *vc, } } -/* ------------------------------------------------------------------------ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edit-Lattice: For Each Screen Vertex + * \{ */ void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, const float screen_co[2]), @@ -543,7 +749,11 @@ void lattice_foreachScreenVert(ViewContext *vc, } } -/* ------------------------------------------------------------------------ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edit-Armature: For Each Screen Bone + * \{ */ /* ED_view3d_init_mats_rv3d must be called first */ void armature_foreachScreenBone(struct ViewContext *vc, @@ -559,39 +769,59 @@ void armature_foreachScreenBone(struct ViewContext *vc, ED_view3d_check_mats_rv3d(vc->rv3d); - for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { - if (EBONE_VISIBLE(arm, ebone)) { - float screen_co_a[2], screen_co_b[2]; - int points_proj_tot = 0; + float content_planes[6][4]; + int content_planes_len; + rctf win_rect; + + if (clip_flag & V3D_PROJ_TEST_CLIP_CONTENT) { + content_planes_len = content_planes_from_clip_flag( + vc->region, vc->obedit, clip_flag, content_planes); + win_rect.xmin = 0; + win_rect.ymin = 0; + win_rect.xmax = vc->region->winx; + win_rect.ymax = vc->region->winy; + } + else { + content_planes_len = 0; + } - /* project head location to screenspace */ - if (ED_view3d_project_float_object(vc->region, ebone->head, screen_co_a, clip_flag) == - V3D_PROJ_RET_OK) { - points_proj_tot++; - } - else { - screen_co_a[0] = IS_CLIPPED; /* weak */ - /* screen_co_a[1]: intentionally don't set this so we get errors on misuse */ - } + for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { + if (!EBONE_VISIBLE(arm, ebone)) { + continue; + } - /* project tail location to screenspace */ - if (ED_view3d_project_float_object(vc->region, ebone->tail, screen_co_b, clip_flag) == - V3D_PROJ_RET_OK) { - points_proj_tot++; - } - else { - screen_co_b[0] = IS_CLIPPED; /* weak */ - /* screen_co_b[1]: intentionally don't set this so we get errors on misuse */ + float screen_co_a[2], screen_co_b[2]; + const float *v_a = ebone->head, *v_b = ebone->tail; + + if (clip_flag & V3D_PROJ_TEST_CLIP_CONTENT) { + if (!view3d_project_segment_to_screen_with_content_clip_planes(vc->region, + v_a, + v_b, + clip_flag, + &win_rect, + content_planes, + content_planes_len, + screen_co_a, + screen_co_b)) { + continue; } - - if (points_proj_tot) { /* at least one point's projection worked */ - func(userData, ebone, screen_co_a, screen_co_b); + } + else { + if (!view3d_project_segment_to_screen_with_clip_tag( + vc->region, v_a, v_b, clip_flag, screen_co_a, screen_co_b)) { + continue; } } + + func(userData, ebone, screen_co_a, screen_co_b); } } -/* ------------------------------------------------------------------------ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Pose: For Each Screen Bone + * \{ */ /* ED_view3d_init_mats_rv3d must be called first */ /* almost _exact_ copy of #armature_foreachScreenBone */ @@ -610,35 +840,53 @@ void pose_foreachScreenBone(struct ViewContext *vc, ED_view3d_check_mats_rv3d(vc->rv3d); + float content_planes[6][4]; + int content_planes_len; + rctf win_rect; + + if (clip_flag & V3D_PROJ_TEST_CLIP_CONTENT) { + content_planes_len = content_planes_from_clip_flag( + vc->region, ob_eval, clip_flag, content_planes); + win_rect.xmin = 0; + win_rect.ymin = 0; + win_rect.xmax = vc->region->winx; + win_rect.ymax = vc->region->winy; + } + else { + content_planes_len = 0; + } + for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - if (PBONE_VISIBLE(arm_eval, pchan->bone)) { - bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name); - float screen_co_a[2], screen_co_b[2]; - int points_proj_tot = 0; - - /* project head location to screenspace */ - if (ED_view3d_project_float_object( - vc->region, pchan_eval->pose_head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) { - points_proj_tot++; - } - else { - screen_co_a[0] = IS_CLIPPED; /* weak */ - /* screen_co_a[1]: intentionally don't set this so we get errors on misuse */ - } + if (!PBONE_VISIBLE(arm_eval, pchan->bone)) { + continue; + } - /* project tail location to screenspace */ - if (ED_view3d_project_float_object( - vc->region, pchan_eval->pose_tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) { - points_proj_tot++; + bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name); + float screen_co_a[2], screen_co_b[2]; + const float *v_a = pchan_eval->pose_head, *v_b = pchan_eval->pose_tail; + + if (clip_flag & V3D_PROJ_TEST_CLIP_CONTENT) { + if (!view3d_project_segment_to_screen_with_content_clip_planes(vc->region, + v_a, + v_b, + clip_flag, + &win_rect, + content_planes, + content_planes_len, + screen_co_a, + screen_co_b)) { + continue; } - else { - screen_co_b[0] = IS_CLIPPED; /* weak */ - /* screen_co_b[1]: intentionally don't set this so we get errors on misuse */ - } - - if (points_proj_tot) { /* at least one point's projection worked */ - func(userData, pchan, screen_co_a, screen_co_b); + } + else { + if (!view3d_project_segment_to_screen_with_clip_tag( + vc->region, v_a, v_b, clip_flag, screen_co_a, screen_co_b)) { + continue; } } + + func(userData, pchan, screen_co_a, screen_co_b); } } + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_navigate_fly.c index 2d499cf85c7..5752837c40f 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_navigate_fly.c @@ -19,7 +19,7 @@ * * Interactive fly navigation modal operator (flying around in space). * - * \note Similar logic to `view3d_walk.c` changes here may apply there too. + * \note Similar logic to `view3d_navigate_walk.c` changes here may apply there too. */ /* defines VIEW3D_OT_fly modal operator */ @@ -101,7 +101,7 @@ typedef enum eFlyPanState { FLY_AXISLOCK_STATE_ACTIVE = 2, } eFlyPanState; -/* called in transform_ops.c, on each regeneration of keymaps */ +/* Called in transform_ops.c, on each regeneration of key-maps. */ void fly_modal_keymap(wmKeyConfig *keyconf) { static const EnumPropertyItem modal_items[] = { @@ -122,7 +122,7 @@ void fly_modal_keymap(wmKeyConfig *keyconf) {FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""}, {FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"}, - {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "X Axis Correction", "Z axis correction (toggle)"}, + {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction (toggle)"}, {FLY_MODAL_PRECISION_ENABLE, "PRECISION_ENABLE", 0, "Precision", ""}, {FLY_MODAL_PRECISION_DISABLE, "PRECISION_DISABLE", 0, "Precision (Off)", ""}, @@ -189,7 +189,7 @@ typedef struct FlyInfo { wmNDOFMotionData *ndof; #endif - /* fly state state */ + /* Fly state. */ /** The speed the view is moving per redraw. */ float speed; /** Axis index to move along by default Z to move along the view. */ @@ -610,8 +610,7 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event) fly->pan_view = false; break; - /* implement WASD keys, - * comments only for 'forward '*/ + /* Implement WASD keys, comments only for 'forward'. */ case FLY_MODAL_DIR_FORWARD: if (fly->axis == 2 && fly->speed < 0.0f) { /* reverse direction stops, tap again to continue */ @@ -758,9 +757,6 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm) #define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */ #define FLY_SMOOTH_FAC 20.0f /* higher value less lag */ - /* fly mode - Shift+F - * a fly loop where the user can move move the view as if they are flying - */ RegionView3D *rv3d = fly->rv3d; /* 3x3 copy of the view matrix so we can move along the view axis */ @@ -772,7 +768,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm) float moffset[2]; /* mouse offset from the views center */ float tmp_quat[4]; /* used for rotating the view */ - /* x and y margin are define the safe area where the mouses movement wont rotate the view */ + /* x and y margin defining the safe area where the mouse's movement won't rotate the view */ int xmargin, ymargin; #ifdef NDOF_FLY_DEBUG @@ -812,10 +808,10 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm) moffset[1] = 0; } - /* scale the mouse movement by this value - scales mouse movement to the view size - * moffset[0] / (region->winx-xmargin * 2) - window size minus margin (same for y) + /* Scale the mouse movement by this value - scales mouse movement to the view size + * `moffset[0] / (region->winx-xmargin * 2)` - window size minus margin (same for y) * - * the mouse moves isn't linear */ + * the mouse moves isn't linear. */ if (moffset[0]) { moffset[0] /= fly->width - (xmargin * 2); diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index ab4cf0c2135..09936b41a74 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -20,7 +20,7 @@ * Interactive walk navigation modal operator * (similar to walking around in a first person game). * - * \note Similar logic to `view3d_fly.c` changes here may apply there too. + * \note Similar logic to `view3d_navigate_fly.c` changes here may apply there too. */ /* defines VIEW3D_OT_navigate - walk modal operator */ @@ -98,9 +98,10 @@ enum { WALK_MODAL_JUMP, WALK_MODAL_JUMP_STOP, WALK_MODAL_TELEPORT, - WALK_MODAL_TOGGLE, + WALK_MODAL_GRAVITY_TOGGLE, WALK_MODAL_ACCELERATE, WALK_MODAL_DECELERATE, + WALK_MODAL_AXIS_LOCK_Z, }; enum { @@ -129,7 +130,19 @@ typedef enum eWalkGravityState { WALK_GRAVITY_STATE_ON, } eWalkGravityState; -/* called in transform_ops.c, on each regeneration of keymaps */ +/* Relative view axis z axis locking. */ +typedef enum eWalkLockState { + /* Disabled. */ + WALK_AXISLOCK_STATE_OFF = 0, + + /* Moving. */ + WALK_AXISLOCK_STATE_ACTIVE = 2, + + /* Done moving, it cannot be activated again. */ + WALK_AXISLOCK_STATE_DONE = 3, +} eWalkLockState; + +/* Called in transform_ops.c, on each regeneration of key-maps. */ void walk_modal_keymap(wmKeyConfig *keyconf) { static const EnumPropertyItem modal_items[] = { @@ -164,7 +177,9 @@ void walk_modal_keymap(wmKeyConfig *keyconf) {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"}, {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"}, - {WALK_MODAL_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"}, + {WALK_MODAL_GRAVITY_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"}, + + {WALK_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction"}, {0, NULL, 0, NULL, NULL}, }; @@ -234,7 +249,7 @@ typedef struct WalkInfo { wmNDOFMotionData *ndof; #endif - /* walk state state */ + /* Walk state. */ /** The base speed without run/slow down modifications. */ float base_speed; /** The speed the view is moving per redraw. */ @@ -292,6 +307,10 @@ typedef struct WalkInfo { /** To use for fast/slow speeds. */ float speed_factor; + eWalkLockState zlock; + /** Nicer dynamics. */ + float zlock_momentum; + struct SnapObjectContext *snap_context; struct View3DCameraControl *v3d_camera_control; @@ -540,6 +559,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->jump_height = U.walk_navigation.jump_height; walk->speed = U.walk_navigation.walk_speed; walk->speed_factor = U.walk_navigation.walk_speed_factor; + walk->zlock = WALK_AXISLOCK_STATE_OFF; walk->gravity_state = WALK_GRAVITY_STATE_OFF; @@ -694,7 +714,7 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) walk->is_cursor_first = false; } else { - /* note, its possible the system isn't giving us the warp event + /* NOTE: its possible the system isn't giving us the warp event * ideally we shouldn't have to worry about this, see: T45361 */ wmWindow *win = CTX_wm_window(C); WM_cursor_warp(win, @@ -708,8 +728,6 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) walk->is_cursor_absolute = true; copy_v2_v2_int(walk->prev_mval, event->mval); copy_v2_v2_int(walk->center_mval, event->mval); - /* Without this we can't turn 180d with the default speed of 1.0. */ - walk->mouse_speed *= 4.0f; } #endif /* USE_TABLET_SUPPORT */ @@ -941,7 +959,7 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) #undef JUMP_TIME_MAX #undef JUMP_SPEED_MIN - case WALK_MODAL_TOGGLE: + case WALK_MODAL_GRAVITY_TOGGLE: if (walk->navigation_mode == WALK_MODE_GRAVITY) { walk_navigation_mode_set(walk, WALK_MODE_FREE); } @@ -949,6 +967,13 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) walk_navigation_mode_set(walk, WALK_MODE_GRAVITY); } break; + + case WALK_MODAL_AXIS_LOCK_Z: + if (walk->zlock != WALK_AXISLOCK_STATE_DONE) { + walk->zlock = WALK_AXISLOCK_STATE_ACTIVE; + walk->zlock_momentum = 0.0f; + } + break; } } } @@ -982,16 +1007,15 @@ static float getVelocityZeroTime(const float gravity, const float velocity) static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) { -#define WALK_ROTATE_RELATIVE_FAC 2.2f /* More is faster, relative to region size. */ -#define WALK_ROTATE_CONSTANT_FAC DEG2RAD(0.15f) /* More is faster, radians per-pixel. */ +#define WALK_ROTATE_TABLET_FAC 8.8f /* Higher is faster, relative to region size. */ +#define WALK_ROTATE_CONSTANT_FAC DEG2RAD(0.15f) /* Higher is faster, radians per-pixel. */ #define WALK_TOP_LIMIT DEG2RADF(85.0f) #define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f) #define WALK_MOVE_SPEED base_speed #define WALK_BOOST_FACTOR ((void)0, walk->speed_factor) +#define WALK_ZUP_CORRECT_FAC 0.1f /* Amount to correct per step. */ +#define WALK_ZUP_CORRECT_ACCEL 0.05f /* Increase upright momentum each step. */ - /* walk mode - Ctrl+Shift+F - * a walk loop where the user can move move the view as if they are in a walk game - */ RegionView3D *rv3d = walk->rv3d; ARegion *region = walk->region; @@ -1025,20 +1049,25 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) /* Should we redraw? */ if ((walk->active_directions) || moffset[0] || moffset[1] || - walk->teleport.state == WALK_TELEPORT_STATE_ON || - walk->gravity_state != WALK_GRAVITY_STATE_OFF || is_confirm) { + walk->zlock == WALK_AXISLOCK_STATE_ACTIVE || + walk->gravity_state != WALK_GRAVITY_STATE_OFF || + walk->teleport.state == WALK_TELEPORT_STATE_ON || is_confirm) { float dvec_tmp[3]; /* time how fast it takes for us to redraw, * this is so simple scenes don't walk too fast */ double time_current; float time_redraw; + float time_redraw_clamped; #ifdef NDOF_WALK_DRAW_TOOMUCH walk->redraw = 1; #endif time_current = PIL_check_seconds_timer(); time_redraw = (float)(time_current - walk->time_lastdraw); + /* Clamp redraw time to avoid jitter in roll correction. */ + time_redraw_clamped = min_ff(0.05f, time_redraw); + walk->time_lastdraw = time_current; /* base speed in m/s */ @@ -1067,7 +1096,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) #ifdef USE_TABLET_SUPPORT if (walk->is_cursor_absolute) { y /= region->winy; - y *= WALK_ROTATE_RELATIVE_FAC; + y *= WALK_ROTATE_TABLET_FAC; } else #endif @@ -1116,7 +1145,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) #ifdef USE_TABLET_SUPPORT if (walk->is_cursor_absolute) { x /= region->winx; - x *= WALK_ROTATE_RELATIVE_FAC; + x *= WALK_ROTATE_TABLET_FAC; } else #endif @@ -1131,6 +1160,32 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) axis_angle_to_quat_single(tmp_quat, 'Z', x); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); } + + if (walk->zlock == WALK_AXISLOCK_STATE_ACTIVE) { + float upvec[3]; + copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); + mul_m3_v3(mat, upvec); + + /* Make sure we have some z rolling. */ + if (fabsf(upvec[2]) > 0.00001f) { + float roll = upvec[2] * 5.0f; + /* Rotate the view about this axis. */ + copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); + mul_m3_v3(mat, upvec); + /* Rotate about the relative up vec. */ + axis_angle_to_quat(tmp_quat, + upvec, + roll * time_redraw_clamped * walk->zlock_momentum * + WALK_ZUP_CORRECT_FAC); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); + + walk->zlock_momentum += WALK_ZUP_CORRECT_ACCEL; + } + else { + /* Lock fixed, don't need to check it ever again. */ + walk->zlock = WALK_AXISLOCK_STATE_DONE; + } + } } /* WASD - 'move' translation code */ @@ -1321,7 +1376,8 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) add_v3_v3(rv3d->ofs, dvec_tmp); if (rv3d->persp == RV3D_CAMOB) { - walk->need_rotation_keyframe |= (moffset[0] || moffset[1]); + walk->need_rotation_keyframe |= (moffset[0] || moffset[1] || + walk->zlock == WALK_AXISLOCK_STATE_ACTIVE); walk->need_translation_keyframe |= (len_squared_v3(dvec_tmp) > FLT_EPSILON); walkMoveCamera( C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm); @@ -1336,7 +1392,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) } return OPERATOR_FINISHED; -#undef WALK_ROTATE_RELATIVE_FAC +#undef WALK_ROTATE_TABLET_FAC #undef WALK_TOP_LIMIT #undef WALK_BOTTOM_LIMIT #undef WALK_MOVE_SPEED diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c index 00e30f8afae..aa3bf46d2e5 100644 --- a/source/blender/editors/space_view3d/view3d_placement.c +++ b/source/blender/editors/space_view3d/view3d_placement.c @@ -252,7 +252,7 @@ static int dot_v3_array_find_max_index(const float dirs[][3], } /** - * Re-order \a mat so \a axis_align uses it's own axis which is closest to \a v. + * Re-order \a mat so \a axis_align uses its own axis which is closest to \a v. */ static bool mat3_align_axis_to_v3(float mat[3][3], const int axis_align, const float v[3]) { @@ -584,7 +584,7 @@ static bool calc_bbox(struct InteractivePlaceData *ipd, BoundBox *bounds) delta_a[x_axis] = 0.0f; delta_b[y_axis] = 0.0f; - /* Assign here in case secondary */ + /* Assign here in case secondary. */ fixed_aspect_dimension = max_ff(fabsf(delta_a[y_axis]), fabsf(delta_b[x_axis])); if (ipd->step[0].is_fixed_aspect) { @@ -961,7 +961,7 @@ static void view3d_interactive_add_calc_plane(bContext *C, const float view_axis_dot = fabsf(dot_v3v3(rv3d->viewinv[2], r_matrix_orient[plane_axis])); if (view_axis_dot < eps_view_align) { /* In this case, just project onto the view plane as it's important the location - * is _always_ under the mouse cursor, even if it turns out that wont lie on + * is _always_ under the mouse cursor, even if it turns out that won't lie on * the original 'plane' that's been calculated for us. */ plane_normal = rv3d->viewinv[2]; } @@ -974,7 +974,7 @@ static void view3d_interactive_add_calc_plane(bContext *C, /* Even if the calculation works, it's possible the point found is behind the view, * or very far away (past the far clipping). - * In either case creating objects wont be useful. */ + * In either case creating objects won't be useful. */ if (rv3d->is_persp) { float dir[3]; sub_v3_v3v3(dir, rv3d->viewinv[3], r_co_src); @@ -1196,7 +1196,7 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv } else { /* If the user runs this as an operator they should set the 'primitive_type', - * however running from operator search will end up at this point. */ + * however running from operator search will end up at this point. */ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_CUBE; ipd->use_tool = false; } @@ -1610,7 +1610,7 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot) ot->cancel = view3d_interactive_add_cancel; ot->poll = view3d_interactive_add_poll; - /* Note, let the operator we call handle undo and registering itself. */ + /* NOTE: let the operator we call handle undo and registering itself. */ /* flags */ ot->flag = 0; @@ -1762,7 +1762,7 @@ static void WIDGETGROUP_placement_setup(const bContext *UNUSED(C), wmGizmoGroup gizmo->flag |= WM_GIZMO_HIDDEN_KEYMAP; } - /* Sets the gizmos custom-data which has it's own free callback. */ + /* Sets the gizmos custom-data which has its own free callback. */ preview_plane_cursor_setup(gzgroup); } @@ -1830,7 +1830,7 @@ static void gizmo_plane_update_cursor(const bContext *C, /* This ensures the snap gizmo has settings from this tool. * This function call could be moved a more appropriate place, * responding to the setting being changed for example, - * however setting the value isn't expensive, so do it here. */ + * however setting the value isn't expensive, so do it here. */ idp_snap_gizmo_update_snap_elements(scene, snap_to, snap_gizmo); view3d_interactive_add_calc_plane((bContext *)C, @@ -1957,7 +1957,7 @@ struct PlacementCursor { /** * Enable this while the modal operator is running, - * so the preview-plane doesn't show at the same time time as add-object preview shape + * so the preview-plane doesn't show at the same time as add-object preview shape * since it's distracting & not helpful. */ bool do_draw; diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 24d34e514c5..d926ea84e0f 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -330,6 +330,17 @@ float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3], bool *r_f return zfac; } +/** + * Calculate a depth value from `co` (result should only be used for comparison). + */ +float ED_view3d_calc_depth_for_comparison(const RegionView3D *rv3d, const float co[3]) +{ + if (rv3d->is_persp) { + return ED_view3d_calc_zfac(rv3d, co, NULL); + } + return -dot_v3v3(rv3d->viewinv[2], co); +} + static void view3d_win_to_ray_segment(struct Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, @@ -550,7 +561,7 @@ void ED_view3d_win_to_3d(const View3D *v3d, copy_v3_v3(ray_origin, rv3d->viewinv[3]); ED_view3d_win_to_vector(region, mval, ray_direction); - /* Note: we could use #isect_line_plane_v3() + /* NOTE: we could use #isect_line_plane_v3() * however we want the intersection to be in front of the view no matter what, * so apply the unsigned factor instead. */ plane_from_point_normal_v3(plane, depth_pt, rv3d->viewinv[2]); @@ -788,7 +799,7 @@ bool ED_view3d_win_to_segment_clipped(struct Depsgraph *depsgraph, /** \name Utility functions for projection * \{ */ -void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, Object *ob, float r_pmat[4][4]) +void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, const Object *ob, float r_pmat[4][4]) { float vmat[4][4]; @@ -809,23 +820,30 @@ void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, /** * Convert between region relative coordinates (x,y) and depth component z and * a point in world space. */ -void ED_view3d_project(const struct ARegion *region, const float world[3], float r_region_co[3]) +void ED_view3d_project_v3(const struct ARegion *region, const float world[3], float r_region_co[3]) { /* Viewport is set up to make coordinates relative to the region, not window. */ RegionView3D *rv3d = region->regiondata; const int viewport[4] = {0, 0, region->winx, region->winy}; + GPU_matrix_project_3fv(world, rv3d->viewmat, rv3d->winmat, viewport, r_region_co); +} - GPU_matrix_project(world, rv3d->viewmat, rv3d->winmat, viewport, r_region_co); +void ED_view3d_project_v2(const struct ARegion *region, const float world[3], float r_region_co[2]) +{ + /* Viewport is set up to make coordinates relative to the region, not window. */ + RegionView3D *rv3d = region->regiondata; + const int viewport[4] = {0, 0, region->winx, region->winy}; + GPU_matrix_project_2fv(world, rv3d->viewmat, rv3d->winmat, viewport, r_region_co); } -bool ED_view3d_unproject( +bool ED_view3d_unproject_v3( const struct ARegion *region, float regionx, float regiony, float regionz, float world[3]) { RegionView3D *rv3d = region->regiondata; const int viewport[4] = {0, 0, region->winx, region->winy}; const float region_co[3] = {regionx, regiony, regionz}; - return GPU_matrix_unproject(region_co, rv3d->viewmat, rv3d->winmat, viewport, world); + return GPU_matrix_unproject_3fv(region_co, rv3d->viewmat, rv3d->winmat, viewport, world); } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 757ed13ac28..ecf43c734e2 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -520,42 +520,16 @@ static void do_lasso_select_pose__do_tag(void *userData, const float screen_co_b[2]) { LassoSelectUserData *data = userData; - bArmature *arm = data->vc->obact->data; - - if (PBONE_SELECTABLE(arm, pchan->bone)) { - bool is_point_done = false; - int points_proj_tot = 0; - - /* project head location to screenspace */ - if (screen_co_a[0] != IS_CLIPPED) { - points_proj_tot++; - if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && - BLI_lasso_is_point_inside( - data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) { - is_point_done = true; - } - } - - /* project tail location to screenspace */ - if (screen_co_b[0] != IS_CLIPPED) { - points_proj_tot++; - if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && - BLI_lasso_is_point_inside( - data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) { - is_point_done = true; - } - } + const bArmature *arm = data->vc->obact->data; + if (!PBONE_SELECTABLE(arm, pchan->bone)) { + return; + } - /* if one of points selected, we skip the bone itself */ - if ((is_point_done == true) || ((is_point_done == false) && (points_proj_tot == 2) && - BLI_lasso_is_edge_inside(data->mcoords, - data->mcoords_len, - UNPACK2(screen_co_a), - UNPACK2(screen_co_b), - INT_MAX))) { - pchan->bone->flag |= BONE_DONE; - } - data->is_changed |= is_point_done; + if (BLI_rctf_isect_segment(data->rect_fl, screen_co_a, screen_co_b) && + BLI_lasso_is_edge_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) { + pchan->bone->flag |= BONE_DONE; + data->is_changed = true; } } static void do_lasso_tag_pose(ViewContext *vc, @@ -580,7 +554,11 @@ static void do_lasso_tag_pose(ViewContext *vc, ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d); - pose_foreachScreenBone(&vc_tmp, do_lasso_select_pose__do_tag, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + /* Treat bones as clipped segments (no joints). */ + pose_foreachScreenBone(&vc_tmp, + do_lasso_select_pose__do_tag, + &data, + V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT); } static bool do_lasso_select_objects(ViewContext *vc, @@ -876,11 +854,16 @@ static bool do_lasso_select_mesh(ViewContext *vc, const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_NEAR | (use_zbuf ? 0 : V3D_PROJ_TEST_CLIP_BB); + /* Fully inside. */ mesh_foreachScreenEdge_clip_bb_segment( vc, do_lasso_select_mesh__doSelectEdge_pass0, &data_for_edge, clip_flag); if (data.is_done == false) { - mesh_foreachScreenEdge_clip_bb_segment( - vc, do_lasso_select_mesh__doSelectEdge_pass1, &data_for_edge, clip_flag); + /* Fall back to partially inside. + * Clip content to account for edges partially behind the view. */ + mesh_foreachScreenEdge_clip_bb_segment(vc, + do_lasso_select_mesh__doSelectEdge_pass1, + &data_for_edge, + clip_flag | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT); } } @@ -1022,46 +1005,76 @@ static void do_lasso_select_armature__doSelectBone(void *userData, const float screen_co_b[2]) { LassoSelectUserData *data = userData; - bArmature *arm = data->vc->obedit->data; - if (EBONE_VISIBLE(arm, ebone)) { - int is_ignore_flag = 0; - int is_inside_flag = 0; - - if (screen_co_a[0] != IS_CLIPPED) { - if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && - BLI_lasso_is_point_inside( - data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) { - is_inside_flag |= BONESEL_ROOT; - } - } - else { - is_ignore_flag |= BONESEL_ROOT; - } + const bArmature *arm = data->vc->obedit->data; + if (!EBONE_VISIBLE(arm, ebone)) { + return; + } - if (screen_co_b[0] != IS_CLIPPED) { - if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && - BLI_lasso_is_point_inside( - data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) { - is_inside_flag |= BONESEL_TIP; - } + int is_ignore_flag = 0; + int is_inside_flag = 0; + + if (screen_co_a[0] != IS_CLIPPED) { + if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) { + is_inside_flag |= BONESEL_ROOT; } - else { - is_ignore_flag |= BONESEL_TIP; + } + else { + is_ignore_flag |= BONESEL_ROOT; + } + + if (screen_co_b[0] != IS_CLIPPED) { + if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) { + is_inside_flag |= BONESEL_TIP; } + } + else { + is_ignore_flag |= BONESEL_TIP; + } - if (is_ignore_flag == 0) { - if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) || - BLI_lasso_is_edge_inside(data->mcoords, - data->mcoords_len, - UNPACK2(screen_co_a), - UNPACK2(screen_co_b), - INT_MAX)) { - is_inside_flag |= BONESEL_BONE; - } + if (is_ignore_flag == 0) { + if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) || + BLI_lasso_is_edge_inside(data->mcoords, + data->mcoords_len, + UNPACK2(screen_co_a), + UNPACK2(screen_co_b), + INT_MAX)) { + is_inside_flag |= BONESEL_BONE; } + } + + ebone->temp.i = is_inside_flag | (is_ignore_flag >> 16); +} +static void do_lasso_select_armature__doSelectBone_clip_content(void *userData, + EditBone *ebone, + const float screen_co_a[2], + const float screen_co_b[2]) +{ + LassoSelectUserData *data = userData; + bArmature *arm = data->vc->obedit->data; + if (!EBONE_VISIBLE(arm, ebone)) { + return; + } + + const int is_ignore_flag = ebone->temp.i << 16; + int is_inside_flag = ebone->temp.i & ~0xFFFF; - ebone->temp.i = is_inside_flag | (is_ignore_flag >> 16); + /* - When #BONESEL_BONE is set, there is nothing to do. + * - When #BONE_ROOTSEL or #BONE_TIPSEL have been set - they take priority over bone selection. + */ + if (is_inside_flag & (BONESEL_BONE | BONE_ROOTSEL | BONE_TIPSEL)) { + return; + } + + if (BLI_lasso_is_edge_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) { + is_inside_flag |= BONESEL_BONE; } + + ebone->temp.i = is_inside_flag | (is_ignore_flag >> 16); } static bool do_lasso_select_armature(ViewContext *vc, @@ -1086,9 +1099,18 @@ static bool do_lasso_select_armature(ViewContext *vc, ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + /* Operate on fully visible (non-clipped) points. */ armature_foreachScreenBone( vc, do_lasso_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + /* Operate on bones as segments clipped to the viewport bounds + * (needed to handle bones with both points outside the view). + * A separate pass is needed since clipped coordinates can't be used for selecting joints. */ + armature_foreachScreenBone(vc, + do_lasso_select_armature__doSelectBone_clip_content, + &data, + V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT); + data.is_changed |= ED_armature_edit_select_op_from_tagged(vc->obedit->data, sel_op); if (data.is_changed) { @@ -1356,7 +1378,7 @@ static bool view3d_lasso_select(bContext *C, changed = do_lasso_select_meta(vc, mcoords, mcoords_len, sel_op); break; default: - BLI_assert(!"lasso select on incorrect object type"); + BLI_assert_msg(0, "lasso select on incorrect object type"); break; } @@ -1811,7 +1833,7 @@ static bool bone_mouse_select_menu(bContext *C, continue; } /* We can hit a bone multiple times, so make sure we are not adding an already included bone - * to the list.*/ + * to the list. */ const bool is_duplicate_bone = BLI_gset_haskey(added_bones, bone_ptr); if (!is_duplicate_bone) { @@ -2269,7 +2291,7 @@ static bool ed_object_select_pick(bContext *C, /* In edit-mode do not activate. */ if (obcenter) { - /* note; shift+alt goes to group-flush-selecting */ + /* NOTE: shift+alt goes to group-flush-selecting. */ if (enumerate) { basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, extend, deselect, toggle); } @@ -2332,10 +2354,10 @@ static bool ed_object_select_pick(bContext *C, // TIMEIT_END(select_time); if (hits > 0) { - /* note: bundles are handling in the same way as bones */ + /* NOTE: bundles are handling in the same way as bones. */ const bool has_bones = object ? false : selectbuffer_has_bones(buffer, hits); - /* note; shift+alt goes to group-flush-selecting */ + /* NOTE: shift+alt goes to group-flush-selecting. */ if (enumerate) { if (has_bones && bone_mouse_select_menu(C, buffer, hits, false, extend, deselect, toggle)) { @@ -3071,6 +3093,9 @@ struct BoxSelectUserData_ForMeshEdge { struct EditSelectBuf_Cache *esel; uint backbuf_offset; }; +/** + * Pass 0 operates on edges when fully inside. + */ static void do_mesh_box_select__doSelectEdge_pass0( void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { @@ -3092,6 +3117,9 @@ static void do_mesh_box_select__doSelectEdge_pass0( data->is_changed = true; } } +/** + * Pass 1 operates on edges when partially inside. + */ static void do_mesh_box_select__doSelectEdge_pass1( void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { @@ -3181,11 +3209,16 @@ static bool do_mesh_box_select(ViewContext *vc, const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_NEAR | (use_zbuf ? 0 : V3D_PROJ_TEST_CLIP_BB); + /* Fully inside. */ mesh_foreachScreenEdge_clip_bb_segment( vc, do_mesh_box_select__doSelectEdge_pass0, &cb_data, clip_flag); if (data.is_done == false) { - mesh_foreachScreenEdge_clip_bb_segment( - vc, do_mesh_box_select__doSelectEdge_pass1, &cb_data, clip_flag); + /* Fall back to partially inside. + * Clip content to account for edges partially behind the view. */ + mesh_foreachScreenEdge_clip_bb_segment(vc, + do_mesh_box_select__doSelectEdge_pass1, + &cb_data, + clip_flag | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT); } } @@ -3571,7 +3604,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) } break; default: - BLI_assert(!"box select on incorrect object type"); + BLI_assert_msg(0, "box select on incorrect object type"); break; } changed_multi |= changed; @@ -3725,6 +3758,9 @@ static bool mesh_circle_select(ViewContext *vc, if (SEL_OP_USE_PRE_DESELECT(sel_op)) { if (vc->em->bm->totvertsel) { EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); + vc->em->bm->totvertsel = 0; + vc->em->bm->totedgesel = 0; + vc->em->bm->totfacesel = 0; changed = true; } } @@ -3771,7 +3807,10 @@ static bool mesh_circle_select(ViewContext *vc, } else { mesh_foreachScreenEdge_clip_bb_segment( - vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + vc, + mesh_circle_doSelectEdge, + &data, + (V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT)); } } @@ -3790,7 +3829,8 @@ static bool mesh_circle_select(ViewContext *vc, changed |= data.is_changed; if (changed) { - EDBM_selectmode_flush(vc->em); + BM_mesh_select_mode_flush_ex( + vc->em->bm, vc->em->selectmode, BM_SELECT_LEN_FLUSH_RECALC_NOTHING); } return changed; } @@ -4016,47 +4056,48 @@ static void do_circle_select_pose__doSelectBone(void *userData, { CircleSelectUserData *data = userData; bArmature *arm = data->vc->obact->data; + if (!PBONE_SELECTABLE(arm, pchan->bone)) { + return; + } - if (PBONE_SELECTABLE(arm, pchan->bone)) { - bool is_point_done = false; - int points_proj_tot = 0; + bool is_point_done = false; + int points_proj_tot = 0; - /* project head location to screenspace */ - if (screen_co_a[0] != IS_CLIPPED) { - points_proj_tot++; - if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) { - is_point_done = true; - } + /* project head location to screenspace */ + if (screen_co_a[0] != IS_CLIPPED) { + points_proj_tot++; + if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) { + is_point_done = true; } + } - /* project tail location to screenspace */ - if (screen_co_b[0] != IS_CLIPPED) { - points_proj_tot++; - if (pchan_circle_doSelectJoint(data, pchan, screen_co_b)) { - is_point_done = true; - } + /* project tail location to screenspace */ + if (screen_co_b[0] != IS_CLIPPED) { + points_proj_tot++; + if (pchan_circle_doSelectJoint(data, pchan, screen_co_b)) { + is_point_done = true; } + } - /* check if the head and/or tail is in the circle - * - the call to check also does the selection already - */ + /* check if the head and/or tail is in the circle + * - the call to check also does the selection already + */ - /* only if the endpoints didn't get selected, deal with the middle of the bone too - * It works nicer to only do this if the head or tail are not in the circle, - * otherwise there is no way to circle select joints alone */ - if ((is_point_done == false) && (points_proj_tot == 2) && - edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) { - if (data->select) { - pchan->bone->flag |= BONE_SELECTED; - } - else { - pchan->bone->flag &= ~BONE_SELECTED; - } - data->is_changed = true; + /* only if the endpoints didn't get selected, deal with the middle of the bone too + * It works nicer to only do this if the head or tail are not in the circle, + * otherwise there is no way to circle select joints alone */ + if ((is_point_done == false) && (points_proj_tot == 2) && + edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) { + if (data->select) { + pchan->bone->flag |= BONE_SELECTED; } - - data->is_changed |= is_point_done; + else { + pchan->bone->flag &= ~BONE_SELECTED; + } + data->is_changed = true; } + + data->is_changed |= is_point_done; } static bool pose_circle_select(ViewContext *vc, const eSelectOp sel_op, @@ -4075,8 +4116,11 @@ static bool pose_circle_select(ViewContext *vc, ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ - pose_foreachScreenBone( - vc, do_circle_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + /* Treat bones as clipped segments (no joints). */ + pose_foreachScreenBone(vc, + do_circle_select_pose__doSelectBone, + &data, + V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT); if (data.is_changed) { ED_pose_bone_select_tag_update(vc->obact); @@ -4118,47 +4162,74 @@ static void do_circle_select_armature__doSelectBone(void *userData, const float screen_co_b[2]) { CircleSelectUserData *data = userData; - bArmature *arm = data->vc->obedit->data; + const bArmature *arm = data->vc->obedit->data; + if (!(data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone))) { + return; + } - if (data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone)) { - bool is_point_done = false; - int points_proj_tot = 0; + /* When true, ignore in the next pass. */ + ebone->temp.i = false; - /* project head location to screenspace */ - if (screen_co_a[0] != IS_CLIPPED) { - points_proj_tot++; - if (armature_circle_doSelectJoint(data, ebone, screen_co_a, true)) { - is_point_done = true; - } + bool is_point_done = false; + bool is_edge_done = false; + int points_proj_tot = 0; + + /* project head location to screenspace */ + if (screen_co_a[0] != IS_CLIPPED) { + points_proj_tot++; + if (armature_circle_doSelectJoint(data, ebone, screen_co_a, true)) { + is_point_done = true; } + } - /* project tail location to screenspace */ - if (screen_co_b[0] != IS_CLIPPED) { - points_proj_tot++; - if (armature_circle_doSelectJoint(data, ebone, screen_co_b, false)) { - is_point_done = true; - } + /* project tail location to screenspace */ + if (screen_co_b[0] != IS_CLIPPED) { + points_proj_tot++; + if (armature_circle_doSelectJoint(data, ebone, screen_co_b, false)) { + is_point_done = true; } + } - /* check if the head and/or tail is in the circle - * - the call to check also does the selection already - */ + /* check if the head and/or tail is in the circle + * - the call to check also does the selection already + */ - /* only if the endpoints didn't get selected, deal with the middle of the bone too - * It works nicer to only do this if the head or tail are not in the circle, - * otherwise there is no way to circle select joints alone */ - if ((is_point_done == false) && (points_proj_tot == 2) && - edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) { - if (data->select) { - ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - else { - ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - data->is_changed = true; - } + /* only if the endpoints didn't get selected, deal with the middle of the bone too + * It works nicer to only do this if the head or tail are not in the circle, + * otherwise there is no way to circle select joints alone */ + if ((is_point_done == false) && (points_proj_tot == 2) && + edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) { + SET_FLAG_FROM_TEST(ebone->flag, data->select, BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + is_edge_done = true; + data->is_changed = true; + } + + if (is_point_done || is_edge_done) { + ebone->temp.i = true; + } + + data->is_changed |= is_point_done; +} +static void do_circle_select_armature__doSelectBone_clip_content(void *userData, + struct EditBone *ebone, + const float screen_co_a[2], + const float screen_co_b[2]) +{ + CircleSelectUserData *data = userData; + bArmature *arm = data->vc->obedit->data; - data->is_changed |= is_point_done; + if (!(data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone))) { + return; + } + + /* Set in the first pass, needed so circle select prioritizes joints. */ + if (ebone->temp.i == true) { + return; + } + + if (edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) { + SET_FLAG_FROM_TEST(ebone->flag, data->select, BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + data->is_changed = true; } } static bool armature_circle_select(ViewContext *vc, @@ -4179,9 +4250,18 @@ static bool armature_circle_select(ViewContext *vc, ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + /* Operate on fully visible (non-clipped) points. */ armature_foreachScreenBone( vc, do_circle_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + /* Operate on bones as segments clipped to the viewport bounds + * (needed to handle bones with both points outside the view). + * A separate pass is needed since clipped coordinates can't be used for selecting joints. */ + armature_foreachScreenBone(vc, + do_circle_select_armature__doSelectBone_clip_content, + &data, + V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT); + if (data.is_changed) { ED_armature_edit_sync_selection(arm->edbo); ED_armature_edit_validate_active(arm); @@ -4362,7 +4442,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) FOREACH_OBJECT_IN_MODE_END; } else if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT)) { - if (PE_circle_select(C, sel_op, mval, (float)radius)) { + if (PE_circle_select(C, wm_userdata, sel_op, mval, (float)radius)) { return OPERATOR_FINISHED; } return OPERATOR_CANCELLED; diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 72c62321e88..4482e5897ca 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -155,7 +155,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) /* Get location of grid point in pose space. */ BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec); - /* adjust location on the original pchan*/ + /* Adjust location on the original pchan. */ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name); if ((pchan->protectflag & OB_LOCK_LOCX) == 0) { pchan->loc[0] = vec[0]; @@ -511,47 +511,47 @@ static int snap_selected_to_location(bContext *C, for (int ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; + if (ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) { + continue; + } - if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) { - - float cursor_parent[3]; /* parent-relative */ - - if (use_offset) { - add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); - } - else { - copy_v3_v3(cursor_parent, snap_target_global); - } + float cursor_parent[3]; /* parent-relative */ - sub_v3_v3(cursor_parent, ob->obmat[3]); + if (use_offset) { + add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); + } + else { + copy_v3_v3(cursor_parent, snap_target_global); + } - if (ob->parent) { - float originmat[3][3], parentmat[4][4]; - /* Use the evaluated object here because sometimes - * `ob->parent->runtime.curve_cache` is required. */ - BKE_scene_graph_evaluated_ensure(depsgraph, bmain); - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + sub_v3_v3(cursor_parent, ob->obmat[3]); - BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat); - mul_m3_m4m4(originmat, parentmat, ob->parentinv); - invert_m3_m3(imat, originmat); - mul_m3_v3(imat, cursor_parent); - } - if ((ob->protectflag & OB_LOCK_LOCX) == 0) { - ob->loc[0] += cursor_parent[0]; - } - if ((ob->protectflag & OB_LOCK_LOCY) == 0) { - ob->loc[1] += cursor_parent[1]; - } - if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { - ob->loc[2] += cursor_parent[2]; - } + if (ob->parent) { + float originmat[3][3], parentmat[4][4]; + /* Use the evaluated object here because sometimes + * `ob->parent->runtime.curve_cache` is required. */ + BKE_scene_graph_evaluated_ensure(depsgraph, bmain); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + + BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat); + mul_m3_m4m4(originmat, parentmat, ob->parentinv); + invert_m3_m3(imat, originmat); + mul_m3_v3(imat, cursor_parent); + } + if ((ob->protectflag & OB_LOCK_LOCX) == 0) { + ob->loc[0] += cursor_parent[0]; + } + if ((ob->protectflag & OB_LOCK_LOCY) == 0) { + ob->loc[1] += cursor_parent[1]; + } + if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { + ob->loc[2] += cursor_parent[2]; + } - /* auto-keyframing */ - ED_autokeyframe_object(C, scene, ob, ks); + /* auto-keyframing */ + ED_autokeyframe_object(C, scene, ob, ks); - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); - } + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); } if (objects) { @@ -895,7 +895,7 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot) /** * Calculates the center position of the active object in global space. * - * Note: this could be exported to be a generic function. + * NOTE: this could be exported to be a generic function. * see: #calculateCenterActive */ static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3]) diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index f96c17d7cff..8bcc05c1e55 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -260,7 +260,7 @@ bool ED_view3d_context_activate(bContext *C) return false; } - /* bad context switch .. */ + /* Bad context switch. */ CTX_wm_area_set(C, area); CTX_wm_region_set(C, region); @@ -299,8 +299,8 @@ void ED_view3d_clipping_calc( float xs = (ELEM(val, 0, 3)) ? rect->xmin : rect->xmax; float ys = (ELEM(val, 0, 1)) ? rect->ymin : rect->ymax; - ED_view3d_unproject(region, xs, ys, 0.0, bb->vec[val]); - ED_view3d_unproject(region, xs, ys, 1.0, bb->vec[4 + val]); + ED_view3d_unproject_v3(region, xs, ys, 0.0, bb->vec[val]); + ED_view3d_unproject_v3(region, xs, ys, 1.0, bb->vec[4 + val]); } /* optionally transform to object space */ @@ -530,7 +530,7 @@ void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph, } /** * Action to take when rotating the view, - * handle auto-persp and logic for switching out of views. + * handle auto-perspective and logic for switching out of views. * * shared with NDOF. */ @@ -1017,7 +1017,7 @@ static float view_autodist_depth_margin(ARegion *region, const int mval[2], int } ViewDepths depth_temp = {0}; - view3d_update_depths_rect(region, &depth_temp, &rect); + view3d_depths_rect_create(region, &rect, &depth_temp); float depth_close = view3d_depth_near(&depth_temp); MEM_SAFE_FREE(depth_temp.depths); return depth_close; @@ -1044,7 +1044,7 @@ bool ED_view3d_autodist(Depsgraph *depsgraph, bool depth_ok = false; /* Get Z Depths, needed for perspective, nice for ortho */ - ED_view3d_depth_override(depsgraph, region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, false); + ED_view3d_depth_override(depsgraph, region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, NULL); /* Attempt with low margin's first */ int i = 0; @@ -1057,7 +1057,7 @@ bool ED_view3d_autodist(Depsgraph *depsgraph, float centx = (float)mval[0] + 0.5f; float centy = (float)mval[1] + 0.5f; - if (ED_view3d_unproject(region, centx, centy, depth_close, mouse_worldloc)) { + if (ED_view3d_unproject_v3(region, centx, centy, depth_close, mouse_worldloc)) { return true; } } @@ -1091,7 +1091,7 @@ bool ED_view3d_autodist_simple(ARegion *region, float centx = (float)mval[0] + 0.5f; float centy = (float)mval[1] + 0.5f; - return ED_view3d_unproject(region, centx, centy, depth, mouse_worldloc); + return ED_view3d_unproject_v3(region, centx, centy, depth, mouse_worldloc); } bool ED_view3d_autodist_depth(ARegion *region, const int mval[2], int margin, float *depth) @@ -1694,20 +1694,18 @@ bool ED_view3d_depth_read_cached(const ViewDepths *vd, return false; } -bool ED_view3d_depth_read_cached_normal(const ViewContext *vc, +bool ED_view3d_depth_read_cached_normal(const ARegion *region, + const ViewDepths *depths, const int mval[2], float r_normal[3]) { - /* Note: we could support passing in a radius. + /* NOTE: we could support passing in a radius. * For now just read 9 pixels. */ /* pixels surrounding */ bool depths_valid[9] = {false}; float coords[9][3] = {{0}}; - ARegion *region = vc->region; - const ViewDepths *depths = vc->rv3d->depths; - for (int x = 0, i = 0; x < 2; x++) { for (int y = 0; y < 2; y++) { const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)}; @@ -1716,7 +1714,7 @@ bool ED_view3d_depth_read_cached_normal(const ViewContext *vc, ED_view3d_depth_read_cached(depths, mval_ofs, 0, &depth_fl); const double depth = (double)depth_fl; if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { - if (ED_view3d_depth_unproject(region, mval_ofs, depth, coords[i])) { + if (ED_view3d_depth_unproject_v3(region, mval_ofs, depth, coords[i])) { depths_valid[i] = true; } } @@ -1751,21 +1749,14 @@ bool ED_view3d_depth_read_cached_normal(const ViewContext *vc, return false; } -bool ED_view3d_depth_unproject(const ARegion *region, - const int mval[2], - const double depth, - float r_location_world[3]) +bool ED_view3d_depth_unproject_v3(const ARegion *region, + const int mval[2], + const double depth, + float r_location_world[3]) { float centx = (float)mval[0] + 0.5f; float centy = (float)mval[1] + 0.5f; - return ED_view3d_unproject(region, centx, centy, depth, r_location_world); -} - -void ED_view3d_depth_tag_update(RegionView3D *rv3d) -{ - if (rv3d->depths) { - rv3d->depths->damaged = true; - } + return ED_view3d_unproject_v3(region, centx, centy, depth, r_location_world); } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 21cb8560e9b..86a610f8dd9 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -85,7 +85,7 @@ struct SmoothView3DState { }; struct SmoothView3DStore { - /* source*/ + /* Source. */ struct SmoothView3DState src; /* source */ struct SmoothView3DState dst; /* destination */ struct SmoothView3DState org; /* original */ @@ -235,7 +235,7 @@ void ED_view3d_smooth_view_ex( /* grid draw as floor */ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) { /* use existing if exists, means multiple calls to smooth view - * wont lose the original 'view' setting */ + * won't lose the original 'view' setting */ rv3d->view = RV3D_VIEW_USER; } @@ -244,7 +244,7 @@ void ED_view3d_smooth_view_ex( /* if this is view rotation only * we can decrease the time allowed by * the angle between quats - * this means small rotations wont lag */ + * this means small rotations won't lag */ if (sview->quat && !sview->ofs && !sview->dist) { /* scale the time allowed by the rotation */ /* 180deg == 1.0 */ @@ -392,7 +392,7 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *region, b view3d_boxview_copy(CTX_wm_area(C), region); } - /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636, + /* 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 smooth-view finishes. @@ -1261,7 +1261,7 @@ static bool view3d_localview_init(const Depsgraph *depsgraph, if (local_view_bit == 0) { /* TODO(dfelinto): We can kick one of the other 3D views out of local view - * specially if it is not being used. */ + * specially if it is not being used. */ BKE_report(reports, RPT_ERROR, "No more than 16 local views"); ok = false; } @@ -1393,6 +1393,7 @@ static void view3d_localview_exit(const Depsgraph *depsgraph, MEM_freeN(v3d->localvd); v3d->localvd = NULL; + MEM_SAFE_FREE(v3d->runtime.local_stats); LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->regiontype == RGN_TYPE_WINDOW) { @@ -1516,7 +1517,7 @@ static int localview_remove_from_exec(bContext *C, wmOperator *op) } if (changed) { - DEG_on_visible_update(bmain, false); + DEG_tag_on_visible_update(bmain, false); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); @@ -1564,7 +1565,7 @@ static uint free_localcollection_bit(Main *bmain, ushort local_collections_uuid, ushort local_view_bits = 0; - /* Check all areas: which localviews are in use? */ + /* Check all areas: which local-views are in use? */ for (screen = bmain->screens.first; screen; screen = screen->id.next) { for (area = screen->areabase.first; area; area = area->next) { SpaceLink *sl = area->spacedata.first; diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index b0bc5c6abda..ad0a330f0f4 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -102,6 +102,7 @@ set(SRC transform_orientations.c transform_snap.c transform_snap_object.c + transform_snap_sequencer.c transform.h transform_constraints.h diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index ba8e5c1e2c6..d34cc6f424f 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -536,7 +536,7 @@ static void viewRedrawPost(bContext *C, TransInfo *t) WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } - /* XXX temp, first hack to get auto-render in compositor work (ton) */ + /* XXX(ton): temp, first hack to get auto-render in compositor work. */ WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C)); } @@ -650,7 +650,7 @@ static bool transform_modal_item_poll(const wmOperator *op, int value) return true; } -/* called in transform_ops.c, on each regeneration of keymaps */ +/* Called in transform_ops.c, on each regeneration of key-maps. */ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) { static const EnumPropertyItem modal_items[] = { @@ -724,81 +724,92 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) static bool transform_event_modal_constraint(TransInfo *t, short modal_type) { - if (!(t->flag & T_NO_CONSTRAINT)) { - if (t->flag & T_2D_EDIT && ELEM(modal_type, TFM_MODAL_AXIS_Z, TFM_MODAL_PLANE_Z)) { + if (t->flag & T_NO_CONSTRAINT) { + return false; + } + + if (t->flag & T_2D_EDIT && ELEM(modal_type, TFM_MODAL_AXIS_Z, TFM_MODAL_PLANE_Z)) { + return false; + } + + int constraint_curr = -1; + + if (t->modifiers & (MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE)) { + t->modifiers &= ~(MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE); + + /* Avoid changing orientation in this case. */ + constraint_curr = -2; + } + else if (t->con.mode & CON_APPLY) { + constraint_curr = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2); + } + + int constraint_new; + const char *msg_2d = "", *msg_3d = ""; + + /* Initialize */ + switch (modal_type) { + case TFM_MODAL_AXIS_X: + msg_2d = TIP_("along X"); + msg_3d = TIP_("along %s X"); + constraint_new = CON_AXIS0; + break; + case TFM_MODAL_AXIS_Y: + msg_2d = TIP_("along Y"); + msg_3d = TIP_("along %s Y"); + constraint_new = CON_AXIS1; + break; + case TFM_MODAL_AXIS_Z: + msg_2d = TIP_("along Z"); + msg_3d = TIP_("along %s Z"); + constraint_new = CON_AXIS2; + break; + case TFM_MODAL_PLANE_X: + msg_3d = TIP_("locking %s X"); + constraint_new = CON_AXIS1 | CON_AXIS2; + break; + case TFM_MODAL_PLANE_Y: + msg_3d = TIP_("locking %s Y"); + constraint_new = CON_AXIS0 | CON_AXIS2; + break; + case TFM_MODAL_PLANE_Z: + msg_3d = TIP_("locking %s Z"); + constraint_new = CON_AXIS0 | CON_AXIS1; + break; + default: + /* Invalid key */ return false; - } - int constraint_curr = (t->con.mode & CON_APPLY) ? - t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2) : - -1; - int constraint_new; - const char *msg_2d = "", *msg_3d = ""; + } - /* Initialize */ - switch (modal_type) { - case TFM_MODAL_AXIS_X: - msg_2d = TIP_("along X"); - msg_3d = TIP_("along %s X"); - constraint_new = CON_AXIS0; - break; - case TFM_MODAL_AXIS_Y: - msg_2d = TIP_("along Y"); - msg_3d = TIP_("along %s Y"); - constraint_new = CON_AXIS1; - break; - case TFM_MODAL_AXIS_Z: - msg_2d = TIP_("along Z"); - msg_3d = TIP_("along %s Z"); - constraint_new = CON_AXIS2; - break; - case TFM_MODAL_PLANE_X: - msg_3d = TIP_("locking %s X"); - constraint_new = CON_AXIS1 | CON_AXIS2; - break; - case TFM_MODAL_PLANE_Y: - msg_3d = TIP_("locking %s Y"); - constraint_new = CON_AXIS0 | CON_AXIS2; - break; - case TFM_MODAL_PLANE_Z: - msg_3d = TIP_("locking %s Z"); - constraint_new = CON_AXIS0 | CON_AXIS1; - break; - default: - /* Invalid key */ - return false; + if (t->flag & T_2D_EDIT) { + BLI_assert(modal_type < TFM_MODAL_PLANE_X); + if (constraint_new == CON_AXIS2) { + return false; } - - if (t->flag & T_2D_EDIT) { - BLI_assert(modal_type < TFM_MODAL_PLANE_X); - if (constraint_new == CON_AXIS2) { - return false; - } - if (constraint_curr == constraint_new) { - stopConstraint(t); - } - else { - setUserConstraint(t, constraint_new, msg_2d); - } + if (constraint_curr == constraint_new) { + stopConstraint(t); } else { - short orient_index = 1; - if (t->orient_curr == O_DEFAULT || ELEM(constraint_curr, -1, constraint_new)) { - /* Successive presses on existing axis, cycle orientation modes. */ - orient_index = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient)); - } + setUserConstraint(t, constraint_new, msg_2d); + } + } + else { + short orient_index = 1; + if (t->orient_curr == O_DEFAULT || ELEM(constraint_curr, -1, constraint_new)) { + /* Successive presses on existing axis, cycle orientation modes. */ + orient_index = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient)); + } - transform_orientations_current_set(t, orient_index); - if (orient_index == 0) { - stopConstraint(t); - } - else { - setUserConstraint(t, constraint_new, msg_3d); - } + transform_orientations_current_set(t, orient_index); + if (orient_index == 0) { + stopConstraint(t); + } + else { + setUserConstraint(t, constraint_new, msg_3d); } - t->redraw |= TREDRAW_HARD; - return true; } - return false; + t->redraw |= TREDRAW_HARD; + return true; } int transformEvent(TransInfo *t, const wmEvent *event) @@ -814,7 +825,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } else if (event->type == MOUSEMOVE) { - if (t->modifiers & (MOD_CONSTRAINT_SELECT | MOD_CONSTRAINT_PLANE)) { + if (t->modifiers & (MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE)) { t->con.mode |= CON_SELECT; } @@ -1062,10 +1073,10 @@ int transformEvent(TransInfo *t, const wmEvent *event) t->state = TRANS_CONFIRM; } else if ((t->flag & T_NO_CONSTRAINT) == 0) { - if (t->modifiers & (MOD_CONSTRAINT_SELECT | MOD_CONSTRAINT_PLANE)) { + if (t->modifiers & (MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE)) { /* Confirm. */ postSelectConstraint(t); - t->modifiers &= ~(MOD_CONSTRAINT_SELECT | MOD_CONSTRAINT_PLANE); + t->modifiers &= ~(MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE); } else { if (t->options & CTX_CAMERA) { @@ -1079,8 +1090,9 @@ int transformEvent(TransInfo *t, const wmEvent *event) } } else { - t->modifiers |= (event->val == TFM_MODAL_AUTOCONSTRAINT) ? MOD_CONSTRAINT_SELECT : - MOD_CONSTRAINT_PLANE; + t->modifiers |= (event->val == TFM_MODAL_AUTOCONSTRAINT) ? + MOD_CONSTRAINT_SELECT_AXIS : + MOD_CONSTRAINT_SELECT_PLANE; if (t->con.mode & CON_APPLY) { stopConstraint(t); } @@ -1685,31 +1697,11 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->draw_handle_cursor = WM_paint_cursor_activate( SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } - else if (t->spacetype == SPACE_IMAGE) { - t->draw_handle_view = ED_region_draw_cb_activate( - t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate( - SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); - } - else if (t->spacetype == SPACE_CLIP) { - t->draw_handle_view = ED_region_draw_cb_activate( - t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate( - SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); - } - else if (t->spacetype == SPACE_NODE) { - t->draw_handle_view = ED_region_draw_cb_activate( - t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate( - SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); - } - else if (t->spacetype == SPACE_GRAPH) { + else if (t->spacetype == SPACE_SEQ) { t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate( - SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } - else if (t->spacetype == SPACE_ACTION) { + else if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP, SPACE_NODE, SPACE_GRAPH, SPACE_ACTION)) { t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); t->draw_handle_cursor = WM_paint_cursor_activate( @@ -1945,7 +1937,7 @@ int transformEnd(bContext *C, TransInfo *t) return exit_code; } -/* TODO, move to: transform_query.c */ +/* TODO: move to: `transform_query.c`. */ bool checkUseAxisMatrix(TransInfo *t) { /* currently only checks for editmode */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index a10a53b2983..1a61a594f37 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -46,6 +46,7 @@ * \{ */ struct ARegion; +struct BMPartialUpdate; struct Depsgraph; struct NumInput; struct Object; @@ -148,15 +149,18 @@ typedef enum { T_AUTOMERGE = 1 << 20, /** Runs auto-merge & splits. */ T_AUTOSPLIT = 1 << 21, + + /** No cursor wrapping on region bounds */ + T_NO_CURSOR_WRAP = 1 << 23, } eTFlag; /** #TransInfo.modifiers */ typedef enum { - MOD_CONSTRAINT_SELECT = 1 << 0, + MOD_CONSTRAINT_SELECT_AXIS = 1 << 0, MOD_PRECISION = 1 << 1, MOD_SNAP = 1 << 2, MOD_SNAP_INVERT = 1 << 3, - MOD_CONSTRAINT_PLANE = 1 << 4, + MOD_CONSTRAINT_SELECT_PLANE = 1 << 4, } eTModifier; /** #TransSnap.status */ @@ -331,7 +335,10 @@ typedef struct TransSnap { /** * Re-usable snap context data. */ - struct SnapObjectContext *object_context; + union { + struct SnapObjectContext *object_context; + struct TransSeqSnapData *seq_context; + }; } TransSnap; typedef struct TransCon { @@ -346,28 +353,28 @@ typedef struct TransCon { eTConstraint mode; void (*drawExtra)(struct TransInfo *t); - /* Note: if 'tc' is NULL, 'td' must also be NULL. + /* NOTE: if 'tc' is NULL, 'td' must also be NULL. * For constraints that needs to draw differently from the other * uses this instead of the generic draw function. */ /** Apply function pointer for linear vectorial transformation * The last three parameters are pointers to the in/out/printable vectors. */ - void (*applyVec)(struct TransInfo *t, - struct TransDataContainer *tc, + void (*applyVec)(const struct TransInfo *t, + const struct TransDataContainer *tc, struct TransData *td, const float in[3], - float out[3]); + float r_out[3]); /** Apply function pointer for size transformation. */ - void (*applySize)(struct TransInfo *t, - struct TransDataContainer *tc, + void (*applySize)(const struct TransInfo *t, + const struct TransDataContainer *tc, struct TransData *td, - float smat[3][3]); + float r_smat[3][3]); /** Apply function pointer for rotation transformation */ - void (*applyRot)(struct TransInfo *t, - struct TransDataContainer *tc, + void (*applyRot)(const struct TransInfo *t, + const struct TransDataContainer *tc, struct TransData *td, - float vec[3], - float *angle); + float r_axis[3], + float *r_angle); } TransCon; typedef struct MouseInput { @@ -419,7 +426,7 @@ typedef struct TransCenterData { * (typically in transform_conversion.c). */ typedef struct TransCustomDataContainer { - /** Owned by the mode (grab, scale, bend... ).*/ + /** Owned by the mode (grab, scale, bend... ). */ union { TransCustomData mode, first_elem; }; @@ -430,14 +437,14 @@ typedef struct TransCustomDataContainer { /** * Container for Transform Data * - * Used to implement multi-object modes, so each object can have it's + * Used to implement multi-object modes, so each object can have its * own data array as well as object matrix, local center etc. * * Anything that can't be shared between all objects * and doesn't make sense to store for every vertex (in the #TransDataContainer.data). * * \note at some point this could be used to store non object containers - * although this only makes sense if each container has it's own matrices, + * although this only makes sense if each container has its own matrices, * otherwise all elements may as well be stored in one array (#TransDataContainer.data), * as is already done for curve-objects, f-curves. etc. */ @@ -795,7 +802,7 @@ struct Object *transform_object_deform_pose_armature_get(const TransInfo *t, str void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data); -/* TODO. transform_query.c */ +/* TODO: `transform_query.c`. */ bool checkUseAxisMatrix(TransInfo *t); #define TRANSFORM_SNAP_MAX_PX 100.0f diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 615467932a7..7135395ee2d 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -97,7 +97,7 @@ static void view_vector_calc(const TransInfo *t, const float focus[3], float r_v /* ************************** CONSTRAINTS ************************* */ #define CONSTRAIN_EPSILON 0.0001f -static void constraint_plane_calc(TransInfo *t, float r_plane[4]) +static void constraint_plane_calc(const TransInfo *t, float r_plane[4]) { const float *constraint_vector[2]; int n = 0; @@ -391,8 +391,11 @@ static void planeProjection(const TransInfo *t, const float in[3], float out[3]) * 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]) +static void applyAxisConstraintVec(const TransInfo *t, + const TransDataContainer *UNUSED(tc), + TransData *td, + const float in[3], + float out[3]) { copy_v3_v3(out, in); if (!td && t->con.mode & CON_APPLY) { @@ -472,8 +475,11 @@ static void applyAxisConstraintVec( * * 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]) +static void applyObjectConstraintVec(const TransInfo *t, + const TransDataContainer *tc, + TransData *td, + const float in[3], + float out[3]) { if (!td) { applyAxisConstraintVec(t, tc, td, in, out); @@ -494,36 +500,36 @@ static void applyObjectConstraintVec( /** * Generic callback for constant spatial constraints applied to resize motion. */ -static void applyAxisConstraintSize(TransInfo *t, - TransDataContainer *UNUSED(tc), +static void applyAxisConstraintSize(const TransInfo *t, + const TransDataContainer *UNUSED(tc), TransData *td, - float smat[3][3]) + float r_smat[3][3]) { if (!td && t->con.mode & CON_APPLY) { float tmat[3][3]; if (!(t->con.mode & CON_AXIS0)) { - smat[0][0] = 1.0f; + r_smat[0][0] = 1.0f; } if (!(t->con.mode & CON_AXIS1)) { - smat[1][1] = 1.0f; + r_smat[1][1] = 1.0f; } if (!(t->con.mode & CON_AXIS2)) { - smat[2][2] = 1.0f; + r_smat[2][2] = 1.0f; } - mul_m3_m3m3(tmat, smat, t->spacemtx_inv); - mul_m3_m3m3(smat, t->spacemtx, tmat); + mul_m3_m3m3(tmat, r_smat, t->spacemtx_inv); + mul_m3_m3m3(r_smat, t->spacemtx, tmat); } } /** * Callback for object based spatial constraints applied to resize motion. */ -static void applyObjectConstraintSize(TransInfo *t, - TransDataContainer *tc, +static void applyObjectConstraintSize(const TransInfo *t, + const TransDataContainer *tc, TransData *td, - float smat[3][3]) + float r_smat[3][3]) { if (td && t->con.mode & CON_APPLY) { float tmat[3][3]; @@ -532,26 +538,26 @@ static void applyObjectConstraintSize(TransInfo *t, invert_m3_m3(imat, td->axismtx); if (!(t->con.mode & CON_AXIS0)) { - smat[0][0] = 1.0f; + r_smat[0][0] = 1.0f; } if (!(t->con.mode & CON_AXIS1)) { - smat[1][1] = 1.0f; + r_smat[1][1] = 1.0f; } if (!(t->con.mode & CON_AXIS2)) { - smat[2][2] = 1.0f; + r_smat[2][2] = 1.0f; } - mul_m3_m3m3(tmat, smat, imat); + mul_m3_m3m3(tmat, r_smat, imat); if (t->flag & T_EDIT) { - mul_m3_m3m3(smat, tc->mat3_unit, smat); + mul_m3_m3m3(r_smat, tc->mat3_unit, r_smat); } - mul_m3_m3m3(smat, td->axismtx, tmat); + mul_m3_m3m3(r_smat, td->axismtx, tmat); } } -static void constraints_rotation_impl(TransInfo *t, +static void constraints_rotation_impl(const TransInfo *t, const float axismtx[3][3], - float r_vec[3], + float r_axis[3], float *r_angle) { BLI_assert(t->con.mode & CON_APPLY); @@ -560,15 +566,15 @@ static void constraints_rotation_impl(TransInfo *t, switch (mode) { case CON_AXIS0: case (CON_AXIS1 | CON_AXIS2): - copy_v3_v3(r_vec, axismtx[0]); + copy_v3_v3(r_axis, axismtx[0]); break; case CON_AXIS1: case (CON_AXIS0 | CON_AXIS2): - copy_v3_v3(r_vec, axismtx[1]); + copy_v3_v3(r_axis, axismtx[1]); break; case CON_AXIS2: case (CON_AXIS0 | CON_AXIS1): - copy_v3_v3(r_vec, axismtx[2]); + copy_v3_v3(r_axis, axismtx[2]); break; } /* don't flip axis if asked to or if num input */ @@ -576,7 +582,7 @@ static void constraints_rotation_impl(TransInfo *t, !((mode & CON_NOFLIP) || hasNumInput(&t->num) || (t->flag & T_INPUT_IS_VALUES_FINAL))) { float view_vector[3]; view_vector_calc(t, t->center_global, view_vector); - if (dot_v3v3(r_vec, view_vector) > 0.0f) { + if (dot_v3v3(r_axis, view_vector) > 0.0f) { *r_angle = -(*r_angle); } } @@ -595,11 +601,14 @@ static void constraints_rotation_impl(TransInfo *t, * This insures that the rotation is always logically following the mouse. * (ie: not doing counterclockwise rotations when the mouse moves clockwise). */ -static void applyAxisConstraintRot( - TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, float vec[3], float *angle) +static void applyAxisConstraintRot(const TransInfo *t, + const TransDataContainer *UNUSED(tc), + TransData *td, + float r_axis[3], + float *r_angle) { if (!td && t->con.mode & CON_APPLY) { - constraints_rotation_impl(t, t->spacemtx, vec, angle); + constraints_rotation_impl(t, t->spacemtx, r_axis, r_angle); } } @@ -616,8 +625,11 @@ static void applyAxisConstraintRot( * This insures that the rotation is always logically following the mouse. * (ie: not doing counterclockwise rotations when the mouse moves clockwise). */ -static void applyObjectConstraintRot( - TransInfo *t, TransDataContainer *tc, TransData *td, float vec[3], float *angle) +static void applyObjectConstraintRot(const TransInfo *t, + const TransDataContainer *tc, + TransData *td, + float r_axis[3], + float *r_angle) { if (t->con.mode & CON_APPLY) { float tmp_axismtx[3][3]; @@ -638,7 +650,7 @@ static void applyObjectConstraintRot( axismtx = td->axismtx; } - constraints_rotation_impl(t, axismtx, vec, angle); + constraints_rotation_impl(t, axismtx, r_axis, r_angle); } } @@ -975,7 +987,6 @@ void initSelectConstraint(TransInfo *t) } setUserConstraint(t, CON_APPLY | CON_SELECT, "%s"); - setNearestAxis(t); } void selectConstraint(TransInfo *t) @@ -1062,7 +1073,7 @@ static void setNearestAxis3d(TransInfo *t) } if (len[0] <= len[1] && len[0] <= len[2]) { - if (t->modifiers & MOD_CONSTRAINT_PLANE) { + if (t->modifiers & MOD_CONSTRAINT_SELECT_PLANE) { t->con.mode |= (CON_AXIS1 | CON_AXIS2); BLI_snprintf(t->con.text, sizeof(t->con.text), TIP_(" locking %s X axis"), t->spacename); } @@ -1072,7 +1083,7 @@ static void setNearestAxis3d(TransInfo *t) } } else if (len[1] <= len[0] && len[1] <= len[2]) { - if (t->modifiers & MOD_CONSTRAINT_PLANE) { + if (t->modifiers & MOD_CONSTRAINT_SELECT_PLANE) { t->con.mode |= (CON_AXIS0 | CON_AXIS2); BLI_snprintf(t->con.text, sizeof(t->con.text), TIP_(" locking %s Y axis"), t->spacename); } @@ -1082,7 +1093,7 @@ static void setNearestAxis3d(TransInfo *t) } } else if (len[2] <= len[1] && len[2] <= len[0]) { - if (t->modifiers & MOD_CONSTRAINT_PLANE) { + if (t->modifiers & MOD_CONSTRAINT_SELECT_PLANE) { t->con.mode |= (CON_AXIS0 | CON_AXIS1); BLI_snprintf(t->con.text, sizeof(t->con.text), TIP_(" locking %s Z axis"), t->spacename); } @@ -1139,7 +1150,7 @@ int constraintModeToIndex(const TransInfo *t) } } -bool isLockConstraint(TransInfo *t) +bool isLockConstraint(const TransInfo *t) { int mode = t->con.mode; @@ -1165,7 +1176,7 @@ bool isLockConstraint(TransInfo *t) * 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 getConstraintSpaceDimension(const TransInfo *t) { int n = 0; diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h index ac62c057f9d..3632b352476 100644 --- a/source/blender/editors/transform/transform_constraints.h +++ b/source/blender/editors/transform/transform_constraints.h @@ -46,5 +46,5 @@ void postSelectConstraint(TransInfo *t); void setNearestAxis(TransInfo *t); int constraintModeToIndex(const TransInfo *t); char constraintModeToChar(const TransInfo *t); -bool isLockConstraint(TransInfo *t); -int getConstraintSpaceDimension(TransInfo *t); +bool isLockConstraint(const TransInfo *t); +int getConstraintSpaceDimension(const TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index b4175faacf4..00fd008151d 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -816,7 +816,7 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list) /* only consider constraint if it is enabled, and has influence on result */ if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) { /* (affirmative) returns for specific constraints here... */ - /* constraints that require this regardless */ + /* constraints that require this regardless. */ if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, @@ -849,10 +849,13 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list) /* Copy Transforms constraint only does this in the Before mode. */ bTransLikeConstraint *data = (bTransLikeConstraint *)con->data; - if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE) && + if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE, TRANSLIKE_MIX_BEFORE_FULL) && ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION)) { return true; } + if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE_SPLIT) && ELEM(t->mode, TFM_ROTATION)) { + return true; + } } else if (con->type == CONSTRAINT_TYPE_ACTION) { /* The Action constraint only does this in the Before mode. */ @@ -1698,9 +1701,11 @@ void recalcData(TransInfo *t) recalcData_mask_common(t); break; case TC_MESH_VERTS: - case TC_MESH_EDGES: recalcData_mesh(t); break; + case TC_MESH_EDGES: + recalcData_mesh_edge(t); + break; case TC_MESH_SKIN: recalcData_mesh_skin(t); break; diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index 11550ec8803..971c23b8c69 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -48,8 +48,8 @@ void clipUVData(TransInfo *t); void transform_convert_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); +void transform_convert_sequencer_channel_clamp(TransInfo *t, float r_val[2]); + /********************* intern **********************/ /* transform_convert.c */ @@ -169,6 +169,7 @@ void special_aftertrans_update__mesh(bContext *C, TransInfo *t); /* transform_convert_mesh_edge.c */ void createTransEdge(TransInfo *t); +void recalcData_mesh_edge(TransInfo *t); /* transform_convert_mesh_skin.c */ void createTransMeshSkin(TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert_action.c b/source/blender/editors/transform/transform_convert_action.c index 8204264e105..cfa14e21d0d 100644 --- a/source/blender/editors/transform/transform_convert_action.c +++ b/source/blender/editors/transform/transform_convert_action.c @@ -191,7 +191,7 @@ static TransData *ActionFCurveToTransData(TransData *td, td->flag |= TD_SELECTED; } - /*set flags to move handles as necessary*/ + /* Set flags to move handles as necessary. */ td->flag |= TD_MOVEHANDLE1 | TD_MOVEHANDLE2; td2d->h1 = bezt->vec[0]; td2d->h2 = bezt->vec[2]; @@ -210,12 +210,13 @@ static TransData *ActionFCurveToTransData(TransData *td, return td; } -/* This function advances the address to which td points to, so it must return +/** + * This function advances the address to which td points to, so it must return * the new address so that the next time new transform data is added, it doesn't - * overwrite the existing ones... i.e. td = GPLayerToTransData(td, ipo, ob, side, cfra); + * overwrite the existing ones: e.g. `td += GPLayerToTransData(td, ...);` * - * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data - * on the named side are used. + * \param side: is needed for the extend mode. 'B' = both sides, + * 'R'/'L' mean only data on the named side are used. */ static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, @@ -242,7 +243,7 @@ static int GPLayerToTransData(TransData *td, tfd->val = (float)gpf->framenum; tfd->sdata = &gpf->framenum; - /* advance td now */ + /* Advance `td` now. */ td++; tfd++; count++; @@ -339,7 +340,7 @@ void createTransActionData(bContext *C, TransInfo *t) t->frame_side = 'B'; } - /* loop 1: fully select ipo-keys and count how many BezTriples are selected */ + /* loop 1: fully select F-curve keys and count how many BezTriples are selected */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(&ac, ale); int adt_count = 0; @@ -554,7 +555,7 @@ void createTransActionData(bContext *C, TransInfo *t) /** \name Action Transform Flush * \{ */ -/* This function helps flush transdata written to tempdata into the gp-frames */ +/* This function helps flush transdata written to tempdata into the gp-frames. */ static void flushTransIntFrameActionData(TransInfo *t) { TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 7f24a0fa5f8..1f1b1f8db97 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -1268,9 +1268,6 @@ void recalcData_edit_armature(TransInfo *t) restoreBones(tc); } } - - /* Tag for redraw/invalidate overlay cache. */ - DEG_id_tag_update(&arm->id, ID_RECALC_SELECT); } } @@ -1452,9 +1449,9 @@ void recalcData_pose(TransInfo *t) /* TODO: autokeyframe calls need some setting to specify to add samples * (FPoints) instead of keyframes? */ if ((t->animtimer) && (t->context) && IS_AUTOKEY_ON(t->scene)) { - int targetless_ik = - (t->flag & - T_AUTOIK); /* XXX this currently doesn't work, since flags aren't set yet! */ + + /* XXX: this currently doesn't work, since flags aren't set yet! */ + int targetless_ik = (t->flag & T_AUTOIK); animrecord_check_state(t, ob); autokeyframe_pose(t->context, t->scene, ob, t->mode, targetless_ik); @@ -1613,10 +1610,10 @@ static short apply_targetless_ik(Object *ob) Bone *bone; float mat[4][4]; - /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */ - /* we put in channel the entire result of mat = (channel * constraint * IK) */ - /* pose_mat(b) = pose_mat(b-1) * offs_bone * mat */ - /* mat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone ) */ + /* `pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK` */ + /* We put in channel the entire result of: `mat = (channel * constraint * IK)` */ + /* `pose_mat(b) = pose_mat(b-1) * offs_bone * mat` */ + /* `mat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone)` */ parchan = chanlist[segcount - 1]; bone = parchan->bone; diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c index f294bbbf0aa..255af3feca2 100644 --- a/source/blender/editors/transform/transform_convert_curve.c +++ b/source/blender/editors/transform/transform_convert_curve.c @@ -277,8 +277,8 @@ void createTransCurveVerts(TransInfo *t) } td->ext = NULL; - /* TODO - make points scale */ - if (t->mode == TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ + /* TODO: make points scale. */ + if (t->mode == TFM_CURVE_SHRINKFATTEN /* `|| t->mode == TFM_RESIZE` */) { td->val = &(bezt->radius); td->ival = bezt->radius; } @@ -423,7 +423,7 @@ void createTransCurveVerts(TransInfo *t) calc_distanceCurveVerts(head, tail, cyclic); } - /* TODO - in the case of tilt and radius we can also avoid allocating the + /* TODO: in the case of tilt and radius we can also avoid allocating the * initTransDataCurveHandles but for now just don't change handle types */ if ((nu->type == CU_BEZIER) && ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) { @@ -449,11 +449,11 @@ void recalcData_curve(TransInfo *t) ListBase *nurbs = BKE_curve_editNurbs_get(cu); Nurb *nu = nurbs->first; - DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */ + DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY); if (t->state == TRANS_CANCEL) { while (nu) { - /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */ + /* Can't do testhandlesNurb here, it messes up the h1 and h2 flags */ BKE_nurb_handles_calc(nu); nu = nu->next; } diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c index 4932a5f8d23..f7b78b10868 100644 --- a/source/blender/editors/transform/transform_convert_gpencil.c +++ b/source/blender/editors/transform/transform_convert_gpencil.c @@ -176,7 +176,7 @@ static void createTransGPencil_curves(bContext *C, } } - /* If not multiedit out of loop. */ + /* If not multi-edit out of loop. */ if (!is_multiedit) { break; } @@ -382,7 +382,7 @@ static void createTransGPencil_curves(bContext *C, } } - /* If not multiedit out of loop. */ + /* If not multi-edit out of loop. */ if (!is_multiedit) { break; } @@ -470,7 +470,7 @@ static void createTransGPencil_strokes(bContext *C, } } } - /* If not multiedit out of loop. */ + /* If not multi-edit out of loop. */ if (!is_multiedit) { break; } @@ -674,7 +674,7 @@ static void createTransGPencil_strokes(bContext *C, } } } - /* if not multiedit out of loop */ + /* If not multi-edit out of loop. */ if (!is_multiedit) { break; } diff --git a/source/blender/editors/transform/transform_convert_graph.c b/source/blender/editors/transform/transform_convert_graph.c index d57f7fffe0b..111f81ff87b 100644 --- a/source/blender/editors/transform/transform_convert_graph.c +++ b/source/blender/editors/transform/transform_convert_graph.c @@ -939,8 +939,8 @@ static void remake_graph_transdata(TransInfo *t, ListBase *anim_data) if (fcu->bezt) { BeztMap *bezm; - /* adjust transform-data pointers */ - /* note, none of these functions use 'use_handle', it could be removed */ + /* Adjust transform-data pointers. */ + /* NOTE: none of these functions use 'use_handle', it could be removed. */ bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert); sort_time_beztmaps(bezm, fcu->totvert); beztmap_to_data(t, fcu, bezm, fcu->totvert); @@ -1082,7 +1082,7 @@ void special_aftertrans_update__graph(bContext *C, TransInfo *t) /* Make sure all F-Curves are set correctly, but not if transform was * canceled, since then curves were already restored to initial state. - * Note: if the refresh is really needed after cancel then some way + * NOTE: if the refresh is really needed after cancel then some way * has to be added to not update handle types (see bug 22289). */ if (!canceled) { diff --git a/source/blender/editors/transform/transform_convert_lattice.c b/source/blender/editors/transform/transform_convert_lattice.c index 20ac7dcb998..fbfce41d555 100644 --- a/source/blender/editors/transform/transform_convert_lattice.c +++ b/source/blender/editors/transform/transform_convert_lattice.c @@ -122,7 +122,7 @@ void recalcData_lattice(TransInfo *t) FOREACH_TRANS_DATA_CONTAINER (t, tc) { Lattice *la = tc->obedit->data; - DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */ + DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY); if (la->editlatt->latt->flag & LT_OUTSIDE) { outside_lattice(la->editlatt->latt); } diff --git a/source/blender/editors/transform/transform_convert_mask.c b/source/blender/editors/transform/transform_convert_mask.c index 45dc6df4fde..54df8270702 100644 --- a/source/blender/editors/transform/transform_convert_mask.c +++ b/source/blender/editors/transform/transform_convert_mask.c @@ -330,7 +330,7 @@ void createTransMaskingData(bContext *C, TransInfo *t) } } - /* note: in prop mode we need at least 1 selected */ + /* NOTE: in prop mode we need at least 1 selected. */ if (countsel == 0) { return; } diff --git a/source/blender/editors/transform/transform_convert_mball.c b/source/blender/editors/transform/transform_convert_mball.c index e47cf4edc4a..f38f3ccf421 100644 --- a/source/blender/editors/transform/transform_convert_mball.c +++ b/source/blender/editors/transform/transform_convert_mball.c @@ -142,7 +142,7 @@ void recalcData_mball(TransInfo *t) } FOREACH_TRANS_DATA_CONTAINER (t, tc) { if (tc->data_len) { - DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */ + DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY); } } } diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 8d942b1094e..383f9870714 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -27,6 +27,7 @@ #include "MEM_guardedalloc.h" #include "BLI_alloca.h" +#include "BLI_bitmap.h" #include "BLI_linklist_stack.h" #include "BLI_math.h" #include "BLI_memarena.h" @@ -52,6 +53,106 @@ /** \name Container TransCustomData Creation * \{ */ +static void tc_mesh_customdata_free_fn(struct TransInfo *t, + struct TransDataContainer *tc, + struct TransCustomData *custom_data); + +struct TransCustomDataLayer; +static void tc_mesh_customdatacorrect_free(struct TransCustomDataLayer *tcld); + +struct TransCustomData_PartialUpdate { + struct BMPartialUpdate *cache; + + /** The size of proportional editing used for #BMPartialUpdate. */ + float prop_size; + /** The size of proportional editing for the last update. */ + float prop_size_prev; +}; + +/** + * \note It's important to order from least to greatest (which updates more data), + * since the larger values are used when values change between updates + * (which can happen when rotation is enabled with snapping). + */ +enum ePartialType { + PARTIAL_NONE = -1, + /** + * Update only faces between tagged and non-tagged faces (affine transformations). + * Use when transforming is guaranteed not to change the relative locations of vertices. + * + * This has the advantage that selecting the entire mesh or only isolated elements, + * can skip normal/tessellation updates entirely, so it's worth using when possible. + */ + PARTIAL_TYPE_GROUP = 0, + /** + * Update for all tagged vertices (any kind of deformation). + * Use as a default since it can be used with any kind of deformation. + */ + PARTIAL_TYPE_ALL = 1, +}; + +#define PARTIAL_TYPE_MAX 2 + +/** + * Settings used for a single update, + * use for comparison with previous updates. + */ +struct PartialTypeState { + enum ePartialType for_looptri; + enum ePartialType for_normals; +}; + +struct TransCustomDataMesh { + struct TransCustomDataLayer *cd_layer_correct; + struct TransCustomData_PartialUpdate partial_update[PARTIAL_TYPE_MAX]; + struct PartialTypeState partial_update_state_prev; +}; + +static struct TransCustomDataMesh *tc_mesh_customdata_ensure(TransDataContainer *tc) +{ + struct TransCustomDataMesh *tcmd = tc->custom.type.data; + BLI_assert(tc->custom.type.data == NULL || + tc->custom.type.free_cb == tc_mesh_customdata_free_fn); + if (tc->custom.type.data == NULL) { + tc->custom.type.data = MEM_callocN(sizeof(struct TransCustomDataMesh), __func__); + tc->custom.type.free_cb = tc_mesh_customdata_free_fn; + tcmd = tc->custom.type.data; + tcmd->partial_update_state_prev.for_looptri = PARTIAL_NONE; + tcmd->partial_update_state_prev.for_normals = PARTIAL_NONE; + } + return tcmd; +} + +static void tc_mesh_customdata_free(struct TransCustomDataMesh *tcmd) +{ + if (tcmd->cd_layer_correct != NULL) { + tc_mesh_customdatacorrect_free(tcmd->cd_layer_correct); + } + + for (int i = 0; i < ARRAY_SIZE(tcmd->partial_update); i++) { + if (tcmd->partial_update[i].cache != NULL) { + BM_mesh_partial_destroy(tcmd->partial_update[i].cache); + } + } + + MEM_freeN(tcmd); +} + +static void tc_mesh_customdata_free_fn(struct TransInfo *UNUSED(t), + struct TransDataContainer *UNUSED(tc), + struct TransCustomData *custom_data) +{ + struct TransCustomDataMesh *tcmd = custom_data->data; + tc_mesh_customdata_free(tcmd); + custom_data->data = NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name CustomData TransCustomDataLayer Creation + * \{ */ + struct TransCustomDataMergeGroup { /** map {BMVert: TransCustomDataLayerVert} */ struct LinkNode **cd_loop_groups; @@ -83,33 +184,6 @@ struct TransCustomDataLayer { bool use_merge_group; }; -static void tc_mesh_customdatacorrect_free_fn(struct TransInfo *UNUSED(t), - struct TransDataContainer *UNUSED(tc), - struct TransCustomData *custom_data) -{ - struct TransCustomDataLayer *tcld = custom_data->data; - bmesh_edit_end(tcld->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); - - if (tcld->bm_origfaces) { - BM_mesh_free(tcld->bm_origfaces); - } - if (tcld->origfaces) { - BLI_ghash_free(tcld->origfaces, NULL, NULL); - } - if (tcld->merge_group.origverts) { - BLI_ghash_free(tcld->merge_group.origverts, NULL, NULL); - } - if (tcld->arena) { - BLI_memarena_free(tcld->arena); - } - if (tcld->merge_group.customdatalayer_map) { - MEM_freeN(tcld->merge_group.customdatalayer_map); - } - - MEM_freeN(tcld); - custom_data->data = NULL; -} - #define USE_FACE_SUBSTITUTE #ifdef USE_FACE_SUBSTITUTE # define FACE_SUBSTITUTE_INDEX INT_MIN @@ -292,8 +366,8 @@ static void tc_mesh_customdatacorrect_init_container_merge_group(TransDataContai tcld->arena, tcld->merge_group.data_len * sizeof(*tcld->merge_group.data)); } -static struct TransCustomDataLayer *tc_mesh_customdatacorrect_create(TransDataContainer *tc, - const bool use_merge_group) +static struct TransCustomDataLayer *tc_mesh_customdatacorrect_create_impl( + TransDataContainer *tc, const bool use_merge_group) { BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; @@ -341,18 +415,41 @@ static struct TransCustomDataLayer *tc_mesh_customdatacorrect_create(TransDataCo return tcld; } -static void tc_mesh_customdata_create(TransDataContainer *tc, const bool use_merge_group) +static void tc_mesh_customdatacorrect_create(TransDataContainer *tc, const bool use_merge_group) { struct TransCustomDataLayer *customdatacorrect; - customdatacorrect = tc_mesh_customdatacorrect_create(tc, use_merge_group); + customdatacorrect = tc_mesh_customdatacorrect_create_impl(tc, use_merge_group); if (!customdatacorrect) { return; } - BLI_assert(tc->custom.type.data == NULL); - tc->custom.type.data = customdatacorrect; - tc->custom.type.free_cb = tc_mesh_customdatacorrect_free_fn; + struct TransCustomDataMesh *tcmd = tc_mesh_customdata_ensure(tc); + BLI_assert(tcmd->cd_layer_correct == NULL); + tcmd->cd_layer_correct = customdatacorrect; +} + +static void tc_mesh_customdatacorrect_free(struct TransCustomDataLayer *tcld) +{ + bmesh_edit_end(tcld->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); + + if (tcld->bm_origfaces) { + BM_mesh_free(tcld->bm_origfaces); + } + if (tcld->origfaces) { + BLI_ghash_free(tcld->origfaces, NULL, NULL); + } + if (tcld->merge_group.origverts) { + BLI_ghash_free(tcld->merge_group.origverts, NULL, NULL); + } + if (tcld->arena) { + BLI_memarena_free(tcld->arena); + } + if (tcld->merge_group.customdatalayer_map) { + MEM_freeN(tcld->merge_group.customdatalayer_map); + } + + MEM_freeN(tcld); } void transform_convert_mesh_customdatacorrect_init(TransInfo *t) @@ -390,10 +487,14 @@ void transform_convert_mesh_customdatacorrect_init(TransInfo *t) FOREACH_TRANS_DATA_CONTAINER (t, tc) { if (tc->custom.type.data != NULL) { - tc_mesh_customdatacorrect_free_fn(t, tc, &tc->custom.type); + struct TransCustomDataMesh *tcmd = tc->custom.type.data; + if (tcmd && tcmd->cd_layer_correct) { + tc_mesh_customdatacorrect_free(tcmd->cd_layer_correct); + tcmd->cd_layer_correct = NULL; + } } - tc_mesh_customdata_create(tc, use_merge_group); + tc_mesh_customdatacorrect_create(tc, use_merge_group); } } @@ -555,10 +656,11 @@ static void tc_mesh_customdatacorrect_apply_vert(struct TransCustomDataLayer *tc static void tc_mesh_customdatacorrect_apply(TransDataContainer *tc, bool is_final) { - if (!tc->custom.type.data) { + struct TransCustomDataMesh *tcmd = tc->custom.type.data; + struct TransCustomDataLayer *tcld = tcmd ? tcmd->cd_layer_correct : NULL; + if (tcld == NULL) { return; } - struct TransCustomDataLayer *tcld = tc->custom.type.data; const bool use_merge_group = tcld->use_merge_group; struct TransCustomDataMergeGroup *merge_data = tcld->merge_group.data; @@ -590,7 +692,8 @@ static void tc_mesh_customdatacorrect_apply(TransDataContainer *tc, bool is_fina static void tc_mesh_customdatacorrect_restore(struct TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { - struct TransCustomDataLayer *tcld = tc->custom.type.data; + struct TransCustomDataMesh *tcmd = tc->custom.type.data; + struct TransCustomDataLayer *tcld = tcmd ? tcmd->cd_layer_correct : NULL; if (!tcld) { continue; } @@ -1234,7 +1337,7 @@ void transform_convert_mesh_crazyspace_detect(TransInfo *t, * correction with \a quats, relative to the coordinates after * the modifiers that support deform matrices \a defcos. */ -#if 0 /* TODO, fix crazy-space & extrude so it can be enabled for general use - campbell */ +#if 0 /* TODO(campbell): fix crazy-space & extrude so it can be enabled for general use. */ if ((totleft > 0) || (totleft == -1)) #else if (totleft > 0) @@ -1614,6 +1717,318 @@ void createTransEditVerts(TransInfo *t) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Recalc Mesh Data (Partial Update) + * \{ */ + +static BMPartialUpdate *tc_mesh_partial_ensure(TransInfo *t, + TransDataContainer *tc, + enum ePartialType partial_type) +{ + struct TransCustomDataMesh *tcmd = tc_mesh_customdata_ensure(tc); + + struct TransCustomData_PartialUpdate *pupdate = &tcmd->partial_update[partial_type]; + + if (pupdate->cache) { + + /* Recalculate partial update data when the proportional editing size changes. + * + * Note that decreasing the proportional editing size requires the existing + * partial data is used before recreating this partial data at the smaller size. + * Since excluding geometry from being transformed requires an update. + * + * Extra logic is needed to account for this situation. */ + + bool recalc; + if (pupdate->prop_size_prev < t->prop_size) { + /* Size increase, simply recalculate. */ + recalc = true; + } + else if (pupdate->prop_size_prev > t->prop_size) { + /* Size decreased, first use this partial data since reducing the size will transform + * geometry which needs recalculating. */ + pupdate->prop_size_prev = t->prop_size; + recalc = false; + } + else if (pupdate->prop_size != t->prop_size) { + BLI_assert(pupdate->prop_size > pupdate->prop_size_prev); + recalc = true; + } + else { + BLI_assert(t->prop_size == pupdate->prop_size_prev); + recalc = false; + } + + if (!recalc) { + return pupdate->cache; + } + + BM_mesh_partial_destroy(pupdate->cache); + pupdate->cache = NULL; + } + + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + + BM_mesh_elem_index_ensure(em->bm, BM_VERT); + + /* Only use `verts_group` or `verts_mask`. */ + int *verts_group = NULL; + int verts_group_count = 0; /* Number of non-zero elements in `verts_group`. */ + + BLI_bitmap *verts_mask = NULL; + int verts_mask_count = 0; /* Number of elements enabled in `verts_mask`. */ + + if ((partial_type == PARTIAL_TYPE_GROUP) && + ((t->flag & T_PROP_EDIT) || tc->use_mirror_axis_any)) { + verts_group = MEM_callocN(sizeof(*verts_group) * em->bm->totvert, __func__); + int i; + TransData *td; + for (i = 0, td = tc->data; i < tc->data_len; i++, td++) { + if (td->factor == 0.0f) { + continue; + } + const BMVert *v = (BMVert *)td->extra; + const int v_index = BM_elem_index_get(v); + BLI_assert(verts_group[v_index] == 0); + if (td->factor < 1.0f) { + /* Don't use grouping logic with the factor is under 1.0. */ + verts_group[v_index] = -1; + } + else { + BLI_assert(td->factor == 1.0f); + verts_group[v_index] = 1; + if (tc->use_mirror_axis_any) { + /* Use bits 2-4 for central alignment (don't overlap the first bit). */ + const int flag = td->flag & (TD_MIRROR_EDGE_X | TD_MIRROR_EDGE_Y | TD_MIRROR_EDGE_Z); + verts_group[v_index] |= (flag >> TD_MIRROR_EDGE_AXIS_SHIFT) << 1; + } + } + verts_mask_count += 1; + } + + TransDataMirror *td_mirror = tc->data_mirror; + for (i = 0; i < tc->data_mirror_len; i++, td_mirror++) { + BMVert *v_mirr = (BMVert *)POINTER_OFFSET(td_mirror->loc_src, -offsetof(BMVert, co)); + /* The equality check is to account for the case when topology mirror moves + * the vertex from it's original location to match it's symmetrical position, + * with proportional editing enabled. */ + const int v_mirr_index = BM_elem_index_get(v_mirr); + if (verts_group[v_mirr_index] == 0 && equals_v3v3(td_mirror->loc, td_mirror->iloc)) { + continue; + } + + BMVert *v_mirr_other = (BMVert *)td_mirror->extra; + /* This assert should never fail since there is no overlap + * between mirrored vertices and non-mirrored. */ + BLI_assert(verts_group[BM_elem_index_get(v_mirr_other)] == 0); + const int v_mirr_other_index = BM_elem_index_get(v_mirr_other); + + if (verts_group[v_mirr_index] == -1) { + verts_group[v_mirr_other_index] = -1; + } + else { + /* Use bits 5-8 for mirror (don't overlap previous bits). */ + const int flag = td_mirror->flag & (TD_MIRROR_X | TD_MIRROR_Y | TD_MIRROR_Z); + verts_group[v_mirr_other_index] |= (flag >> TD_MIRROR_EDGE_AXIS_SHIFT) << 4; + } + verts_mask_count += 1; + } + } + else { + /* See the body of the comments in the previous block for details. */ + verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); + int i; + TransData *td; + for (i = 0, td = tc->data; i < tc->data_len; i++, td++) { + if (td->factor == 0.0f) { + continue; + } + const BMVert *v = (BMVert *)td->extra; + const int v_index = BM_elem_index_get(v); + BLI_assert(!BLI_BITMAP_TEST(verts_mask, v_index)); + BLI_BITMAP_ENABLE(verts_mask, v_index); + verts_mask_count += 1; + } + + TransDataMirror *td_mirror = tc->data_mirror; + for (i = 0; i < tc->data_mirror_len; i++, td_mirror++) { + BMVert *v_mirr = (BMVert *)POINTER_OFFSET(td_mirror->loc_src, -offsetof(BMVert, co)); + if (!BLI_BITMAP_TEST(verts_mask, BM_elem_index_get(v_mirr)) && + equals_v3v3(td_mirror->loc, td_mirror->iloc)) { + continue; + } + + BMVert *v_mirr_other = (BMVert *)td_mirror->extra; + BLI_assert(!BLI_BITMAP_TEST(verts_mask, BM_elem_index_get(v_mirr_other))); + const int v_mirr_other_index = BM_elem_index_get(v_mirr_other); + BLI_BITMAP_ENABLE(verts_mask, v_mirr_other_index); + verts_mask_count += 1; + } + } + + switch (partial_type) { + case PARTIAL_TYPE_ALL: { + pupdate->cache = BM_mesh_partial_create_from_verts(em->bm, + &(BMPartialUpdate_Params){ + .do_tessellate = true, + .do_normals = true, + }, + verts_mask, + verts_mask_count); + break; + } + case PARTIAL_TYPE_GROUP: { + pupdate->cache = + (verts_group ? BM_mesh_partial_create_from_verts_group_multi(em->bm, + &(BMPartialUpdate_Params){ + .do_tessellate = true, + .do_normals = true, + }, + verts_group, + verts_group_count) : + BM_mesh_partial_create_from_verts_group_single(em->bm, + &(BMPartialUpdate_Params){ + .do_tessellate = true, + .do_normals = true, + }, + verts_mask, + verts_mask_count)); + break; + } + case PARTIAL_NONE: { + BLI_assert_unreachable(); + } + } + + if (verts_group) { + MEM_freeN(verts_group); + } + else { + MEM_freeN(verts_mask); + } + + pupdate->prop_size_prev = t->prop_size; + pupdate->prop_size = t->prop_size; + + return pupdate->cache; +} + +static void tc_mesh_partial_types_calc(TransInfo *t, struct PartialTypeState *r_partial_state) +{ + /* Calculate the kind of partial updates which can be performed. */ + enum ePartialType partial_for_normals = PARTIAL_NONE; + enum ePartialType partial_for_looptri = PARTIAL_NONE; + + /* Note that operations such as #TFM_CREASE are not handled here + * (if they were, leaving as #PARTIAL_NONE would be appropriate). */ + switch (t->mode) { + case TFM_TRANSLATION: { + partial_for_looptri = PARTIAL_TYPE_GROUP; + partial_for_normals = PARTIAL_TYPE_GROUP; + /* Translation can rotate when snapping to normal. */ + if (activeSnap(t) && usingSnappingNormal(t) && validSnappingNormal(t)) { + partial_for_normals = PARTIAL_TYPE_ALL; + } + break; + } + case TFM_ROTATION: { + partial_for_looptri = PARTIAL_TYPE_GROUP; + partial_for_normals = PARTIAL_TYPE_ALL; + break; + } + case TFM_RESIZE: { + partial_for_looptri = PARTIAL_TYPE_GROUP; + partial_for_normals = PARTIAL_TYPE_GROUP; + /* Non-uniform scale needs to recalculate all normals + * since their relative locations change. + * Uniform negative scale can keep normals as-is since the faces are flipped, + * normals remain unchanged. */ + if ((t->con.mode & CON_APPLY) || + (t->values_final[0] != t->values_final[1] || t->values_final[0] != t->values_final[2])) { + partial_for_normals = PARTIAL_TYPE_ALL; + } + break; + } + default: { + partial_for_looptri = PARTIAL_TYPE_ALL; + partial_for_normals = PARTIAL_TYPE_ALL; + break; + } + } + + /* With projection, transform isn't affine. */ + if (activeSnap_with_project(t)) { + if (partial_for_looptri == PARTIAL_TYPE_GROUP) { + partial_for_looptri = PARTIAL_TYPE_ALL; + } + if (partial_for_normals == PARTIAL_TYPE_GROUP) { + partial_for_normals = PARTIAL_TYPE_ALL; + } + } + + r_partial_state->for_looptri = partial_for_looptri; + r_partial_state->for_normals = partial_for_normals; +} + +static void tc_mesh_partial_update(TransInfo *t, + TransDataContainer *tc, + const struct PartialTypeState *partial_state) +{ + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + + struct TransCustomDataMesh *tcmd = tc_mesh_customdata_ensure(tc); + + const struct PartialTypeState *partial_state_prev = &tcmd->partial_update_state_prev; + + /* Promote the partial update types based on the previous state + * so the values that no longer modified are reset before being left as-is. + * Needed for translation which can toggle snap-to-normal during transform. */ + const enum ePartialType partial_for_looptri = MAX2(partial_state->for_looptri, + partial_state_prev->for_looptri); + const enum ePartialType partial_for_normals = MAX2(partial_state->for_normals, + partial_state_prev->for_normals); + + if ((partial_for_looptri == PARTIAL_TYPE_ALL) && (partial_for_normals == PARTIAL_TYPE_ALL) && + (em->bm->totvert == em->bm->totvertsel)) { + /* The additional cost of generating the partial connectivity data isn't justified + * when all data needs to be updated. + * + * While proportional editing can cause all geometry to need updating with a partial + * selection. It's impractical to calculate this ahead of time. Further, the down side of + * using partial updates when their not needed is negligible. */ + BKE_editmesh_looptri_and_normals_calc(em); + } + else { + if (partial_for_looptri != PARTIAL_NONE) { + BMPartialUpdate *bmpinfo = tc_mesh_partial_ensure(t, tc, partial_for_looptri); + BKE_editmesh_looptri_calc_with_partial_ex(em, + bmpinfo, + &(const struct BMeshCalcTessellation_Params){ + .face_normals = true, + }); + } + + if (partial_for_normals != PARTIAL_NONE) { + BMPartialUpdate *bmpinfo = tc_mesh_partial_ensure(t, tc, partial_for_normals); + /* While not a large difference, take advantage of existing normals where possible. */ + const bool face_normals = !((partial_for_looptri == PARTIAL_TYPE_ALL) || + ((partial_for_looptri == PARTIAL_TYPE_GROUP) && + (partial_for_normals == PARTIAL_TYPE_GROUP))); + BM_mesh_normals_update_with_partial_ex(em->bm, + bmpinfo, + &(const struct BMeshNormalsUpdate_Params){ + .face_normals = face_normals, + }); + } + } + + /* Store the previous requested (not the previous used), + * since the values used may have been promoted based on the previous types. */ + tcmd->partial_update_state_prev = *partial_state; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Recalc Mesh Data * \{ */ @@ -1652,6 +2067,27 @@ static void tc_mesh_transdata_mirror_apply(TransDataContainer *tc) } } +static bool tc_mesh_is_deform_only_update(TransInfo *t, TransDataContainer *tc) +{ + if (tc->custom.type.data && + ((struct TransCustomDataMesh *)tc->custom.type.data)->cd_layer_correct) { + return false; + } + + Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(t->depsgraph, (ID *)tc->obedit->data); + Mesh *mesh_eval_cage = me_eval->edit_mesh->mesh_eval_cage; + Mesh *mesh_eval_final = me_eval->edit_mesh->mesh_eval_final; + if (mesh_eval_cage && !mesh_eval_cage->runtime.is_original) { + return false; + } + if (mesh_eval_final && mesh_eval_final != mesh_eval_cage && + !mesh_eval_final->runtime.is_original) { + return false; + } + + return me_eval->runtime.deformed_only; +} + void recalcData_mesh(TransInfo *t) { bool is_canceling = t->state == TRANS_CANCEL; @@ -1675,11 +2111,16 @@ void recalcData_mesh(TransInfo *t) tc_mesh_customdatacorrect_restore(t); } + struct PartialTypeState partial_state; + tc_mesh_partial_types_calc(t, &partial_state); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { - DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */ - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - EDBM_mesh_normals_update(em); - BKE_editmesh_looptri_calc(em); + const bool is_deform_only = tc_mesh_is_deform_only_update(t, tc); + + DEG_id_tag_update(tc->obedit->data, + is_deform_only ? ID_RECALC_GEOMETRY_DEFORM : ID_RECALC_GEOMETRY); + + tc_mesh_partial_update(t, tc, &partial_state); } } /** \} */ diff --git a/source/blender/editors/transform/transform_convert_mesh_edge.c b/source/blender/editors/transform/transform_convert_mesh_edge.c index bb9296b4b90..2db3e259153 100644 --- a/source/blender/editors/transform/transform_convert_mesh_edge.c +++ b/source/blender/editors/transform/transform_convert_mesh_edge.c @@ -28,6 +28,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" @@ -123,4 +124,11 @@ void createTransEdge(TransInfo *t) } } +void recalcData_mesh_edge(TransInfo *t) +{ + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY); + } +} + /** \} */ diff --git a/source/blender/editors/transform/transform_convert_mesh_skin.c b/source/blender/editors/transform/transform_convert_mesh_skin.c index 68305c45280..69b44998980 100644 --- a/source/blender/editors/transform/transform_convert_mesh_skin.c +++ b/source/blender/editors/transform/transform_convert_mesh_skin.c @@ -298,10 +298,9 @@ void recalcData_mesh_skin(TransInfo *t) } FOREACH_TRANS_DATA_CONTAINER (t, tc) { - DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */ + DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY); BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - EDBM_mesh_normals_update(em); - BKE_editmesh_looptri_calc(em); + BKE_editmesh_looptri_and_normals_calc(em); } } /** \} */ diff --git a/source/blender/editors/transform/transform_convert_mesh_uv.c b/source/blender/editors/transform/transform_convert_mesh_uv.c index a5f90e9ac5f..61397b6ef4b 100644 --- a/source/blender/editors/transform/transform_convert_mesh_uv.c +++ b/source/blender/editors/transform/transform_convert_mesh_uv.c @@ -30,6 +30,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh_mapping.h" @@ -475,7 +476,7 @@ void recalcData_uv(TransInfo *t) FOREACH_TRANS_DATA_CONTAINER (t, tc) { if (tc->data_len) { - DEG_id_tag_update(tc->obedit->data, 0); + DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY); } } } diff --git a/source/blender/editors/transform/transform_convert_node.c b/source/blender/editors/transform/transform_convert_node.c index 12c4d0816ae..9d2d3713bf0 100644 --- a/source/blender/editors/transform/transform_convert_node.c +++ b/source/blender/editors/transform/transform_convert_node.c @@ -27,6 +27,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_rect.h" #include "BKE_context.h" #include "BKE_node.h" @@ -35,6 +36,7 @@ #include "ED_node.h" #include "UI_interface.h" +#include "UI_view2d.h" #include "transform.h" #include "transform_convert.h" @@ -44,6 +46,12 @@ /** \name Node Transform Creation * \{ */ +typedef struct NodeTransCustomData { + /* Initial rect of the view2d, used for computing offset during edge panning */ + rctf initial_v2d_cur; + View2DEdgePanData edge_pan; +} NodeTransCustomData; + /* transcribe given node into TransData2D for Transforming */ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node, const float dpi_fac) { @@ -107,6 +115,24 @@ void createTransNodeData(TransInfo *t) const float dpi_fac = UI_DPI_FAC; SpaceNode *snode = t->area->spacedata.first; + if (t->mode == TFM_TRANSLATION) { + /* Disable cursor wrapping in the node editor for edge pan */ + t->flag |= T_NO_CURSOR_WRAP; + } + + /* Custom data to enable edge panning during the node transform */ + NodeTransCustomData *customdata = MEM_callocN(sizeof(*customdata), __func__); + UI_view2d_edge_pan_init(t->context, + &customdata->edge_pan, + NODE_EDGE_PAN_INSIDE_PAD, + NODE_EDGE_PAN_OUTSIDE_PAD, + NODE_EDGE_PAN_SPEED_RAMP, + NODE_EDGE_PAN_MAX_SPEED, + NODE_EDGE_PAN_DELAY); + customdata->initial_v2d_cur = t->region->v2d.cur; + t->custom.type.data = customdata; + t->custom.type.use_free = true; + TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); tc->data_len = 0; @@ -150,6 +176,19 @@ void flushTransNodes(TransInfo *t) { const float dpi_fac = UI_DPI_FAC; + NodeTransCustomData *customdata = (NodeTransCustomData *)t->custom.type.data; + + if (t->mode == TFM_TRANSLATION) { + /* Edge panning functions expect window coordinates, mval is relative to region */ + const float x = t->region->winrct.xmin + t->mval[0]; + const float y = t->region->winrct.ymin + t->mval[1]; + UI_view2d_edge_pan_apply(t->context, &customdata->edge_pan, x, y); + } + + /* Initial and current view2D rects for additional transform due to view panning and zooming */ + const rctf *rect_src = &customdata->initial_v2d_cur; + const rctf *rect_dst = &t->region->v2d.cur; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { applyGridAbsolute(t); @@ -159,23 +198,28 @@ void flushTransNodes(TransInfo *t) TransData2D *td2d = &tc->data_2d[i]; bNode *node = td->extra; - /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */ + float loc[2]; + copy_v2_v2(loc, td2d->loc); + + /* additional offset due to change in view2D rect */ + BLI_rctf_transform_pt_v(rect_dst, rect_src, loc, loc); + #ifdef USE_NODE_CENTER - float locx = (td2d->loc[0] - (BLI_rctf_size_x(&node->totr)) * +0.5f) / dpi_fac; - float locy = (td2d->loc[1] - (BLI_rctf_size_y(&node->totr)) * -0.5f) / dpi_fac; -#else - float locx = td2d->loc[0] / dpi_fac; - float locy = td2d->loc[1] / dpi_fac; + loc[0] -= 0.5f * BLI_rctf_size_x(&node->totr); + loc[1] += 0.5f * BLI_rctf_size_y(&node->totr); #endif + /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */ + loc[0] /= dpi_fac; + loc[1] /= dpi_fac; + /* account for parents (nested nodes) */ if (node->parent) { - nodeFromView(node->parent, locx, locy, &node->locx, &node->locy); - } - else { - node->locx = locx; - node->locy = locy; + nodeFromView(node->parent, loc[0], loc[1], &loc[0], &loc[1]); } + + node->locx = loc[0]; + node->locy = loc[1]; } /* handle intersection with noodles */ diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index c217478bd04..ee6cb391fdc 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -153,7 +153,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) if (t->mode != TFM_DUMMY && ob->rigidbody_object) { float rot[3][3], scale[3]; - float ctime = BKE_scene_frame_get(scene); + float ctime = BKE_scene_ctime_get(scene); /* only use rigid body transform if simulation is running, * avoids problems with initial setup of rigid bodies */ @@ -978,7 +978,7 @@ void special_aftertrans_update__object(bContext *C, TransInfo *t) /* restore rigid body transform */ if (ob->rigidbody_object && canceled) { - float ctime = BKE_scene_frame_get(t->scene); + float ctime = BKE_scene_ctime_get(t->scene); if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime)) { BKE_rigidbody_aftertrans_update(ob, td->ext->oloc, diff --git a/source/blender/editors/transform/transform_convert_particle.c b/source/blender/editors/transform/transform_convert_particle.c index cb4df28d94b..681d6aea774 100644 --- a/source/blender/editors/transform/transform_convert_particle.c +++ b/source/blender/editors/transform/transform_convert_particle.c @@ -91,7 +91,7 @@ void createTransParticleVerts(TransInfo *t) } } - /* note: in prop mode we need at least 1 selected */ + /* NOTE: in prop mode we need at least 1 selected. */ if (hasselected == 0) { return; } diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index c0a66b8846e..a6f5aba5a1d 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -33,6 +33,7 @@ #include "ED_markers.h" +#include "SEQ_iterator.h" #include "SEQ_relations.h" #include "SEQ_sequencer.h" #include "SEQ_time.h" @@ -62,9 +63,6 @@ typedef struct TransDataSeq { */ typedef struct TransSeq { TransDataSeq *tdseq; - int min; - int max; - bool snap_left; int selection_channel_range_min; int selection_channel_range_max; } TransSeq; @@ -76,12 +74,9 @@ typedef struct TransSeq { /* This function applies the rules for transforming a strip so duplicate * checks don't need to be added in multiple places. * - * recursive, count and flag MUST be set. - * - * seq->depth must be set before running this function so we know if the strips - * are root level or not + * count and flag MUST be set. */ -static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_recursive, int *r_count, int *r_flag) +static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_count, int *r_flag) { /* for extend we need to do some tricks */ if (t->mode == TFM_TIME_EXTEND) { @@ -90,16 +85,14 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_recursive, int *r_c Scene *scene = t->scene; int cfra = CFRA; - int left = SEQ_transform_get_left_handle_frame(seq, false); - int right = SEQ_transform_get_right_handle_frame(seq, false); + int left = SEQ_transform_get_left_handle_frame(seq); + int right = SEQ_transform_get_right_handle_frame(seq); - if (seq->depth == 0 && ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK))) { - *r_recursive = false; + if (((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK))) { *r_count = 0; *r_flag = 0; } else { - *r_recursive = false; *r_count = 1; /* unless its set to 0, extend will never set 2 handles at once */ *r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL); @@ -131,66 +124,34 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_recursive, int *r_c /* *** Normal Transform *** */ - if (seq->depth == 0) { - - /* Count */ + /* Count */ - /* Non nested strips (resect selection and handles) */ - if ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK)) { - *r_recursive = false; - *r_count = 0; - *r_flag = 0; + /* Non nested strips (resect selection and handles) */ + if ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK)) { + *r_count = 0; + *r_flag = 0; + } + else { + if ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == (SEQ_LEFTSEL | SEQ_RIGHTSEL)) { + *r_flag = seq->flag; + *r_count = 2; /* we need 2 transdata's */ } else { - if ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == (SEQ_LEFTSEL | SEQ_RIGHTSEL)) { - *r_flag = seq->flag; - *r_count = 2; /* we need 2 transdata's */ - } - else { - *r_flag = seq->flag; - *r_count = 1; /* selected or with a handle selected */ - } - - /* Recursive */ - - if ((seq->type == SEQ_TYPE_META) && ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == 0)) { - /* if any handles are selected, don't recurse */ - *r_recursive = true; - } - else { - *r_recursive = false; - } + *r_flag = seq->flag; + *r_count = 1; /* selected or with a handle selected */ } } - else { - /* Nested, different rules apply */ - - *r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL); - *r_count = 1; /* ignore the selection for nested */ - *r_recursive = (seq->type == SEQ_TYPE_META); - } } } -static int SeqTransCount(TransInfo *t, Sequence *parent, ListBase *seqbase, int depth) +static int SeqTransCount(TransInfo *t, ListBase *seqbase) { Sequence *seq; - int tot = 0, recursive, count, flag; + int tot = 0, count, flag; for (seq = seqbase->first; seq; seq = seq->next) { - seq->depth = depth; - - /* 'seq->tmp' is used by seq_tx_get_final_{left, right} - * to check sequence's range and clamp to it if needed. - * It's first place where digging into sequences tree, so store link to parent here. */ - seq->tmp = parent; - - SeqTransInfo(t, seq, &recursive, &count, &flag); /* ignore the flag */ + SeqTransInfo(t, seq, &count, &flag); /* ignore the flag */ tot += count; - - if (recursive) { - tot += SeqTransCount(t, seq, &seq->seqbase, depth + 1); - } } return tot; @@ -206,16 +167,16 @@ static TransData *SeqToTransData( /* Use seq_tx_get_final_left() and an offset here * so transform has the left hand location of the strip. * tdsq->start_offset is used when flushing the tx data back */ - start_left = SEQ_transform_get_left_handle_frame(seq, false); + start_left = SEQ_transform_get_left_handle_frame(seq); td2d->loc[0] = start_left; tdsq->start_offset = start_left - seq->start; /* use to apply the original location */ break; case SEQ_LEFTSEL: - start_left = SEQ_transform_get_left_handle_frame(seq, false); + start_left = SEQ_transform_get_left_handle_frame(seq); td2d->loc[0] = start_left; break; case SEQ_RIGHTSEL: - td2d->loc[0] = SEQ_transform_get_right_handle_frame(seq, false); + td2d->loc[0] = SEQ_transform_get_right_handle_frame(seq); break; } @@ -256,27 +217,16 @@ static TransData *SeqToTransData( return td; } -static int SeqToTransData_Recursive( +static int SeqToTransData_build( TransInfo *t, ListBase *seqbase, TransData *td, TransData2D *td2d, TransDataSeq *tdsq) { Sequence *seq; - int recursive, count, flag; + int count, flag; int tot = 0; for (seq = seqbase->first; seq; seq = seq->next) { - SeqTransInfo(t, seq, &recursive, &count, &flag); - - /* add children first so recalculating metastrips does nested strips first */ - if (recursive) { - int tot_children = SeqToTransData_Recursive(t, &seq->seqbase, td, td2d, tdsq); - - td = td + tot_children; - td2d = td2d + tot_children; - tdsq = tdsq + tot_children; - - tot += tot_children; - } + SeqTransInfo(t, seq, &count, &flag); /* use 'flag' which is derived from seq->flag but modified for special cases */ if (flag & SELECT) { @@ -299,224 +249,200 @@ static int SeqToTransData_Recursive( return tot; } -static void SeqTransDataBounds(TransInfo *t, ListBase *seqbase, TransSeq *ts) +static void free_transform_custom_data(TransCustomData *custom_data) { - Sequence *seq; - int recursive, count, flag; - int max = INT32_MIN, min = INT32_MAX; - - for (seq = seqbase->first; seq; seq = seq->next) { + if ((custom_data->data != NULL) && custom_data->use_free) { + TransSeq *ts = custom_data->data; + MEM_freeN(ts->tdseq); + MEM_freeN(custom_data->data); + custom_data->data = NULL; + } +} - /* just to get the flag since there are corner cases where this isn't totally obvious */ - SeqTransInfo(t, seq, &recursive, &count, &flag); +/* Canceled, need to update the strips display. */ +static void seq_transform_cancel(TransInfo *t, SeqCollection *transformed_strips) +{ + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, transformed_strips) { + SEQ_time_update_sequence_bounds(t->scene, seq); + } +} - /* use 'flag' which is derived from seq->flag but modified for special cases */ - if (flag & SELECT) { - if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) { - if (flag & SEQ_LEFTSEL) { - min = min_ii(seq->startdisp, min); - max = max_ii(seq->startdisp, max); - } - if (flag & SEQ_RIGHTSEL) { - min = min_ii(seq->enddisp, min); - max = max_ii(seq->enddisp, max); - } - } - else { - min = min_ii(seq->startdisp, min); - max = max_ii(seq->enddisp, max); - } +static bool seq_transform_check_overlap(SeqCollection *transformed_strips) +{ + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, transformed_strips) { + if (seq->flag & SEQ_OVERLAP) { + return true; } } + return false; +} - if (ts) { - ts->max = max; - ts->min = min; +static SeqCollection *extract_standalone_strips(SeqCollection *transformed_strips) +{ + SeqCollection *collection = SEQ_collection_create(__func__); + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, transformed_strips) { + if ((seq->type & SEQ_TYPE_EFFECT) == 0 || seq->seq1 == NULL) { + SEQ_collection_append_strip(seq, collection); + } } + return collection; } -static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data) +/* Query strips positioned after left edge of transformed strips boundbox. */ +static SeqCollection *query_right_side_strips(ListBase *seqbase, SeqCollection *transformed_strips) { - Editing *ed = SEQ_editing_get(t->scene, false); - - if (ed != NULL) { - - ListBase *seqbasep = ed->seqbasep; - TransData *td = tc->data; - int a; - - /* prevent updating the same seq twice - * if the transdata order is changed this will mess up - * but so will TransDataSeq */ - Sequence *seq_prev = NULL; + int minframe = MAXFRAME; + { Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, transformed_strips) { + minframe = min_ii(minframe, seq->startdisp); + } + } - if (!(t->state == TRANS_CANCEL)) { + SeqCollection *collection = SEQ_collection_create(__func__); + LISTBASE_FOREACH (Sequence *, seq, seqbase) { + if ((seq->flag & SELECT) == 0 && seq->startdisp >= minframe) { + SEQ_collection_append_strip(seq, collection); + } + } + return collection; +} -#if 0 /* Default 2.4 behavior. */ +static void seq_transform_update_effects(TransInfo *t, SeqCollection *collection) +{ + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, collection) { + if ((seq->type & SEQ_TYPE_EFFECT) && (seq->seq1 || seq->seq2 || seq->seq3)) { + SEQ_time_update_sequence(t->scene, seq); + } + } +} - /* flush to 2d vector from internally used 3d vector */ - for (a = 0; a < t->total; a++, td++) { - if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) { - seq = ((TransDataSeq *)td->extra)->seq; - SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene); - } +/* Check if effect strips with input are transformed. */ +static bool seq_transform_check_strip_effects(SeqCollection *transformed_strips) +{ + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, transformed_strips) { + if ((seq->type & SEQ_TYPE_EFFECT) && (seq->seq1 || seq->seq2 || seq->seq3)) { + return true; + } + } + return false; +} - seq_prev = seq; - } +/* Offset all strips positioned after left edge of transformed strips boundbox by amount equal + * to overlap of transformed strips. */ +static void seq_transform_handle_expand_to_fit(TransInfo *t, SeqCollection *transformed_strips) +{ + Editing *ed = SEQ_editing_get(t->scene, false); + ListBase *seqbasep = SEQ_active_seqbase_get(ed); + ListBase *markers = &t->scene->markers; + const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag & + SEQ_MARKER_TRANS) != 0; -#else /* durian hack */ - { - int overlap = 0; + SeqCollection *right_side_strips = query_right_side_strips(seqbasep, transformed_strips); - for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) { - seq = ((TransDataSeq *)td->extra)->seq; - if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) { - overlap = 1; - break; - } - } + /* Temporarily move right side strips beyond timeline boundary. */ + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, right_side_strips) { + seq->machine += MAXSEQ * 2; + } - if (overlap) { - const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag & - SEQ_MARKER_TRANS) != 0; - ListBase *markers = &t->scene->markers; + /* Shuffle transformed standalone strips. This is because transformed strips can overlap with + * strips on left side. */ + SeqCollection *standalone_strips = extract_standalone_strips(transformed_strips); + SEQ_transform_seqbase_shuffle_time( + standalone_strips, seqbasep, t->scene, markers, use_sync_markers); + SEQ_collection_free(standalone_strips); - bool has_effect_root = false, has_effect_any = false; - for (seq = seqbasep->first; seq; seq = seq->next) { - seq->tmp = NULL; - } + /* Move temporarily moved strips back to their original place and tag for shuffling. */ + SEQ_ITERATOR_FOREACH (seq, right_side_strips) { + seq->machine -= MAXSEQ * 2; + } + /* Shuffle again to displace strips on right side. Final effect shuffling is done in + * seq_transform_handle_overlap. */ + SEQ_transform_seqbase_shuffle_time( + right_side_strips, seqbasep, t->scene, markers, use_sync_markers); + seq_transform_update_effects(t, right_side_strips); + SEQ_collection_free(right_side_strips); +} - td = tc->data; - for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) { - seq = ((TransDataSeq *)td->extra)->seq; - if ((seq != seq_prev)) { - /* check effects strips, we cant change their time */ - if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) { - has_effect_any = true; - if (seq->depth == 0) { - has_effect_root = true; - } - } - else { - /* Tag seq with a non zero value, used by - * SEQ_transform_seqbase_shuffle_time to identify the ones to shuffle */ - if (seq->depth == 0) { - seq->tmp = (void *)1; - } - } - } - } +static void seq_transform_handle_overlap(TransInfo *t, SeqCollection *transformed_strips) +{ + Editing *ed = SEQ_editing_get(t->scene, false); + ListBase *seqbasep = SEQ_active_seqbase_get(ed); - if (t->flag & T_ALT_TRANSFORM) { - int minframe = MAXFRAME; - td = tc->data; - for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) { - seq = ((TransDataSeq *)td->extra)->seq; - if ((seq != seq_prev) && (seq->depth == 0)) { - minframe = min_ii(minframe, seq->startdisp); - } - } - - for (seq = seqbasep->first; seq; seq = seq->next) { - if (!(seq->flag & SELECT)) { - if (seq->startdisp >= minframe) { - seq->machine += MAXSEQ * 2; - } - } - } - - SEQ_transform_seqbase_shuffle_time(seqbasep, t->scene, markers, use_sync_markers); - - for (seq = seqbasep->first; seq; seq = seq->next) { - if (seq->machine >= MAXSEQ * 2) { - seq->machine -= MAXSEQ * 2; - seq->tmp = (void *)1; - } - else { - seq->tmp = NULL; - } - } - - SEQ_transform_seqbase_shuffle_time(seqbasep, t->scene, markers, use_sync_markers); - } - else { - SEQ_transform_seqbase_shuffle_time(seqbasep, t->scene, markers, use_sync_markers); - } + if (t->flag & T_ALT_TRANSFORM) { + seq_transform_handle_expand_to_fit(t, transformed_strips); + } + else { + ListBase *markers = &t->scene->markers; + const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag & + SEQ_MARKER_TRANS) != 0; + /* Shuffle non strips with no effects attached. */ + SeqCollection *standalone_strips = extract_standalone_strips(transformed_strips); + SEQ_transform_seqbase_shuffle_time( + standalone_strips, seqbasep, t->scene, markers, use_sync_markers); + SEQ_collection_free(standalone_strips); + } - if (has_effect_any) { - /* update effects strips based on strips just moved in time */ - td = tc->data; - for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) { - seq = ((TransDataSeq *)td->extra)->seq; - if ((seq != seq_prev)) { - if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) { - SEQ_time_update_sequence(t->scene, seq); - } - } - } - } + if (seq_transform_check_strip_effects(transformed_strips)) { + /* Update effect strips based on strips just moved in time. */ + seq_transform_update_effects(t, transformed_strips); - if (has_effect_root) { - /* now if any effects _still_ overlap, we need to move them up */ - td = tc->data; - for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) { - seq = ((TransDataSeq *)td->extra)->seq; - if ((seq != seq_prev) && (seq->depth == 0)) { - if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) { - if (SEQ_transform_test_overlap(seqbasep, seq)) { - SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene); - } - } - } - } - /* done with effects */ - } + /* If any effects still overlap, we need to move them up. */ + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, transformed_strips) { + if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) { + if (SEQ_transform_test_overlap(seqbasep, seq)) { + SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene); } } -#endif + } + } +} - for (seq = seqbasep->first; seq; seq = seq->next) { - /* We might want to build a list of effects that need to be updated during transform */ - if (seq->type & SEQ_TYPE_EFFECT) { - if (seq->seq1 && seq->seq1->flag & SELECT) { - SEQ_time_update_sequence(t->scene, seq); - } - else if (seq->seq2 && seq->seq2->flag & SELECT) { - SEQ_time_update_sequence(t->scene, seq); - } - else if (seq->seq3 && seq->seq3->flag & SELECT) { - SEQ_time_update_sequence(t->scene, seq); - } - } - } +static SeqCollection *seq_transform_collection_from_transdata(TransDataContainer *tc) +{ + SeqCollection *collection = SEQ_collection_create(__func__); + TransData *td = tc->data; + for (int a = 0; a < tc->data_len; a++, td++) { + Sequence *seq = ((TransDataSeq *)td->extra)->seq; + SEQ_collection_append_strip(seq, collection); + } + return collection; +} - SEQ_sort(t->scene); - } - else { - /* Canceled, need to update the strips display */ - for (a = 0; a < tc->data_len; a++, td++) { - seq = ((TransDataSeq *)td->extra)->seq; - if ((seq != seq_prev) && (seq->depth == 0)) { - if (seq->flag & SEQ_OVERLAP) { - SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene); - } +static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data) +{ + Editing *ed = SEQ_editing_get(t->scene, false); + if (ed == NULL) { + free_transform_custom_data(custom_data); + return; + } - SEQ_time_update_sequence_bounds(t->scene, seq); - } - seq_prev = seq; - } - } + SeqCollection *transformed_strips = seq_transform_collection_from_transdata(tc); + + if (t->state == TRANS_CANCEL) { + seq_transform_cancel(t, transformed_strips); + SEQ_collection_free(transformed_strips); + free_transform_custom_data(custom_data); + return; } - if ((custom_data->data != NULL) && custom_data->use_free) { - TransSeq *ts = custom_data->data; - MEM_freeN(ts->tdseq); - MEM_freeN(custom_data->data); - custom_data->data = NULL; + if (seq_transform_check_overlap(transformed_strips)) { + seq_transform_handle_overlap(t, transformed_strips); } + seq_transform_update_effects(t, transformed_strips); + SEQ_collection_free(transformed_strips); + + SEQ_sort(ed->seqbasep); DEG_id_tag_update(&t->scene->id, ID_RECALC_SEQUENCER_STRIPS); + free_transform_custom_data(custom_data); } void createTransSeqData(TransInfo *t) @@ -562,7 +488,7 @@ void createTransSeqData(TransInfo *t) } #endif - count = SeqTransCount(t, NULL, ed->seqbasep, 0); + count = SeqTransCount(t, ed->seqbasep); /* allocate memory for data */ tc->data_len = count; @@ -579,16 +505,7 @@ void createTransSeqData(TransInfo *t) ts->tdseq = tdsq = MEM_callocN(tc->data_len * sizeof(TransDataSeq), "TransSeq TransDataSeq"); /* loop 2: build transdata array */ - SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq); - SeqTransDataBounds(t, ed->seqbasep, ts); - - if (t->flag & T_MODAL) { - /* set the snap mode based on how close the mouse is at the end/start points */ - int xmouse = (int)UI_view2d_region_to_view_x((View2D *)t->view, t->mouse.imval[0]); - if (abs(xmouse - ts->max) > abs(xmouse - ts->min)) { - ts->snap_left = true; - } - } + SeqToTransData_build(t, ed->seqbasep, td, td2d, tdsq); ts->selection_channel_range_min = MAXSEQ + 1; LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { @@ -612,15 +529,10 @@ void createTransSeqData(TransInfo *t) BLI_INLINE void trans_update_seq(Scene *sce, Sequence *seq, int old_start, int sel_flag) { - if (seq->depth == 0) { - /* Calculate this strip and all nested strips. - * Children are ALWAYS transformed first so we don't need to do this in another loop. - */ - SEQ_time_update_sequence(sce, seq); - } - else { - SEQ_time_update_sequence_bounds(sce, seq); - } + /* Calculate this strip and all nested strips. + * Children are ALWAYS transformed first so we don't need to do this in another loop. + */ + SEQ_time_update_sequence(sce, seq); if (sel_flag == SELECT) { SEQ_offset_animdata(sce, seq, seq->start - old_start); @@ -640,102 +552,49 @@ static void flushTransSeq(TransInfo *t) TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); - /* prevent updating the same seq twice - * if the transdata order is changed this will mess up - * but so will TransDataSeq */ - Sequence *seq_prev = NULL; - int old_start_prev = 0, sel_flag_prev = 0; - - /* flush to 2d vector from internally used 3d vector */ + /* Flush to 2D vector from internally used 3D vector. */ for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) { - int old_start; tdsq = (TransDataSeq *)td->extra; seq = tdsq->seq; - old_start = seq->start; new_frame = round_fl_to_int(td2d->loc[0]); switch (tdsq->sel_flag) { case SELECT: - if ((seq->depth != 0 || SEQ_transform_sequence_can_be_translated(seq))) { - /* for meta's, their children move */ - seq->start = new_frame - tdsq->start_offset; - } - if (seq->depth == 0) { - seq->machine = round_fl_to_int(td2d->loc[1]); - CLAMP(seq->machine, 1, MAXSEQ); + if (SEQ_transform_sequence_can_be_translated(seq)) { + const int offset = new_frame - tdsq->start_offset - seq->start; + SEQ_transform_translate_sequence(t->scene, seq, offset); } + seq->machine = round_fl_to_int(td2d->loc[1]); + CLAMP(seq->machine, 1, MAXSEQ); break; - case SEQ_LEFTSEL: /* no vertical transform */ + + case SEQ_LEFTSEL: /* No vertical transform. */ SEQ_transform_set_left_handle_frame(seq, new_frame); SEQ_transform_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL); - - /* todo - move this into aftertrans update? - old seq tx needed it anyway */ SEQ_transform_fix_single_image_seq_offsets(seq); + SEQ_time_update_sequence(t->scene, seq); break; - case SEQ_RIGHTSEL: /* no vertical transform */ + case SEQ_RIGHTSEL: /* No vertical transform. */ SEQ_transform_set_right_handle_frame(seq, new_frame); SEQ_transform_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL); - - /* todo - move this into aftertrans update? - old seq tx needed it anyway */ SEQ_transform_fix_single_image_seq_offsets(seq); + SEQ_time_update_sequence(t->scene, seq); break; } - - /* Update *previous* seq! Else, we would update a seq after its first transform, - * and if it has more than one (like e.g. SEQ_LEFTSEL and SEQ_RIGHTSEL), - * the others are not updated! See T38469. - */ - if (seq != seq_prev) { - if (seq_prev) { - trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev); - } - - seq_prev = seq; - old_start_prev = old_start; - sel_flag_prev = tdsq->sel_flag; - } - else { - /* We want to accumulate *all* sel_flags for this seq! */ - sel_flag_prev |= tdsq->sel_flag; - } - } - - /* Don't forget to update the last seq! */ - if (seq_prev) { - trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev); } - /* originally TFM_TIME_EXTEND, transform changes */ + /* Update all effects. */ if (ELEM(t->mode, TFM_SEQ_SLIDE, TFM_TIME_TRANSLATE)) { - /* Special annoying case here, need to calc meta-strips with TFM_TIME_EXTEND only */ - - /* calc all meta's then effects T27953. */ - for (seq = seqbasep->first; seq; seq = seq->next) { - if (seq->type == SEQ_TYPE_META && seq->flag & SELECT) { - SEQ_time_update_sequence(t->scene, seq); - } - } for (seq = seqbasep->first; seq; seq = seq->next) { if (seq->seq1 || seq->seq2 || seq->seq3) { SEQ_time_update_sequence(t->scene, seq); } } - - /* update effects inside meta's */ - for (a = 0, seq_prev = NULL, td = tc->data, td2d = tc->data_2d; a < tc->data_len; - a++, td++, td2d++, seq_prev = seq) { - tdsq = (TransDataSeq *)td->extra; - seq = tdsq->seq; - if ((seq != seq_prev) && (seq->depth != 0)) { - if (seq->seq1 || seq->seq2 || seq->seq3) { - SEQ_time_update_sequence(t->scene, seq); - } - } - } } /* need to do the overlap check in a new loop otherwise adjacent strips * will not be updated and we'll get false positives */ + Sequence *seq_prev = NULL; seq_prev = NULL; for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) { @@ -743,12 +602,10 @@ static void flushTransSeq(TransInfo *t) seq = tdsq->seq; if (seq != seq_prev) { - if (seq->depth == 0) { - /* test overlap, displays red outline */ - seq->flag &= ~SEQ_OVERLAP; - if (SEQ_transform_test_overlap(seqbasep, seq)) { - seq->flag |= SEQ_OVERLAP; - } + /* test overlap, displays red outline */ + seq->flag &= ~SEQ_OVERLAP; + if (SEQ_transform_test_overlap(seqbasep, seq)) { + seq->flag |= SEQ_OVERLAP; } } seq_prev = seq; @@ -792,7 +649,7 @@ void special_aftertrans_update__sequencer(bContext *UNUSED(C), TransInfo *t) return; } /* freeSeqData in transform_conversions.c does this - * keep here so the else at the end wont run... */ + * keep here so the else at the end won't run... */ SpaceSeq *sseq = (SpaceSeq *)t->area->spacedata.first; @@ -815,25 +672,19 @@ void special_aftertrans_update__sequencer(bContext *UNUSED(C), TransInfo *t) } } -void transform_convert_sequencer_channel_clamp(TransInfo *t) +void transform_convert_sequencer_channel_clamp(TransInfo *t, float r_val[2]) { 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 channel_offset = round_fl_to_int(r_val[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; + r_val[1] -= max_channel_after_transform - MAXSEQ; } if (min_channel_after_transform < 1) { - t->values[1] -= min_channel_after_transform - 1; + r_val[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; - return ts->snap_left ? ts->min : ts->max; -} - /** \} */ diff --git a/source/blender/editors/transform/transform_data.h b/source/blender/editors/transform/transform_data.h index 5b01433c96b..15e40ec466b 100644 --- a/source/blender/editors/transform/transform_data.h +++ b/source/blender/editors/transform/transform_data.h @@ -149,6 +149,8 @@ typedef struct TransData { short protectflag; } TransData; +#define TRANSDATA_THREAD_LIMIT 1024 + /** #TransData.flag */ enum { TD_SELECTED = 1 << 0, @@ -168,15 +170,17 @@ enum { TD_BEZTRIPLE = 1 << 8, /** when this is set, don't apply translation changes to this element */ TD_NO_LOC = 1 << 9, - /** For Graph Editor autosnap, indicates that point should not undergo autosnapping */ + /** For Graph Editor auto-snap, indicates that point should not undergo auto-snapping. */ TD_NOTIMESNAP = 1 << 10, /** For Graph Editor - curves that can only have int-values * need their keyframes tagged with this. */ TD_INTVALUES = 1 << 11, +#define TD_MIRROR_AXIS_SHIFT 12 /** For editmode mirror. */ TD_MIRROR_X = 1 << 12, TD_MIRROR_Y = 1 << 13, TD_MIRROR_Z = 1 << 14, +#define TD_MIRROR_EDGE_AXIS_SHIFT 12 /** For editmode mirror, clamp axis to 0 */ TD_MIRROR_EDGE_X = 1 << 12, TD_MIRROR_EDGE_Y = 1 << 13, diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 71c91221fbb..aaac8e21cb9 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -353,13 +353,11 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->around = V3D_AROUND_CENTER_BOUNDS; } - BLI_assert(is_zero_v4(t->values_modal_offset)); - bool t_values_set_is_array = false; if (op && (prop = RNA_struct_find_property(op->ptr, "value")) && RNA_property_is_set(op->ptr, prop)) { - float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */ + float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory. */ if (RNA_property_array_check(prop)) { RNA_float_get_array(op->ptr, "value", values); t_values_set_is_array = true; @@ -368,7 +366,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve values[0] = RNA_float_get(op->ptr, "value"); } - copy_v4_v4(t->values, values); if (t->flag & T_MODAL) { /* Run before init functions so 'values_modal_offset' can be applied on mouse input. */ copy_v4_v4(t->values_modal_offset, values); @@ -859,8 +856,8 @@ void calculateCenter2D(TransInfo *t) void calculateCenterLocal(TransInfo *t, const float center_global[3]) { - /* setting constraint center */ - /* note, init functions may over-ride t->center */ + /* Setting constraint center. */ + /* NOTE: init functions may over-ride `t->center`. */ FOREACH_TRANS_DATA_CONTAINER (t, tc) { if (tc->use_local_mat) { mul_v3_m4v3(tc->center_local, tc->imat, center_global); @@ -913,7 +910,7 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2]) BKE_mask_coord_from_movieclip(space_clip->clip, &space_clip->user, co, cursor); } else { - BLI_assert(!"Shall not happen"); + BLI_assert_msg(0, "Shall not happen"); } r_center[0] = co[0] * t->aspect[0]; diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 7a780df0def..080a19cce1f 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -521,7 +521,7 @@ static void protectflag_to_drawflags_pchan(RegionView3D *rv3d, } } -/* for editmode*/ +/* For editmode. */ static void protectflag_to_drawflags_ebone(RegionView3D *rv3d, const EditBone *ebo) { if (ebo->flag & BONE_EDITMODE_LOCKED) { diff --git a/source/blender/editors/transform/transform_gizmo_extrude_3d.c b/source/blender/editors/transform/transform_gizmo_extrude_3d.c index ed6c3eb0255..ca4ed01c0f6 100644 --- a/source/blender/editors/transform/transform_gizmo_extrude_3d.c +++ b/source/blender/editors/transform/transform_gizmo_extrude_3d.c @@ -367,7 +367,7 @@ static void gizmo_mesh_extrude_refresh(const bContext *C, wmGizmoGroup *gzgroup) } } - /* TODO: skip calculating axis which wont be used (above). */ + /* TODO: skip calculating axis which won't be used (above). */ switch (axis_type) { case EXTRUDE_AXIS_NORMAL: for (int i = 0; i < 3; i++) { diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 414199badd7..0b46d0b9a13 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -450,17 +450,6 @@ void applyMouseInput(TransInfo *t, MouseInput *mi, const int mval[2], float outp mi->apply(t, mi, mval_db, output); } - if (!is_zero_v3(t->values_modal_offset)) { - float values_ofs[3]; - if (t->con.mode & CON_APPLY) { - mul_v3_m3v3(values_ofs, t->spacemtx, t->values_modal_offset); - } - else { - copy_v3_v3(values_ofs, t->values_modal_offset); - } - add_v3_v3(t->values, values_ofs); - } - if (mi->post) { mi->post(t, output); } diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index d61e7bb867c..65a673940f8 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -68,7 +68,7 @@ int transform_mode_really_used(bContext *C, int mode) return mode; } -bool transdata_check_local_center(TransInfo *t, short around) +bool transdata_check_local_center(const TransInfo *t, short around) { return ((around == V3D_AROUND_LOCAL_ORIGINS) && ((t->options & (CTX_OBJECT | CTX_POSE_BONE)) || @@ -248,7 +248,7 @@ void protectedSizeBits(short protectflag, float size[3]) /** \name Transform Limits * \{ */ -void constraintTransLim(TransInfo *t, TransData *td) +void constraintTransLim(const TransInfo *t, TransData *td) { if (td->con) { const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type( @@ -359,7 +359,7 @@ static void constraintob_from_transdata(bConstraintOb *cob, TransData *td) } } -static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) +static void constraintRotLim(const TransInfo *UNUSED(t), TransData *td) { if (td->con) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT); @@ -432,7 +432,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) } } -void constraintSizeLim(TransInfo *t, TransData *td) +void constraintSizeLim(const TransInfo *t, TransData *td) { if (td->con && td->ext) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT); @@ -524,7 +524,7 @@ void constraintSizeLim(TransInfo *t, TransData *td) /** \name Transform (Rotation Utils) * \{ */ /* Used by Transform Rotation and Transform Normal Rotation */ -void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final) +void headerRotation(TransInfo *t, char *str, const int str_size, float final) { size_t ofs = 0; @@ -533,25 +533,21 @@ void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final) outputNumInput(&(t->num), c, &t->scene->unit); - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - TIP_("Rotation: %s %s %s"), - &c[0], - t->con.text, - t->proptext); + ofs += BLI_snprintf_rlen( + str + ofs, str_size - ofs, TIP_("Rotation: %s %s %s"), &c[0], t->con.text, t->proptext); } else { - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - TIP_("Rotation: %.2f%s %s"), - RAD2DEGF(final), - t->con.text, - t->proptext); + ofs += BLI_snprintf_rlen(str + ofs, + str_size - ofs, + TIP_("Rotation: %.2f%s %s"), + RAD2DEGF(final), + t->con.text, + t->proptext); } if (t->flag & T_PROP_EDIT_ALL) { - ofs += BLI_snprintf( - str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" Proportional size: %.2f"), t->prop_size); + ofs += BLI_snprintf_rlen( + str + ofs, str_size - ofs, TIP_(" Proportional size: %.2f"), t->prop_size); } } @@ -561,8 +557,8 @@ void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final) * * Protected axis and other transform settings are taken into account. */ -void ElementRotation_ex(TransInfo *t, - TransDataContainer *tc, +void ElementRotation_ex(const TransInfo *t, + const TransDataContainer *tc, TransData *td, const float mat[3][3], const float *center) @@ -738,9 +734,25 @@ void ElementRotation_ex(TransInfo *t, /* can be called for texture space translate for example, then opt out */ if (td->ext->quat) { mul_m3_series(fmat, td->smtx, mat, td->mtx); + + if (!is_zero_v3(td->ext->dquat)) { + /* Correct for delta quat */ + float tmp_mat[3][3]; + quat_to_mat3(tmp_mat, td->ext->dquat); + mul_m3_m3m3(fmat, fmat, tmp_mat); + } + mat3_to_quat(quat, fmat); /* Actual transform */ + if (!is_zero_v4(td->ext->dquat)) { + /* Correct back for delta quat. */ + float idquat[4]; + invert_qt_qt_normalized(idquat, td->ext->dquat); + mul_qt_qtqt(quat, idquat, quat); + } + mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); + /* this function works on end result */ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); } @@ -765,21 +777,28 @@ void ElementRotation_ex(TransInfo *t, td->ext->irotAngle); } else { + /* Calculate the total rotation in eulers. */ float obmat[3][3]; mul_m3_m3m3(totmat, mat, td->mtx); mul_m3_m3m3(smat, td->smtx, totmat); - /* Calculate the total rotation in eulers. */ - add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* correct for delta rot */ + if (!is_zero_v3(td->ext->drot)) { + /* Correct for delta rot */ + add_eul_euleul(eul, td->ext->irot, td->ext->drot, td->ext->rotOrder); + } + else { + copy_v3_v3(eul, td->ext->irot); + } + eulO_to_mat3(obmat, eul, td->ext->rotOrder); - /* mat = transform, obmat = object rotation */ mul_m3_m3m3(fmat, smat, obmat); - mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat); - /* correct back for delta rot */ - sub_v3_v3v3(eul, eul, td->ext->drot); + if (!is_zero_v3(td->ext->drot)) { + /* Correct back for delta rot. */ + sub_eul_euleul(eul, eul, td->ext->drot, td->ext->rotOrder); + } /* and apply */ protectedRotateBits(td->protectflag, eul, td->ext->irot); @@ -791,8 +810,11 @@ void ElementRotation_ex(TransInfo *t, } } -void ElementRotation( - TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around) +void ElementRotation(const TransInfo *t, + const TransDataContainer *tc, + TransData *td, + const float mat[3][3], + const short around) { const float *center; @@ -811,7 +833,7 @@ void ElementRotation( /* -------------------------------------------------------------------- */ /** \name Transform (Resize Utils) * \{ */ -void headerResize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR]) +void headerResize(TransInfo *t, const float vec[3], char *str, const int str_size) { char tvec[NUM_STR_REP_LEN * 3]; size_t ofs = 0; @@ -827,59 +849,55 @@ void headerResize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR]) if (t->con.mode & CON_APPLY) { switch (t->num.idx_max) { case 0: - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - TIP_("Scale: %s%s %s"), - &tvec[0], - t->con.text, - t->proptext); + ofs += BLI_snprintf_rlen( + str + ofs, str_size - ofs, TIP_("Scale: %s%s %s"), &tvec[0], t->con.text, t->proptext); break; case 1: - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - TIP_("Scale: %s : %s%s %s"), - &tvec[0], - &tvec[NUM_STR_REP_LEN], - t->con.text, - t->proptext); + ofs += BLI_snprintf_rlen(str + ofs, + str_size - ofs, + TIP_("Scale: %s : %s%s %s"), + &tvec[0], + &tvec[NUM_STR_REP_LEN], + t->con.text, + t->proptext); break; case 2: - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - TIP_("Scale: %s : %s : %s%s %s"), - &tvec[0], - &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], - t->con.text, - t->proptext); + ofs += BLI_snprintf_rlen(str + ofs, + str_size - ofs, + TIP_("Scale: %s : %s : %s%s %s"), + &tvec[0], + &tvec[NUM_STR_REP_LEN], + &tvec[NUM_STR_REP_LEN * 2], + t->con.text, + t->proptext); break; } } else { if (t->flag & T_2D_EDIT) { - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - TIP_("Scale X: %s Y: %s%s %s"), - &tvec[0], - &tvec[NUM_STR_REP_LEN], - t->con.text, - t->proptext); + ofs += BLI_snprintf_rlen(str + ofs, + str_size - ofs, + TIP_("Scale X: %s Y: %s%s %s"), + &tvec[0], + &tvec[NUM_STR_REP_LEN], + t->con.text, + t->proptext); } else { - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - TIP_("Scale X: %s Y: %s Z: %s%s %s"), - &tvec[0], - &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], - t->con.text, - t->proptext); + ofs += BLI_snprintf_rlen(str + ofs, + str_size - ofs, + TIP_("Scale X: %s Y: %s Z: %s%s %s"), + &tvec[0], + &tvec[NUM_STR_REP_LEN], + &tvec[NUM_STR_REP_LEN * 2], + t->con.text, + t->proptext); } } if (t->flag & T_PROP_EDIT_ALL) { - ofs += BLI_snprintf( - str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" Proportional size: %.2f"), t->prop_size); + ofs += BLI_snprintf_rlen( + str + ofs, str_size - ofs, TIP_(" Proportional size: %.2f"), t->prop_size); } } @@ -906,7 +924,10 @@ static void TransMat3ToSize(const float mat[3][3], const float smat[3][3], float } } -void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3]) +void ElementResize(const TransInfo *t, + const TransDataContainer *tc, + TransData *td, + const float mat[3][3]) { float tmat[3][3], smat[3][3], center[3]; float vec[3]; @@ -999,17 +1020,31 @@ void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float ma sub_v3_v3(vec, td->center); } - /* grease pencil falloff */ + /* Grease pencil falloff. + * + * FIXME: This is bad on multiple levels! + * + * - #applyNumInput is not intended to be run for every element, + * this writes back into the number input in a way that doesn't make sense to run many times. + * + * - Writing into #TransInfo should be avoided since it means order of operations + * may impact the result and isn't thread-safe. + * + * Operating on copies as a temporary solution. + */ if (t->options & CTX_GPENCIL_STROKES) { bGPDstroke *gps = (bGPDstroke *)td->extra; mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff); - /* scale stroke thickness */ + /* Scale stroke thickness. */ if (td->val) { - transform_snap_increment(t, t->values_final); - applyNumInput(&t->num, t->values_final); + NumInput num_evil = t->num; + float values_final_evil[4]; + copy_v4_v4(values_final_evil, t->values_final); + transform_snap_increment(t, values_final_evil); + applyNumInput(&num_evil, values_final_evil); - float ratio = t->values_final[0]; + float ratio = values_final_evil[0]; *td->val = td->ival * ratio * gps->runtime.multi_frame_falloff; CLAMP_MIN(*td->val, 0.001f); } @@ -1029,6 +1064,7 @@ void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float ma constraintTransLim(t, td); } + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h index 106dc68c9ee..027fb6b6982 100644 --- a/source/blender/editors/transform/transform_mode.h +++ b/source/blender/editors/transform/transform_mode.h @@ -41,22 +41,28 @@ typedef struct TransDataGenericSlideVert { /* transform_mode.c */ int transform_mode_really_used(struct bContext *C, int mode); -bool transdata_check_local_center(TransInfo *t, short around); +bool transdata_check_local_center(const TransInfo *t, short around); bool transform_mode_is_changeable(const int mode); void protectedTransBits(short protectflag, float vec[3]); void protectedSizeBits(short protectflag, float size[3]); -void constraintTransLim(TransInfo *t, TransData *td); -void constraintSizeLim(TransInfo *t, TransData *td); -void headerRotation(TransInfo *t, char *str, float final); -void ElementRotation_ex(TransInfo *t, - TransDataContainer *tc, +void constraintTransLim(const TransInfo *t, TransData *td); +void constraintSizeLim(const TransInfo *t, TransData *td); +void headerRotation(TransInfo *t, char *str, int str_size, float final); +void ElementRotation_ex(const TransInfo *t, + const TransDataContainer *tc, TransData *td, const float mat[3][3], const float *center); -void ElementRotation( - TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around); -void headerResize(TransInfo *t, const float vec[3], char *str); -void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3]); +void ElementRotation(const TransInfo *t, + const TransDataContainer *tc, + TransData *td, + const float mat[3][3], + const short around); +void headerResize(TransInfo *t, const float vec[3], char *str, int str_size); +void ElementResize(const TransInfo *t, + const TransDataContainer *tc, + TransData *td, + const float mat[3][3]); short getAnimEdit_SnapMode(TransInfo *t); void doAnimEdit_SnapFrame( TransInfo *t, TransData *td, TransData2D *td2d, struct AnimData *adt, short autosnap); diff --git a/source/blender/editors/transform/transform_mode_bend.c b/source/blender/editors/transform/transform_mode_bend.c index b3b1860f9ec..850d26571cd 100644 --- a/source/blender/editors/transform/transform_mode_bend.c +++ b/source/blender/editors/transform/transform_mode_bend.c @@ -29,6 +29,7 @@ #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_unit.h" @@ -47,9 +48,12 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/** \name Transform (Bend) +/** \name Transform (Bend) Custom Data * \{ */ +/** + * Custom data, stored in #TransInfo.custom.mode.data + */ struct BendCustomData { /* All values are in global space. */ float warp_sta[3]; @@ -62,6 +66,122 @@ struct BendCustomData { float warp_init_dist; }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform (Bend) Element + * \{ */ + +/** + * \note Small arrays / data-structures should be copied for faster memory access. + */ +struct TransDataArgs_Bend { + const TransInfo *t; + const TransDataContainer *tc; + + float angle; + struct BendCustomData bend_data; + + const float warp_sta_local[3]; + const float warp_end_local[3]; + const float warp_end_radius_local[3]; + const float pivot_local[3]; + bool is_clamp; +}; + +static void transdata_elem_bend(const TransInfo *t, + const TransDataContainer *tc, + TransData *td, + float angle, + const struct BendCustomData *bend_data, + const float warp_sta_local[3], + const float UNUSED(warp_end_local[3]), + const float warp_end_radius_local[3], + const float pivot_local[3], + + bool is_clamp) +{ + if (UNLIKELY(angle == 0.0f)) { + copy_v3_v3(td->loc, td->iloc); + return; + } + + float vec[3]; + float mat[3][3]; + float delta[3]; + float fac, fac_scaled; + + copy_v3_v3(vec, td->iloc); + mul_m3_v3(td->mtx, vec); + + fac = line_point_factor_v3(vec, warp_sta_local, warp_end_radius_local); + if (is_clamp) { + CLAMP(fac, 0.0f, 1.0f); + } + + if (t->options & CTX_GPENCIL_STROKES) { + /* grease pencil multiframe falloff */ + bGPDstroke *gps = (bGPDstroke *)td->extra; + if (gps != NULL) { + fac_scaled = fac * td->factor * gps->runtime.multi_frame_falloff; + } + else { + fac_scaled = fac * td->factor; + } + } + else { + fac_scaled = fac * td->factor; + } + + axis_angle_normalized_to_mat3(mat, bend_data->warp_nor, angle * fac_scaled); + interp_v3_v3v3(delta, warp_sta_local, warp_end_radius_local, fac_scaled); + sub_v3_v3(delta, warp_sta_local); + + /* delta is subtracted, rotation adds back this offset */ + sub_v3_v3(vec, delta); + + sub_v3_v3(vec, pivot_local); + mul_m3_v3(mat, vec); + add_v3_v3(vec, pivot_local); + + mul_m3_v3(td->smtx, vec); + + /* rotation */ + if ((t->flag & T_POINTS) == 0) { + ElementRotation(t, tc, td, mat, V3D_AROUND_LOCAL_ORIGINS); + } + + /* location */ + copy_v3_v3(td->loc, vec); +} + +static void transdata_elem_bend_fn(void *__restrict iter_data_v, + const int iter, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + struct TransDataArgs_Bend *data = iter_data_v; + TransData *td = &data->tc->data[iter]; + if (td->flag & TD_SKIP) { + return; + } + transdata_elem_bend(data->t, + data->tc, + td, + data->angle, + &data->bend_data, + data->warp_sta_local, + data->warp_end_local, + data->warp_end_radius_local, + data->pivot_local, + data->is_clamp); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform (Bend) + * \{ */ + static eRedrawFlag handleEventBend(TransInfo *UNUSED(t), const wmEvent *event) { eRedrawFlag status = TREDRAW_NOTHING; @@ -75,12 +195,11 @@ static eRedrawFlag handleEventBend(TransInfo *UNUSED(t), const wmEvent *event) static void Bend(TransInfo *t, const int UNUSED(mval[2])) { - float vec[3]; float pivot_global[3]; float warp_end_radius_global[3]; int i; char str[UI_MAX_DRAW_STR]; - const struct BendCustomData *data = t->custom.mode.data; + const struct BendCustomData *bend_data = t->custom.mode.data; const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0; union { @@ -100,7 +219,7 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) * this isn't essential but nicer to give reasonable snapping values for radius. */ if (t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) { const float radius_snap = 0.1f; - const float snap_hack = (t->snap[0] * data->warp_init_dist) / radius_snap; + const float snap_hack = (t->snap[0] * bend_data->warp_init_dist) / radius_snap; values.scale *= snap_hack; transform_snap_increment(t, values.vector); values.scale /= snap_hack; @@ -108,7 +227,7 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) #endif if (applyNumInput(&t->num, values.vector)) { - values.scale = values.scale / data->warp_init_dist; + values.scale = values.scale / bend_data->warp_init_dist; } copy_v2_v2(t->values_final, values.vector); @@ -132,34 +251,33 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) sizeof(str), TIP_("Bend Angle: %.3f Radius: %.4f, Alt, Clamp %s"), RAD2DEGF(values.angle), - values.scale * data->warp_init_dist, + values.scale * bend_data->warp_init_dist, WM_bool_as_string(is_clamp)); } values.angle *= -1.0f; - values.scale *= data->warp_init_dist; + values.scale *= bend_data->warp_init_dist; /* calc 'data->warp_end' from 'data->warp_end_init' */ - copy_v3_v3(warp_end_radius_global, data->warp_end); - dist_ensure_v3_v3fl(warp_end_radius_global, data->warp_sta, values.scale); + copy_v3_v3(warp_end_radius_global, bend_data->warp_end); + dist_ensure_v3_v3fl(warp_end_radius_global, bend_data->warp_sta, values.scale); /* done */ /* calculate pivot */ - copy_v3_v3(pivot_global, data->warp_sta); + copy_v3_v3(pivot_global, bend_data->warp_sta); if (values.angle > 0.0f) { madd_v3_v3fl(pivot_global, - data->warp_tan, + bend_data->warp_tan, -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle)); } else { madd_v3_v3fl(pivot_global, - data->warp_tan, + bend_data->warp_tan, +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle)); } /* TODO(campbell): xform, compensate object center. */ FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; float warp_sta_local[3]; float warp_end_local[3]; @@ -167,74 +285,52 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) float pivot_local[3]; if (tc->use_local_mat) { - sub_v3_v3v3(warp_sta_local, data->warp_sta, tc->mat[3]); - sub_v3_v3v3(warp_end_local, data->warp_end, tc->mat[3]); + sub_v3_v3v3(warp_sta_local, bend_data->warp_sta, tc->mat[3]); + sub_v3_v3v3(warp_end_local, bend_data->warp_end, tc->mat[3]); sub_v3_v3v3(warp_end_radius_local, warp_end_radius_global, tc->mat[3]); sub_v3_v3v3(pivot_local, pivot_global, tc->mat[3]); } else { - copy_v3_v3(warp_sta_local, data->warp_sta); - copy_v3_v3(warp_end_local, data->warp_end); + copy_v3_v3(warp_sta_local, bend_data->warp_sta); + copy_v3_v3(warp_end_local, bend_data->warp_end); copy_v3_v3(warp_end_radius_local, warp_end_radius_global); copy_v3_v3(pivot_local, pivot_global); } - for (i = 0; i < tc->data_len; i++, td++) { - float mat[3][3]; - float delta[3]; - float fac, fac_scaled; - - if (td->flag & TD_SKIP) { - continue; - } + if (tc->data_len < TRANSDATA_THREAD_LIMIT) { + TransData *td = tc->data; - if (UNLIKELY(values.angle == 0.0f)) { - copy_v3_v3(td->loc, td->iloc); - continue; - } - - copy_v3_v3(vec, td->iloc); - mul_m3_v3(td->mtx, vec); - - fac = line_point_factor_v3(vec, warp_sta_local, warp_end_radius_local); - if (is_clamp) { - CLAMP(fac, 0.0f, 1.0f); - } - - if (t->options & CTX_GPENCIL_STROKES) { - /* grease pencil multiframe falloff */ - bGPDstroke *gps = (bGPDstroke *)td->extra; - if (gps != NULL) { - fac_scaled = fac * td->factor * gps->runtime.multi_frame_falloff; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; } - else { - fac_scaled = fac * td->factor; - } - } - else { - fac_scaled = fac * td->factor; + transdata_elem_bend(t, + tc, + td, + values.angle, + bend_data, + warp_sta_local, + warp_end_local, + warp_end_radius_local, + pivot_local, + is_clamp); } - - axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled); - interp_v3_v3v3(delta, warp_sta_local, warp_end_radius_local, fac_scaled); - sub_v3_v3(delta, warp_sta_local); - - /* delta is subtracted, rotation adds back this offset */ - sub_v3_v3(vec, delta); - - sub_v3_v3(vec, pivot_local); - mul_m3_v3(mat, vec); - add_v3_v3(vec, pivot_local); - - mul_m3_v3(td->smtx, vec); - - /* rotation */ - if ((t->flag & T_POINTS) == 0) { - ElementRotation(t, tc, td, mat, V3D_AROUND_LOCAL_ORIGINS); - } - - /* location */ - copy_v3_v3(td->loc, vec); + } + else { + struct TransDataArgs_Bend data = { + .t = t, + .tc = tc, + .angle = values.angle, + .bend_data = *bend_data, + .warp_sta_local = {UNPACK3(warp_sta_local)}, + .warp_end_local = {UNPACK3(warp_end_local)}, + .warp_end_radius_local = {UNPACK3(warp_end_radius_local)}, + .pivot_local = {UNPACK3(pivot_local)}, + .is_clamp = is_clamp, + }; + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_bend_fn, &settings); } } diff --git a/source/blender/editors/transform/transform_mode_edge_bevelweight.c b/source/blender/editors/transform/transform_mode_edge_bevelweight.c index 3ce52ed3296..425bfec241e 100644 --- a/source/blender/editors/transform/transform_mode_edge_bevelweight.c +++ b/source/blender/editors/transform/transform_mode_edge_bevelweight.c @@ -25,6 +25,7 @@ #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_unit.h" @@ -40,6 +41,50 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ +/** \name Transform (Bevel Weight) Element + * \{ */ + +/** + * \note Small arrays / data-structures should be stored copied for faster memory access. + */ +struct TransDataArgs_BevelWeight { + const TransInfo *t; + const TransDataContainer *tc; + float weight; +}; + +static void transdata_elem_bevel_weight(const TransInfo *UNUSED(t), + const TransDataContainer *UNUSED(tc), + TransData *td, + const float weight) +{ + if (td->val == NULL) { + return; + } + *td->val = td->ival + weight * td->factor; + if (*td->val < 0.0f) { + *td->val = 0.0f; + } + if (*td->val > 1.0f) { + *td->val = 1.0f; + } +} + +static void transdata_elem_bevel_weight_fn(void *__restrict iter_data_v, + const int iter, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + struct TransDataArgs_BevelWeight *data = iter_data_v; + TransData *td = &data->tc->data[iter]; + if (td->flag & TD_SKIP) { + return; + } + transdata_elem_bevel_weight(data->t, data->tc, td, data->weight); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Transform (Bevel Weight) * \{ */ @@ -83,18 +128,25 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2])) } FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->val) { - *td->val = td->ival + weight * td->factor; - if (*td->val < 0.0f) { - *td->val = 0.0f; - } - if (*td->val > 1.0f) { - *td->val = 1.0f; + if (tc->data_len < TRANSDATA_THREAD_LIMIT) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; } + transdata_elem_bevel_weight(t, tc, td, weight); } } + else { + struct TransDataArgs_BevelWeight data = { + .t = t, + .tc = tc, + .weight = weight, + }; + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_bevel_weight_fn, &settings); + } } recalcData(t); diff --git a/source/blender/editors/transform/transform_mode_edge_crease.c b/source/blender/editors/transform/transform_mode_edge_crease.c index 23fa20b68ff..91e2507e544 100644 --- a/source/blender/editors/transform/transform_mode_edge_crease.c +++ b/source/blender/editors/transform/transform_mode_edge_crease.c @@ -25,6 +25,7 @@ #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_unit.h" @@ -40,6 +41,51 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ +/** \name Transform (Crease) Element + * \{ */ + +/** + * \note Small arrays / data-structures should be stored copied for faster memory access. + */ +struct TransDataArgs_Crease { + const TransInfo *t; + const TransDataContainer *tc; + float crease; +}; + +static void transdata_elem_crease(const TransInfo *UNUSED(t), + const TransDataContainer *UNUSED(tc), + TransData *td, + const float crease) +{ + if (td->val == NULL) { + return; + } + + *td->val = td->ival + crease * td->factor; + if (*td->val < 0.0f) { + *td->val = 0.0f; + } + if (*td->val > 1.0f) { + *td->val = 1.0f; + } +} + +static void transdata_elem_crease_fn(void *__restrict iter_data_v, + const int iter, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + struct TransDataArgs_Crease *data = iter_data_v; + TransData *td = &data->tc->data[iter]; + if (td->flag & TD_SKIP) { + return; + } + transdata_elem_crease(data->t, data->tc, td, data->crease); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Transform (Crease) * \{ */ @@ -83,22 +129,25 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2])) } FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_SKIP) { - continue; - } - - if (td->val) { - *td->val = td->ival + crease * td->factor; - if (*td->val < 0.0f) { - *td->val = 0.0f; - } - if (*td->val > 1.0f) { - *td->val = 1.0f; + if (tc->data_len < TRANSDATA_THREAD_LIMIT) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; } + transdata_elem_crease(t, tc, td, crease); } } + else { + struct TransDataArgs_Crease data = { + .t = t, + .tc = tc, + .crease = crease, + }; + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_crease_fn, &settings); + } } recalcData(t); @@ -124,4 +173,5 @@ void initCrease(TransInfo *t) t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } + /** \} */ diff --git a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c index b7b3de69731..6f2bcc148ce 100644 --- a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c +++ b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c @@ -103,7 +103,7 @@ static void applyNormalRotation(TransInfo *t, const int UNUSED(mval[2])) applyNumInput(&t->num, &angle); - headerRotation(t, str, angle); + headerRotation(t, str, sizeof(str), angle); axis_angle_normalized_to_mat3(mat, axis, angle); 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 4330d5e79be..a8f7fc43b5e 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -23,8 +23,10 @@ #include <stdlib.h> +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" #include "BLI_math.h" -#include "BLI_string.h" #include "BKE_context.h" #include "BKE_unit.h" @@ -37,6 +39,10 @@ #include "UI_interface.h" #include "UI_view2d.h" +#include "SEQ_iterator.h" +#include "SEQ_sequencer.h" +#include "SEQ_time.h" + #include "BLT_translation.h" #include "transform.h" @@ -72,7 +78,7 @@ static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRA BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]); } - ofs += BLI_snprintf( + ofs += BLI_snprintf_rlen( str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text); const wmKeyMapItem *kmi = t->custom.mode.data; @@ -80,10 +86,10 @@ static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRA ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs); } - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - TIP_(" or Alt) Expand to fit %s"), - WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0)); + ofs += BLI_snprintf_rlen(str + ofs, + UI_MAX_DRAW_STR - ofs, + TIP_(" or Alt) Expand to fit %s"), + WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0)); } static void applySeqSlideValue(TransInfo *t, const float val[2]) @@ -102,13 +108,11 @@ static void applySeqSlideValue(TransInfo *t, const float val[2]) } } -static void applySeqSlide(TransInfo *t, const int mval[2]) +static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2])) { char str[UI_MAX_DRAW_STR]; 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) { @@ -119,11 +123,14 @@ static void applySeqSlide(TransInfo *t, const int mval[2]) } } } - else if (t->con.mode & CON_APPLY) { - t->con.applyVec(t, NULL, NULL, t->values, values_final); - } else { copy_v2_v2(values_final, t->values); + applySnapping(t, values_final); + transform_convert_sequencer_channel_clamp(t, values_final); + + if (t->con.mode & CON_APPLY) { + t->con.applyVec(t, NULL, NULL, values_final, values_final); + } } values_final[0] = floorf(values_final[0] + 0.5f); @@ -142,6 +149,7 @@ void initSeqSlide(TransInfo *t) { t->transform = applySeqSlide; t->handleEvent = seq_slide_handleEvent; + t->tsnap.applySnap = transform_snap_sequencer_apply_translate; initMouseInputMode(t, &t->mouse, INPUT_VECTOR); @@ -164,4 +172,5 @@ void initSeqSlide(TransInfo *t) 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 16c1c05a6f8..066a2853dc7 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -107,7 +107,7 @@ static TransDataContainer *edge_slide_container_first_ok(TransInfo *t) return tc; } } - BLI_assert(!"Should never happen, at least one EdgeSlideData should be valid"); + BLI_assert_msg(0, "Should never happen, at least one EdgeSlideData should be valid"); return NULL; } @@ -375,8 +375,8 @@ static void calcEdgeSlide_mval_range(TransInfo *t, UNUSED_VARS_NDEBUG(sv_table); /* silence warning */ BLI_assert(i == sv_table[BM_elem_index_get(v)]); - /* search cross edges for visible edge to the mouse cursor, - * then use the shared vertex to calculate screen vector*/ + /* Search cross edges for visible edge to the mouse cursor, + * then use the shared vertex to calculate screen vector. */ BM_ITER_ELEM (e, &iter_other, v, BM_EDGES_OF_VERT) { /* screen-space coords */ float sco_a[3], sco_b[3]; @@ -540,7 +540,7 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo sld->curr_sv_index = 0; - /*ensure valid selection*/ + /* Ensure valid selection. */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { BMIter iter2; @@ -548,7 +548,7 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { /* BMESH_TODO: this is probably very evil, - * set v->e to a selected edge*/ + * set `v->e` to a selected edge. */ v->e = e; numsel++; @@ -565,7 +565,7 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - /* note, any edge with loops can work, but we won't get predictable results, so bail out */ + /* NOTE: any edge with loops can work, but we won't get predictable results, so bail out. */ if (!BM_edge_is_manifold(e) && !BM_edge_is_boundary(e)) { /* can edges with at least once face user */ MEM_freeN(sld); @@ -640,10 +640,10 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo v_first = v; - /*walk along the edge loop*/ + /* Walk along the edge loop. */ e = v->e; - /*first, rewind*/ + /* First, rewind. */ do { e = get_other_edge(v, e); if (!e) { @@ -709,7 +709,7 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo STACK_PUSH_RET_PTR(sv_array)) : \ (&sv_array[sv_table[BM_elem_index_get(v)]])) - /*iterate over the loop*/ + /* Iterate over the loop. */ v_first = v; do { bool l_a_ok_prev; @@ -818,7 +818,7 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo /* if there are non-contiguous faces, we can still recover * the loops of the new edges faces */ - /* note!, the behavior in this case means edges may move in opposite directions, + /* NOTE:, the behavior in this case means edges may move in opposite directions, * this could be made to work more usefully. */ if (l_a_ok_prev) { @@ -1220,7 +1220,7 @@ void drawEdgeSlide(TransInfo *t) immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); immBegin(GPU_PRIM_LINES, sld->totsv * 2); - /* TODO(campbell): Loop over all verts */ + /* TODO(campbell): Loop over all verts. */ sv = sld->sv; for (i = 0; i < sld->totsv; i++, sv++) { float a[3], b[3]; @@ -1482,15 +1482,15 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs); } else { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final); + ofs += BLI_snprintf_rlen(str + ofs, sizeof(str) - ofs, "%.4f ", final); } - ofs += BLI_snprintf( + ofs += BLI_snprintf_rlen( str + ofs, sizeof(str) - ofs, TIP_("(E)ven: %s, "), WM_bool_as_string(use_even)); if (use_even) { - ofs += BLI_snprintf( + ofs += BLI_snprintf_rlen( str + ofs, sizeof(str) - ofs, TIP_("(F)lipped: %s, "), WM_bool_as_string(flipped)); } - ofs += BLI_snprintf( + ofs += BLI_snprintf_rlen( str + ofs, sizeof(str) - ofs, TIP_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp)); /* done with header string */ diff --git a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c index 857ee37f0ad..cfbd6030788 100644 --- a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c @@ -89,7 +89,7 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) /* apply shrink/fatten */ FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; + TransData *td; for (td = tc->data, i = 0; i < tc->data_len; i++, td++) { if (td->flag & TD_SKIP) { continue; diff --git a/source/blender/editors/transform/transform_mode_push_pull.c b/source/blender/editors/transform/transform_mode_push_pull.c index 8a92978f33f..0492ec8df8c 100644 --- a/source/blender/editors/transform/transform_mode_push_pull.c +++ b/source/blender/editors/transform/transform_mode_push_pull.c @@ -25,6 +25,7 @@ #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_unit.h" @@ -41,12 +42,82 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ +/** \name Transform (Push/Pull) Element + * \{ */ + +/** + * \note Small arrays / data-structures should be stored copied for faster memory access. + */ +struct TransDataArgs_PushPull { + const TransInfo *t; + const TransDataContainer *tc; + + float distance; + const float axis_global[3]; + bool is_lock_constraint; + bool is_data_space; +}; + +static void transdata_elem_push_pull(const TransInfo *t, + const TransDataContainer *tc, + TransData *td, + const float distance, + const float axis_global[3], + const bool is_lock_constraint, + const bool is_data_space) +{ + float vec[3]; + sub_v3_v3v3(vec, tc->center_local, td->center); + if (t->con.applyRot && t->con.mode & CON_APPLY) { + float axis[3]; + copy_v3_v3(axis, axis_global); + t->con.applyRot(t, tc, td, axis, NULL); + + mul_m3_v3(td->smtx, axis); + if (is_lock_constraint) { + float dvec[3]; + project_v3_v3v3(dvec, vec, axis); + sub_v3_v3(vec, dvec); + } + else { + project_v3_v3v3(vec, vec, axis); + } + } + normalize_v3_length(vec, distance * td->factor); + if (is_data_space) { + mul_m3_v3(td->smtx, vec); + } + + add_v3_v3v3(td->loc, td->iloc, vec); +} + +static void transdata_elem_push_pull_fn(void *__restrict iter_data_v, + const int iter, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + struct TransDataArgs_PushPull *data = iter_data_v; + TransData *td = &data->tc->data[iter]; + if (td->flag & TD_SKIP) { + return; + } + transdata_elem_push_pull(data->t, + data->tc, + td, + data->distance, + data->axis_global, + data->is_lock_constraint, + data->is_data_space); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Transform (Push/Pull) * \{ */ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) { - float vec[3], axis_global[3]; + float axis_global[3]; float distance; int i; char str[UI_MAX_DRAW_STR]; @@ -77,32 +148,31 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) t->con.applyRot(t, NULL, NULL, axis_global, NULL); } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_SKIP) { - continue; - } + const bool is_lock_constraint = isLockConstraint(t); + const bool is_data_space = (t->options & CTX_POSE_BONE) != 0; - sub_v3_v3v3(vec, tc->center_local, td->center); - if (t->con.applyRot && t->con.mode & CON_APPLY) { - float axis[3]; - copy_v3_v3(axis, axis_global); - t->con.applyRot(t, tc, td, axis, NULL); - - mul_m3_v3(td->smtx, axis); - if (isLockConstraint(t)) { - float dvec[3]; - project_v3_v3v3(dvec, vec, axis); - sub_v3_v3(vec, dvec); - } - else { - project_v3_v3v3(vec, vec, axis); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + if (tc->data_len < TRANSDATA_THREAD_LIMIT) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; } + transdata_elem_push_pull( + t, tc, td, distance, axis_global, is_lock_constraint, is_data_space); } - normalize_v3_length(vec, distance * td->factor); - - add_v3_v3v3(td->loc, td->iloc, vec); + } + else { + struct TransDataArgs_PushPull data = { + .t = t, + .tc = tc, + .axis_global = {UNPACK3(axis_global)}, + .is_lock_constraint = is_lock_constraint, + .is_data_space = is_data_space, + }; + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_push_pull_fn, &settings); } } diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c index 0d7d0be3c0e..65f4623b3be 100644 --- a/source/blender/editors/transform/transform_mode_resize.c +++ b/source/blender/editors/transform/transform_mode_resize.c @@ -24,6 +24,7 @@ #include <stdlib.h> #include "BLI_math.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_unit.h" @@ -39,6 +40,30 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ +/** \name Transform (Resize) Element + * \{ */ + +struct ElemResizeData { + const TransInfo *t; + const TransDataContainer *tc; + float mat[3][3]; +}; + +static void element_resize_fn(void *__restrict iter_data_v, + const int iter, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + struct ElemResizeData *data = iter_data_v; + TransData *td = &data->tc->data[iter]; + if (td->flag & TD_SKIP) { + return; + } + ElementResize(data->t, data->tc, td, data->mat); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Transform (Resize) * \{ */ @@ -88,6 +113,7 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2])) float ratio = t->values[0]; copy_v3_fl(t->values_final, ratio); + add_v3_v3(t->values_final, t->values_modal_offset); transform_snap_increment(t, t->values_final); @@ -113,22 +139,36 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2])) pvec[j++] = t->values_final[i]; } } - headerResize(t, pvec, str); + headerResize(t, pvec, str, sizeof(str)); } else { - headerResize(t, t->values_final, str); + headerResize(t, t->values_final, str, sizeof(str)); } copy_m3_m3(t->mat, mat); /* used in gizmo */ FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_SKIP) { - continue; - } - ElementResize(t, tc, td, mat); + if (tc->data_len < TRANSDATA_THREAD_LIMIT) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; + } + + ElementResize(t, tc, td, mat); + } + } + else { + struct ElemResizeData data = { + .t = t, + .tc = tc, + }; + copy_m3_m3(data.mat, mat); + + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + BLI_task_parallel_range(0, tc->data_len, &data, element_resize_fn, &settings); } } diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c index 0fdbfb25989..44a29cfac45 100644 --- a/source/blender/editors/transform/transform_mode_rotate.c +++ b/source/blender/editors/transform/transform_mode_rotate.c @@ -24,6 +24,7 @@ #include <stdlib.h> #include "BLI_math.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_unit.h" @@ -37,6 +38,140 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ +/** \name Transform (Rotation) Matrix Cache + * \{ */ + +struct RotateMatrixCache { + /** + * Counter for needed updates (when we need to update to non-default matrix, + * we also need another update on next iteration to go back to default matrix, + * hence the '2' value used here, instead of a mere boolean). + */ + short do_update_matrix; + float mat[3][3]; +}; + +static void rmat_cache_init(struct RotateMatrixCache *rmc, const float angle, const float axis[3]) +{ + axis_angle_normalized_to_mat3(rmc->mat, axis, angle); + rmc->do_update_matrix = 0; +} + +static void rmat_cache_reset(struct RotateMatrixCache *rmc) +{ + rmc->do_update_matrix = 2; +} + +static void rmat_cache_update(struct RotateMatrixCache *rmc, + const float axis[3], + const float angle) +{ + if (rmc->do_update_matrix > 0) { + axis_angle_normalized_to_mat3(rmc->mat, axis, angle); + rmc->do_update_matrix--; + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform (Rotation) Element + * \{ */ + +/** + * \note Small arrays / data-structures should be stored copied for faster memory access. + */ +struct TransDataArgs_Rotate { + const TransInfo *t; + const TransDataContainer *tc; + const float axis[3]; + float angle; + float angle_step; + bool is_large_rotation; +}; + +struct TransDataArgs_RotateTLS { + struct RotateMatrixCache rmc; +}; + +static void transdata_elem_rotate(const TransInfo *t, + const TransDataContainer *tc, + TransData *td, + const float axis[3], + const float angle, + const float angle_step, + const bool is_large_rotation, + struct RotateMatrixCache *rmc) +{ + float axis_buffer[3]; + const float *axis_final = axis; + + float angle_final = angle; + if (t->con.applyRot) { + copy_v3_v3(axis_buffer, axis); + axis_final = axis_buffer; + t->con.applyRot(t, tc, td, axis_buffer, NULL); + angle_final = angle * td->factor; + /* Even though final angle might be identical to orig value, + * we have to update the rotation matrix in that case... */ + rmat_cache_reset(rmc); + } + else if (t->flag & T_PROP_EDIT) { + angle_final = angle * td->factor; + } + + /* Rotation is very likely to be above 180°, we need to do rotation by steps. + * Note that this is only needed when doing 'absolute' rotation + * (i.e. from initial rotation again, typically when using numinput). + * regular incremental rotation (from mouse/widget/...) will be called often enough, + * hence steps are small enough to be properly handled without that complicated trick. + * Note that we can only do that kind of stepped rotation if we have initial rotation values + * (and access to some actual rotation value storage). + * Otherwise, just assume it's useless (e.g. in case of mesh/UV/etc. editing). + * Also need to be in Euler rotation mode, the others never allow more than one turn anyway. + */ + if (is_large_rotation && td->ext != NULL && td->ext->rotOrder == ROT_MODE_EUL) { + copy_v3_v3(td->ext->rot, td->ext->irot); + for (float angle_progress = angle_step; fabsf(angle_progress) < fabsf(angle_final); + angle_progress += angle_step) { + axis_angle_normalized_to_mat3(rmc->mat, axis_final, angle_progress); + ElementRotation(t, tc, td, rmc->mat, t->around); + } + rmat_cache_reset(rmc); + } + else if (angle_final != angle) { + rmat_cache_reset(rmc); + } + + rmat_cache_update(rmc, axis_final, angle_final); + + ElementRotation(t, tc, td, rmc->mat, t->around); +} + +static void transdata_elem_rotate_fn(void *__restrict iter_data_v, + const int iter, + const TaskParallelTLS *__restrict tls) +{ + struct TransDataArgs_Rotate *data = iter_data_v; + struct TransDataArgs_RotateTLS *tls_data = tls->userdata_chunk; + + TransData *td = &data->tc->data[iter]; + if (td->flag & TD_SKIP) { + return; + } + transdata_elem_rotate(data->t, + data->tc, + td, + data->axis, + data->angle, + data->angle_step, + data->is_large_rotation, + &tls_data->rmc); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Transform (Rotation) * \{ */ @@ -115,12 +250,9 @@ static float large_rotation_limit(float angle) static void applyRotationValue(TransInfo *t, float angle, - float axis[3], + const float axis[3], const bool is_large_rotation) { - float mat[3][3]; - int i; - const float angle_sign = angle < 0.0f ? -1.0f : 1.0f; /* We cannot use something too close to 180°, or 'continuous' rotation may fail * due to computing error... */ @@ -132,60 +264,37 @@ static void applyRotationValue(TransInfo *t, angle = large_rotation_limit(angle); } - axis_angle_normalized_to_mat3(mat, axis, angle); - /* Counter for needed updates (when we need to update to non-default matrix, - * we also need another update on next iteration to go back to default matrix, - * hence the '2' value used here, instead of a mere boolean). */ - short do_update_matrix = 0; + struct RotateMatrixCache rmc = {0}; + rmat_cache_init(&rmc, angle, axis); FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_SKIP) { - continue; - } - - float angle_final = angle; - if (t->con.applyRot) { - t->con.applyRot(t, tc, td, axis, NULL); - angle_final = angle * td->factor; - /* Even though final angle might be identical to orig value, - * we have to update the rotation matrix in that case... */ - do_update_matrix = 2; - } - else if (t->flag & T_PROP_EDIT) { - angle_final = angle * td->factor; - } - - /* Rotation is very likely to be above 180°, we need to do rotation by steps. - * Note that this is only needed when doing 'absolute' rotation - * (i.e. from initial rotation again, typically when using numinput). - * regular incremental rotation (from mouse/widget/...) will be called often enough, - * hence steps are small enough to be properly handled without that complicated trick. - * Note that we can only do that kind of stepped rotation if we have initial rotation values - * (and access to some actual rotation value storage). - * Otherwise, just assume it's useless (e.g. in case of mesh/UV/etc. editing). - * Also need to be in Euler rotation mode, the others never allow more than one turn anyway. - */ - if (is_large_rotation && td->ext != NULL && td->ext->rotOrder == ROT_MODE_EUL) { - copy_v3_v3(td->ext->rot, td->ext->irot); - for (float angle_progress = angle_step; fabsf(angle_progress) < fabsf(angle_final); - angle_progress += angle_step) { - axis_angle_normalized_to_mat3(mat, axis, angle_progress); - ElementRotation(t, tc, td, mat, t->around); + if (tc->data_len < TRANSDATA_THREAD_LIMIT) { + TransData *td = tc->data; + for (int i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; } - do_update_matrix = 2; + transdata_elem_rotate(t, tc, td, axis, angle, angle_step, is_large_rotation, &rmc); } - else if (angle_final != angle) { - do_update_matrix = 2; - } - - if (do_update_matrix > 0) { - axis_angle_normalized_to_mat3(mat, axis, angle_final); - do_update_matrix--; - } - - ElementRotation(t, tc, td, mat, t->around); + } + else { + struct TransDataArgs_Rotate data = { + .t = t, + .tc = tc, + .axis = {UNPACK3(axis)}, + .angle = angle, + .angle_step = angle_step, + .is_large_rotation = is_large_rotation, + }; + struct TransDataArgs_RotateTLS tls_data = { + .rmc = rmc, + }; + + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.userdata_chunk = &tls_data; + settings.userdata_chunk_size = sizeof(tls_data); + BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_rotate_fn, &settings); } } } @@ -194,7 +303,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) { char str[UI_MAX_DRAW_STR]; float axis_final[3]; - float final = t->values[0]; + float final = t->values[0] + t->values_modal_offset[0]; if ((t->con.mode & CON_APPLY) && t->con.applyRot) { t->con.applyRot(t, NULL, NULL, axis_final, &final); @@ -217,7 +326,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) t->values_final[0] = final; - headerRotation(t, str, final); + headerRotation(t, str, sizeof(str), final); const bool is_large_rotation = hasNumInput(&t->num); applyRotationValue(t, final, axis_final, is_large_rotation); diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c index 23ee55bf6c5..f5672887905 100644 --- a/source/blender/editors/transform/transform_mode_shear.c +++ b/source/blender/editors/transform/transform_mode_shear.c @@ -27,6 +27,7 @@ #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_unit.h" @@ -44,6 +45,79 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ +/** \name Transform (Shear) Element + * \{ */ + +/** + * \note Small arrays / data-structures should be stored copied for faster memory access. + */ +struct TransDataArgs_Shear { + const TransInfo *t; + const TransDataContainer *tc; + float mat_final[3][3]; + bool is_local_center; +}; + +static void transdata_elem_shear(const TransInfo *t, + const TransDataContainer *tc, + TransData *td, + const float mat_final[3][3], + const bool is_local_center) +{ + float tmat[3][3]; + const float *center; + if (t->flag & T_EDIT) { + mul_m3_series(tmat, td->smtx, mat_final, td->mtx); + } + else { + copy_m3_m3(tmat, mat_final); + } + + if (is_local_center) { + center = td->center; + } + else { + center = tc->center_local; + } + + float vec[3]; + sub_v3_v3v3(vec, td->iloc, center); + mul_m3_v3(tmat, vec); + add_v3_v3(vec, center); + sub_v3_v3(vec, td->iloc); + + if (t->options & CTX_GPENCIL_STROKES) { + /* Grease pencil multi-frame falloff. */ + bGPDstroke *gps = (bGPDstroke *)td->extra; + if (gps != NULL) { + mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff); + } + else { + mul_v3_fl(vec, td->factor); + } + } + else { + mul_v3_fl(vec, td->factor); + } + + add_v3_v3v3(td->loc, td->iloc, vec); +} + +static void transdata_elem_shear_fn(void *__restrict iter_data_v, + const int iter, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + struct TransDataArgs_Shear *data = iter_data_v; + TransData *td = &data->tc->data[iter]; + if (td->flag & TD_SKIP) { + return; + } + transdata_elem_shear(data->t, data->tc, td, data->mat_final, data->is_local_center); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Transform (Shear) * \{ */ @@ -117,8 +191,7 @@ static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event) static void applyShear(TransInfo *t, const int UNUSED(mval[2])) { - float vec[3]; - float smat[3][3], tmat[3][3], totmat[3][3], axismat[3][3], axismat_inv[3][3]; + float smat[3][3], axismat[3][3], axismat_inv[3][3], mat_final[3][3]; float value; int i; char str[UI_MAX_DRAW_STR]; @@ -157,50 +230,29 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2])) cross_v3_v3v3(axismat_inv[1], axismat_inv[0], axismat_inv[2]); invert_m3_m3(axismat, axismat_inv); - mul_m3_series(totmat, axismat_inv, smat, axismat); + mul_m3_series(mat_final, axismat_inv, smat, axismat); FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - const float *center; - if (td->flag & TD_SKIP) { - continue; - } - - if (t->flag & T_EDIT) { - mul_m3_series(tmat, td->smtx, totmat, td->mtx); - } - else { - copy_m3_m3(tmat, totmat); - } - - if (is_local_center) { - center = td->center; - } - else { - center = tc->center_local; - } - - sub_v3_v3v3(vec, td->iloc, center); - mul_m3_v3(tmat, vec); - add_v3_v3(vec, center); - sub_v3_v3(vec, td->iloc); - - if (t->options & CTX_GPENCIL_STROKES) { - /* grease pencil multiframe falloff */ - bGPDstroke *gps = (bGPDstroke *)td->extra; - if (gps != NULL) { - mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff); - } - else { - mul_v3_fl(vec, td->factor); + if (tc->data_len < TRANSDATA_THREAD_LIMIT) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; } + transdata_elem_shear(t, tc, td, mat_final, is_local_center); } - else { - mul_v3_fl(vec, td->factor); - } - - add_v3_v3v3(td->loc, td->iloc, vec); + } + else { + struct TransDataArgs_Shear data = { + .t = t, + .tc = tc, + .is_local_center = is_local_center, + }; + copy_m3_m3(data.mat_final, mat_final); + + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_shear_fn, &settings); } } diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c index 6e497d85417..4cdaab599b4 100644 --- a/source/blender/editors/transform/transform_mode_shrink_fatten.c +++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c @@ -25,6 +25,7 @@ #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_unit.h" @@ -43,6 +44,47 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ +/** \name Transform (Shrink-Fatten) Element + * \{ */ + +/** + * \note Small arrays / data-structures should be stored copied for faster memory access. + */ +struct TransDataArgs_ShrinkFatten { + const TransInfo *t; + const TransDataContainer *tc; + float distance; +}; + +static void transdata_elem_shrink_fatten(const TransInfo *t, + const TransDataContainer *UNUSED(tc), + TransData *td, + const float distance) +{ + /* Get the final offset. */ + float tdistance = distance * td->factor; + if (td->ext && (t->flag & T_ALT_TRANSFORM) != 0) { + tdistance *= td->ext->isize[0]; /* shell factor */ + } + + madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance); +} + +static void transdata_elem_shrink_fatten_fn(void *__restrict iter_data_v, + const int iter, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + struct TransDataArgs_ShrinkFatten *data = iter_data_v; + TransData *td = &data->tc->data[iter]; + if (td->flag & TD_SKIP) { + return; + } + transdata_elem_shrink_fatten(data->t, data->tc, td, data->distance); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Transform (Shrink-Fatten) * \{ */ @@ -79,7 +121,7 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c, unit); - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%s", c); + ofs += BLI_snprintf_rlen(str + ofs, sizeof(str) - ofs, "%s", c); } else { /* default header print */ @@ -93,12 +135,12 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) true); } else { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f", distance); + ofs += BLI_snprintf_rlen(str + ofs, sizeof(str) - ofs, "%.4f", distance); } } if (t->proptext[0]) { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", t->proptext); + ofs += BLI_snprintf_rlen(str + ofs, sizeof(str) - ofs, " %s", t->proptext); } ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs); @@ -114,20 +156,24 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) /* done with header string */ FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - float tdistance; /* temp dist */ - if (td->flag & TD_SKIP) { - continue; + if (tc->data_len < TRANSDATA_THREAD_LIMIT) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; + } + transdata_elem_shrink_fatten(t, tc, td, distance); } - - /* get the final offset */ - tdistance = distance * td->factor; - if (td->ext && (t->flag & T_ALT_TRANSFORM) != 0) { - tdistance *= td->ext->isize[0]; /* shell factor */ - } - - madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance); + } + else { + struct TransDataArgs_ShrinkFatten data = { + .t = t, + .tc = tc, + .distance = distance, + }; + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_shrink_fatten_fn, &settings); } } diff --git a/source/blender/editors/transform/transform_mode_skin_resize.c b/source/blender/editors/transform/transform_mode_skin_resize.c index 77e57484bef..0a7eea8a989 100644 --- a/source/blender/editors/transform/transform_mode_skin_resize.c +++ b/source/blender/editors/transform/transform_mode_skin_resize.c @@ -24,6 +24,7 @@ #include <stdlib.h> #include "BLI_math.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_unit.h" @@ -38,12 +39,64 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ +/** \name Transform (Skin) Element + * \{ */ + +/** + * \note Small arrays / data-structures should be stored copied for faster memory access. + */ +struct TransDataArgs_SkinResize { + const TransInfo *t; + const TransDataContainer *tc; + float mat_final[3][3]; +}; + +static void transdata_elem_skin_resize(const TransInfo *t, + const TransDataContainer *UNUSED(tc), + TransData *td, + const float mat[3][3]) +{ + float tmat[3][3], smat[3][3]; + float fsize[3]; + + if (t->flag & T_EDIT) { + mul_m3_m3m3(smat, mat, td->mtx); + mul_m3_m3m3(tmat, td->smtx, smat); + } + else { + copy_m3_m3(tmat, mat); + } + + if (t->con.applySize) { + t->con.applySize(t, NULL, NULL, tmat); + } + + mat3_to_size(fsize, tmat); + td->loc[0] = td->iloc[0] * (1 + (fsize[0] - 1) * td->factor); + td->loc[1] = td->iloc[1] * (1 + (fsize[1] - 1) * td->factor); +} + +static void transdata_elem_skin_resize_fn(void *__restrict iter_data_v, + const int iter, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + struct TransDataArgs_SkinResize *data = iter_data_v; + TransData *td = &data->tc->data[iter]; + if (td->flag & TD_SKIP) { + return; + } + transdata_elem_skin_resize(data->t, data->tc, td, data->mat_final); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Transform (Skin) * \{ */ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) { - float mat[3][3]; + float mat_final[3][3]; int i; char str[UI_MAX_DRAW_STR]; @@ -62,34 +115,29 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) applySnapping(t, t->values_final); } - size_to_mat3(mat, t->values_final); + size_to_mat3(mat_final, t->values_final); - headerResize(t, t->values_final, str); + headerResize(t, t->values_final, str, sizeof(str)); FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - float tmat[3][3], smat[3][3]; - float fsize[3]; - if (td->flag & TD_SKIP) { - continue; + if (tc->data_len < TRANSDATA_THREAD_LIMIT) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; + } + transdata_elem_skin_resize(t, tc, td, mat_final); } - - if (t->flag & T_EDIT) { - mul_m3_m3m3(smat, mat, td->mtx); - mul_m3_m3m3(tmat, td->smtx, smat); - } - else { - copy_m3_m3(tmat, mat); - } - - if (t->con.applySize) { - t->con.applySize(t, NULL, NULL, tmat); - } - - mat3_to_size(fsize, tmat); - td->loc[0] = td->iloc[0] * (1 + (fsize[0] - 1) * td->factor); - td->loc[1] = td->iloc[1] * (1 + (fsize[1] - 1) * td->factor); + } + else { + struct TransDataArgs_SkinResize data = { + .t = t, + .tc = tc, + }; + copy_m3_m3(data.mat_final, mat_final); + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_skin_resize_fn, &settings); } } diff --git a/source/blender/editors/transform/transform_mode_timetranslate.c b/source/blender/editors/transform/transform_mode_timetranslate.c index 5ad6d04b4de..948242e547f 100644 --- a/source/blender/editors/transform/transform_mode_timetranslate.c +++ b/source/blender/editors/transform/transform_mode_timetranslate.c @@ -76,10 +76,10 @@ static void headerTimeTranslate(TransInfo *t, char str[UI_MAX_DRAW_STR]) } } - ofs += BLI_snprintf(str, UI_MAX_DRAW_STR, TIP_("DeltaX: %s"), &tvec[0]); + ofs += BLI_snprintf_rlen(str, UI_MAX_DRAW_STR, TIP_("DeltaX: %s"), &tvec[0]); if (t->flag & T_PROP_EDIT_ALL) { - ofs += BLI_snprintf( + ofs += BLI_snprintf_rlen( str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" Proportional size: %.2f"), t->prop_size); } } diff --git a/source/blender/editors/transform/transform_mode_tosphere.c b/source/blender/editors/transform/transform_mode_tosphere.c index 15906f2c90c..8587d5ae140 100644 --- a/source/blender/editors/transform/transform_mode_tosphere.c +++ b/source/blender/editors/transform/transform_mode_tosphere.c @@ -25,6 +25,7 @@ #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_task.h" #include "MEM_guardedalloc.h" @@ -55,8 +56,10 @@ static void to_sphere_radius_update(TransInfo *t) { struct ToSphereInfo *data = t->custom.mode.data; float radius = 0.0f; + float vec[3]; const bool is_local_center = transdata_check_local_center(t, t->around); + const bool is_data_space = (t->options & CTX_POSE_BONE) != 0; if (t->flag & T_PROP_EDIT_ALL) { int factor_accum = 0.0f; @@ -67,7 +70,15 @@ static void to_sphere_radius_update(TransInfo *t) continue; } const float *center = is_local_center ? td->center : tc->center_local; - radius += td->factor * len_v3v3(center, td->iloc); + if (is_data_space) { + copy_v3_v3(vec, td->center); + } + else { + copy_v3_v3(vec, td->iloc); + } + + sub_v3_v3(vec, center); + radius += td->factor * len_v3(vec); factor_accum += td->factor; } } @@ -80,7 +91,15 @@ static void to_sphere_radius_update(TransInfo *t) TransData *td = tc->data; for (int i = 0; i < tc->data_len; i++, td++) { const float *center = is_local_center ? td->center : tc->center_local; - radius += len_v3v3(center, td->iloc); + if (is_data_space) { + copy_v3_v3(vec, td->center); + } + else { + copy_v3_v3(vec, td->iloc); + } + + sub_v3_v3(vec, center); + radius += len_v3(vec); } } radius /= (float)t->data_len_all; @@ -93,15 +112,83 @@ static void to_sphere_radius_update(TransInfo *t) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Transform (ToSphere) Element + * \{ */ + +/** + * \note Small arrays / data-structures should be stored copied for faster memory access. + */ +struct TransDataArgs_ToSphere { + const TransInfo *t; + const TransDataContainer *tc; + float ratio; + const struct ToSphereInfo to_sphere_info; + bool is_local_center; + bool is_data_space; +}; + +static void transdata_elem_to_sphere(const TransInfo *UNUSED(t), + const TransDataContainer *tc, + TransData *td, + const float ratio, + const struct ToSphereInfo *to_sphere_info, + const bool is_local_center, + const bool is_data_space) +{ + float vec[3]; + const float *center = is_local_center ? td->center : tc->center_local; + if (is_data_space) { + copy_v3_v3(vec, td->center); + } + else { + copy_v3_v3(vec, td->iloc); + } + + sub_v3_v3(vec, center); + const float radius = normalize_v3(vec); + const float tratio = ratio * td->factor; + mul_v3_fl(vec, radius * (1.0f - tratio) + to_sphere_info->radius * tratio); + add_v3_v3(vec, center); + + if (is_data_space) { + sub_v3_v3(vec, td->center); + mul_m3_v3(td->smtx, vec); + add_v3_v3(vec, td->iloc); + } + + copy_v3_v3(td->loc, vec); +} + +static void transdata_elem_to_sphere_fn(void *__restrict iter_data_v, + const int iter, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + struct TransDataArgs_ToSphere *data = iter_data_v; + TransData *td = &data->tc->data[iter]; + if (td->flag & TD_SKIP) { + return; + } + transdata_elem_to_sphere(data->t, + data->tc, + td, + data->ratio, + &data->to_sphere_info, + data->is_local_center, + data->is_data_space); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Transform (ToSphere) * \{ */ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2])) { const bool is_local_center = transdata_check_local_center(t, t->around); + const bool is_data_space = (t->options & CTX_POSE_BONE) != 0; - float vec[3]; - float ratio, radius; + float ratio; int i; char str[UI_MAX_DRAW_STR]; @@ -128,30 +215,33 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2])) BLI_snprintf(str, sizeof(str), TIP_("To Sphere: %.4f %s"), ratio, t->proptext); } - const struct ToSphereInfo *data = t->custom.mode.data; - if (data->prop_size_prev != t->prop_size) { + const struct ToSphereInfo *to_sphere_info = t->custom.mode.data; + if (to_sphere_info->prop_size_prev != t->prop_size) { to_sphere_radius_update(t); } FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - float tratio; - if (td->flag & TD_SKIP) { - continue; + if (tc->data_len < TRANSDATA_THREAD_LIMIT) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; + } + transdata_elem_to_sphere(t, tc, td, ratio, to_sphere_info, is_local_center, is_data_space); } - - const float *center = is_local_center ? td->center : tc->center_local; - - sub_v3_v3v3(vec, td->iloc, center); - - radius = normalize_v3(vec); - - tratio = ratio * td->factor; - - mul_v3_fl(vec, radius * (1.0f - tratio) + data->radius * tratio); - - add_v3_v3v3(td->loc, center, vec); + } + else { + struct TransDataArgs_ToSphere data = { + .t = t, + .tc = tc, + .ratio = ratio, + .to_sphere_info = *to_sphere_info, + .is_local_center = is_local_center, + .is_data_space = is_data_space, + }; + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_to_sphere_fn, &settings); } } diff --git a/source/blender/editors/transform/transform_mode_trackball.c b/source/blender/editors/transform/transform_mode_trackball.c index 5a57a69f986..68177c6becf 100644 --- a/source/blender/editors/transform/transform_mode_trackball.c +++ b/source/blender/editors/transform/transform_mode_trackball.c @@ -25,6 +25,7 @@ #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_unit.h" @@ -40,6 +41,51 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ +/** \name Transform (Rotation - Trackball) Element + * \{ */ + +/** + * \note Small arrays / data-structures should be stored copied for faster memory access. + */ +struct TransDataArgs_Trackball { + const TransInfo *t; + const TransDataContainer *tc; + const float axis[3]; + const float angle; + float mat_final[3][3]; +}; + +static void transdata_elem_trackball(const TransInfo *t, + const TransDataContainer *tc, + TransData *td, + const float axis[3], + const float angle, + const float mat_final[3][3]) +{ + float mat_buf[3][3]; + const float(*mat)[3] = mat_final; + if (t->flag & T_PROP_EDIT) { + axis_angle_normalized_to_mat3(mat_buf, axis, td->factor * angle); + mat = mat_buf; + } + ElementRotation(t, tc, td, mat, t->around); +} + +static void transdata_elem_trackball_fn(void *__restrict iter_data_v, + const int iter, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + struct TransDataArgs_Trackball *data = iter_data_v; + TransData *td = &data->tc->data[iter]; + if (td->flag & TD_SKIP) { + return; + } + transdata_elem_trackball(data->t, data->tc, td, data->axis, data->angle, data->mat_final); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Transform (Rotation - Trackball) * \{ */ @@ -48,7 +94,7 @@ static void applyTrackballValue(TransInfo *t, const float axis2[3], const float angles[2]) { - float mat[3][3]; + float mat_final[3][3]; float axis[3]; float angle; int i; @@ -56,20 +102,30 @@ static void applyTrackballValue(TransInfo *t, mul_v3_v3fl(axis, axis1, angles[0]); madd_v3_v3fl(axis, axis2, angles[1]); angle = normalize_v3(axis); - axis_angle_normalized_to_mat3(mat, axis, angle); + axis_angle_normalized_to_mat3(mat_final, axis, angle); FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_SKIP) { - continue; + if (tc->data_len < TRANSDATA_THREAD_LIMIT) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; + } + transdata_elem_trackball(t, tc, td, axis, angle, mat_final); } - - if (t->flag & T_PROP_EDIT) { - axis_angle_normalized_to_mat3(mat, axis, td->factor * angle); - } - - ElementRotation(t, tc, td, mat, t->around); + } + else { + struct TransDataArgs_Trackball data = { + .t = t, + .tc = tc, + .axis = {UNPACK3(axis)}, + .angle = angle, + }; + copy_m3_m3(data.mat_final, mat_final); + + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_trackball_fn, &settings); } } } @@ -102,24 +158,24 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c, &t->scene->unit); - ofs += BLI_snprintf(str + ofs, - sizeof(str) - ofs, - TIP_("Trackball: %s %s %s"), - &c[0], - &c[NUM_STR_REP_LEN], - t->proptext); + ofs += BLI_snprintf_rlen(str + ofs, + sizeof(str) - ofs, + TIP_("Trackball: %s %s %s"), + &c[0], + &c[NUM_STR_REP_LEN], + t->proptext); } else { - ofs += BLI_snprintf(str + ofs, - sizeof(str) - ofs, - TIP_("Trackball: %.2f %.2f %s"), - RAD2DEGF(phi[0]), - RAD2DEGF(phi[1]), - t->proptext); + ofs += BLI_snprintf_rlen(str + ofs, + sizeof(str) - ofs, + TIP_("Trackball: %.2f %.2f %s"), + RAD2DEGF(phi[0]), + RAD2DEGF(phi[1]), + t->proptext); } if (t->flag & T_PROP_EDIT_ALL) { - ofs += BLI_snprintf( + ofs += BLI_snprintf_rlen( str + ofs, sizeof(str) - ofs, TIP_(" Proportional size: %.2f"), t->prop_size); } diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 0bef6364214..2cbf52b6100 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -29,6 +29,7 @@ #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_report.h" @@ -49,15 +50,164 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ +/** \name Transform (Translate) Custom Data + * \{ */ + +/** Rotation may be enabled when snapping. */ +enum eTranslateRotateMode { + /** Don't rotate (default). */ + TRANSLATE_ROTATE_OFF = 0, + /** Perform rotation (currently only snap to normal is used). */ + TRANSLATE_ROTATE_ON, + /** Rotate, resetting back to the disabled state. */ + TRANSLATE_ROTATE_RESET, +}; + +/** + * Custom data, stored in #TransInfo.custom.mode.data + */ +struct TranslateCustomData { + /** Settings used in the last call to #applyTranslation. */ + struct { + enum eTranslateRotateMode rotate_mode; + } prev; +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform (Translation) Element + * \{ */ + +/** + * \note Small arrays / data-structures should be stored copied for faster memory access. + */ +struct TransDataArgs_Translate { + const TransInfo *t; + const TransDataContainer *tc; + const float pivot_local[3]; + const float vec[3]; + enum eTranslateRotateMode rotate_mode; +}; + +static void transdata_elem_translate(const TransInfo *t, + const TransDataContainer *tc, + TransData *td, + const float pivot_local[3], + const float vec[3], + enum eTranslateRotateMode rotate_mode) +{ + float rotate_offset[3] = {0}; + bool use_rotate_offset = false; + + /* Handle snapping rotation before doing the translation. */ + if (rotate_mode != TRANSLATE_ROTATE_OFF) { + float mat[3][3]; + + if (rotate_mode == TRANSLATE_ROTATE_RESET) { + unit_m3(mat); + } + else { + BLI_assert(rotate_mode == TRANSLATE_ROTATE_ON); + + const float *original_normal; + + /* In pose mode, we want to align normals with Y axis of bones. */ + if (t->options & CTX_POSE_BONE) { + original_normal = td->axismtx[1]; + } + else { + original_normal = td->axismtx[2]; + } + + rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal); + } + + ElementRotation_ex(t, tc, td, mat, pivot_local); + + if (td->loc) { + use_rotate_offset = true; + sub_v3_v3v3(rotate_offset, td->loc, td->iloc); + } + } + + float tvec[3]; + + if (t->con.applyVec) { + t->con.applyVec(t, tc, td, vec, tvec); + } + else { + copy_v3_v3(tvec, vec); + } + + mul_m3_v3(td->smtx, tvec); + + if (use_rotate_offset) { + add_v3_v3(tvec, rotate_offset); + } + + if (t->options & CTX_GPENCIL_STROKES) { + /* Grease pencil multi-frame falloff. */ + bGPDstroke *gps = (bGPDstroke *)td->extra; + if (gps != NULL) { + mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff); + } + else { + mul_v3_fl(tvec, td->factor); + } + } + else { + /* Proportional editing falloff. */ + mul_v3_fl(tvec, td->factor); + } + + protectedTransBits(td->protectflag, tvec); + + if (td->loc) { + add_v3_v3v3(td->loc, td->iloc, tvec); + } + + constraintTransLim(t, td); +} + +static void transdata_elem_translate_fn(void *__restrict iter_data_v, + const int iter, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + struct TransDataArgs_Translate *data = iter_data_v; + TransData *td = &data->tc->data[iter]; + if (td->flag & TD_SKIP) { + return; + } + transdata_elem_translate(data->t, data->tc, td, data->pivot_local, data->vec, data->rotate_mode); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Transform (Translation) * \{ */ +static void translate_dist_to_str(char *r_str, + const int len_max, + const float val, + const UnitSettings *unit) +{ + if (unit) { + BKE_unit_value_as_string( + r_str, len_max, val * unit->scale_length, 4, B_UNIT_LENGTH, unit, false); + } + else { + /* Check range to prevent string buffer overflow. */ + BLI_snprintf(r_str, len_max, IN_RANGE_INCL(val, -1e10f, 1e10f) ? "%.4f" : "%.4e", val); + } +} + static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR]) { size_t ofs = 0; - char tvec[NUM_STR_REP_LEN * 3]; - char distvec[NUM_STR_REP_LEN]; - char autoik[NUM_STR_REP_LEN]; + char dvec_str[3][NUM_STR_REP_LEN]; + char dist_str[NUM_STR_REP_LEN]; float dist; UnitSettings *unit = NULL; @@ -66,7 +216,7 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ } if (hasNumInput(&t->num)) { - outputNumInput(&(t->num), tvec, &t->scene->unit); + outputNumInput(&(t->num), dvec_str[0], &t->scene->unit); dist = len_v3(t->num.val); } else { @@ -94,117 +244,82 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ dist = len_v3(dvec); - if (unit) { - for (int i = 0; i < 3; i++) { - BKE_unit_value_as_string(&tvec[NUM_STR_REP_LEN * i], - NUM_STR_REP_LEN, - dvec[i] * unit->scale_length, - 4, - B_UNIT_LENGTH, - unit, - true); - } - } - else { - BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", dvec[0]); - BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", dvec[1]); - BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", dvec[2]); + for (int i = 0; i < 3; i++) { + translate_dist_to_str(dvec_str[i], sizeof(dvec_str[i]), dvec[i], unit); } } - if (unit) { - BKE_unit_value_as_string( - distvec, sizeof(distvec), dist * unit->scale_length, 4, B_UNIT_LENGTH, unit, false); - } - else if (dist > 1e10f || dist < -1e10f) { - /* prevent string buffer overflow */ - BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist); - } - else { - BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4f", dist); + translate_dist_to_str(dist_str, sizeof(dist_str), dist, unit); + + if (t->flag & T_PROP_EDIT_ALL) { + char prop_str[NUM_STR_REP_LEN]; + translate_dist_to_str(prop_str, sizeof(prop_str), t->prop_size, unit); + + ofs += BLI_snprintf_rlen(str + ofs, + UI_MAX_DRAW_STR - ofs, + "%s %s: %s ", + TIP_("Proportional Size"), + t->proptext, + prop_str); } if (t->flag & T_AUTOIK) { short chainlen = t->settings->autoik_chainlen; - if (chainlen) { - BLI_snprintf(autoik, NUM_STR_REP_LEN, TIP_("AutoIK-Len: %d"), chainlen); - } - else { - autoik[0] = '\0'; + ofs += BLI_snprintf_rlen(str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("AutoIK-Len: %d"), chainlen); + ofs += BLI_strncpy_rlen(str + ofs, " ", UI_MAX_DRAW_STR - ofs); } } - else { - autoik[0] = '\0'; - } if (t->con.mode & CON_APPLY) { switch (t->num.idx_max) { case 0: - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - "D: %s (%s)%s %s %s", - &tvec[0], - distvec, - t->con.text, - t->proptext, - autoik); + ofs += BLI_snprintf_rlen( + str + ofs, UI_MAX_DRAW_STR - ofs, "D: %s (%s)%s", dvec_str[0], dist_str, t->con.text); break; case 1: - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - "D: %s D: %s (%s)%s %s %s", - &tvec[0], - &tvec[NUM_STR_REP_LEN], - distvec, - t->con.text, - t->proptext, - autoik); + ofs += BLI_snprintf_rlen(str + ofs, + UI_MAX_DRAW_STR - ofs, + "D: %s D: %s (%s)%s", + dvec_str[0], + dvec_str[1], + dist_str, + t->con.text); break; case 2: - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - "D: %s D: %s D: %s (%s)%s %s %s", - &tvec[0], - &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], - distvec, - t->con.text, - t->proptext, - autoik); + ofs += BLI_snprintf_rlen(str + ofs, + UI_MAX_DRAW_STR - ofs, + "D: %s D: %s D: %s (%s)%s", + dvec_str[0], + dvec_str[1], + dvec_str[2], + dist_str, + t->con.text); break; } } else { if (t->flag & T_2D_EDIT) { - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - "Dx: %s Dy: %s (%s)%s %s", - &tvec[0], - &tvec[NUM_STR_REP_LEN], - distvec, - t->con.text, - t->proptext); + ofs += BLI_snprintf_rlen(str + ofs, + UI_MAX_DRAW_STR - ofs, + "Dx: %s Dy: %s (%s)%s", + dvec_str[0], + dvec_str[1], + dist_str, + t->con.text); } else { - ofs += BLI_snprintf(str + ofs, - UI_MAX_DRAW_STR - ofs, - "Dx: %s Dy: %s Dz: %s (%s)%s %s %s", - &tvec[0], - &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], - distvec, - t->con.text, - t->proptext, - autoik); + ofs += BLI_snprintf_rlen(str + ofs, + UI_MAX_DRAW_STR - ofs, + "Dx: %s Dy: %s Dz: %s (%s)%s", + dvec_str[0], + dvec_str[1], + dvec_str[2], + dist_str, + t->con.text); } } - if (t->flag & T_PROP_EDIT_ALL) { - ofs += BLI_snprintf( - str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" Proportional size: %.2f"), t->prop_size); - } - if (t->spacetype == SPACE_NODE) { SpaceNode *snode = (SpaceNode *)t->area->spacedata.first; @@ -217,12 +332,12 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ WM_modalkeymap_items_to_string( t->keymap, TFM_MODAL_INSERTOFS_TOGGLE_DIR, true, str_km, sizeof(str_km)); - ofs += BLI_snprintf(str, - UI_MAX_DRAW_STR, - TIP_("Auto-offset set to %s - press %s to toggle direction | %s"), - str_dir, - str_km, - str_old); + ofs += BLI_snprintf_rlen(str, + UI_MAX_DRAW_STR, + TIP_("Auto-offset set to %s - press %s to toggle direction | %s"), + str_dir, + str_km, + str_old); MEM_freeN((void *)str_old); } @@ -243,6 +358,9 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3]) vec[1] = point[1] - t->tsnap.snapTarget[1]; } } + else if (t->spacetype == SPACE_SEQ) { + transform_snap_sequencer_apply_translate(t, vec); + } else { if (t->spacetype == SPACE_VIEW3D) { if (t->options & CTX_PAINT_CURVE) { @@ -259,99 +377,65 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3]) static void applyTranslationValue(TransInfo *t, const float vec[3]) { - const bool apply_snap_align_rotation = usingSnappingNormal( - t); // && (t->tsnap.status & POINT_INIT); - float tvec[3]; - - /* The ideal would be "apply_snap_align_rotation" only when a snap point is found - * so, maybe inside this function is not the best place to apply this rotation. - * but you need "handle snapping rotation before doing the translation" (really?) */ - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - - float pivot[3]; - if (apply_snap_align_rotation) { - copy_v3_v3(pivot, t->tsnap.snapTarget); - /* The pivot has to be in local-space (see T49494) */ - if (tc->use_local_mat) { - mul_m4_v3(tc->imat, pivot); - } - } - - TransData *td = tc->data; - for (int i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_SKIP) { - continue; - } - - float rotate_offset[3] = {0}; - bool use_rotate_offset = false; - - /* handle snapping rotation before doing the translation */ - if (apply_snap_align_rotation) { - float mat[3][3]; + struct TranslateCustomData *custom_data = t->custom.mode.data; - if (validSnappingNormal(t)) { - const float *original_normal; + enum eTranslateRotateMode rotate_mode = TRANSLATE_ROTATE_OFF; - /* In pose mode, we want to align normals with Y axis of bones... */ - if (t->options & CTX_POSE_BONE) { - original_normal = td->axismtx[1]; - } - else { - original_normal = td->axismtx[2]; - } - - rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal); - } - else { - unit_m3(mat); - } - - ElementRotation_ex(t, tc, td, mat, pivot); - - if (td->loc) { - use_rotate_offset = true; - sub_v3_v3v3(rotate_offset, td->loc, td->iloc); - } - } + if (activeSnap(t) && usingSnappingNormal(t) && validSnappingNormal(t)) { + rotate_mode = TRANSLATE_ROTATE_ON; + } - if (t->con.applyVec) { - t->con.applyVec(t, tc, td, vec, tvec); - } - else { - copy_v3_v3(tvec, vec); + /* Check to see if this needs to be re-enabled. */ + if (rotate_mode == TRANSLATE_ROTATE_OFF) { + if (t->flag & T_POINTS) { + /* When transforming points, only use rotation when snapping is enabled + * since re-applying translation without rotation removes rotation. */ + } + else { + /* When transforming data that it's self stores rotation (objects, bones etc), + * apply rotation if it was applied (with the snap normal) previously. + * This is needed because failing to rotate will leave the rotation at the last + * value used before snapping was disabled. */ + if (custom_data->prev.rotate_mode == TRANSLATE_ROTATE_ON) { + rotate_mode = TRANSLATE_ROTATE_RESET; } + } + } - mul_m3_v3(td->smtx, tvec); - - if (use_rotate_offset) { - add_v3_v3(tvec, rotate_offset); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + float pivot_local[3]; + if (rotate_mode != TRANSLATE_ROTATE_OFF) { + copy_v3_v3(pivot_local, t->tsnap.snapTarget); + /* The pivot has to be in local-space (see T49494) */ + if (tc->use_local_mat) { + mul_m4_v3(tc->imat, pivot_local); } + } - if (t->options & CTX_GPENCIL_STROKES) { - /* grease pencil multiframe falloff */ - bGPDstroke *gps = (bGPDstroke *)td->extra; - if (gps != NULL) { - mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff); - } - else { - mul_v3_fl(tvec, td->factor); + if (tc->data_len < TRANSDATA_THREAD_LIMIT) { + TransData *td = tc->data; + for (int i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; } + transdata_elem_translate(t, tc, td, pivot_local, vec, rotate_mode); } - else { - /* proportional editing falloff */ - mul_v3_fl(tvec, td->factor); - } - - protectedTransBits(td->protectflag, tvec); - - if (td->loc) { - add_v3_v3v3(td->loc, td->iloc, tvec); - } - - constraintTransLim(t, td); + } + else { + struct TransDataArgs_Translate data = { + .t = t, + .tc = tc, + .pivot_local = {UNPACK3(pivot_local)}, + .vec = {UNPACK3(vec)}, + .rotate_mode = rotate_mode, + }; + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_translate_fn, &settings); } } + + custom_data->prev.rotate_mode = rotate_mode; } static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) @@ -383,6 +467,11 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) } else { copy_v3_v3(global_dir, t->values); + if (!is_zero_v3(t->values_modal_offset)) { + float values_ofs[3]; + mul_v3_m3v3(values_ofs, t->spacemtx, t->values_modal_offset); + add_v3_v3(global_dir, values_ofs); + } t->tsnap.snapElem = 0; applySnapping(t, global_dir); @@ -471,6 +560,12 @@ void initTranslation(TransInfo *t) t->num.unit_type[2] = B_UNIT_NONE; } - transform_mode_default_modal_orientation_set(t, V3D_ORIENT_GLOBAL); + transform_mode_default_modal_orientation_set( + t, (t->options & CTX_CAMERA) ? V3D_ORIENT_VIEW : V3D_ORIENT_GLOBAL); + + struct TranslateCustomData *custom_data = MEM_callocN(sizeof(*custom_data), __func__); + custom_data->prev.rotate_mode = TRANSLATE_ROTATE_OFF; + t->custom.mode.data = custom_data; + t->custom.mode.use_free = true; } /** \} */ diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c index 1e5d027e253..def5f911c6f 100644 --- a/source/blender/editors/transform/transform_mode_vert_slide.c +++ b/source/blender/editors/transform/transform_mode_vert_slide.c @@ -158,7 +158,7 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2] TransDataVertSlideVert *sv; int i; - /* note: we could save a matrix-multiply for each vertex + /* NOTE: we could save a matrix-multiply for each vertex * by finding the closest edge in local-space. * However this skews the outcome with non-uniform-scale. */ @@ -606,15 +606,15 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2])) ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs); } else { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final); + ofs += BLI_snprintf_rlen(str + ofs, sizeof(str) - ofs, "%.4f ", final); } - ofs += BLI_snprintf( + ofs += BLI_snprintf_rlen( str + ofs, sizeof(str) - ofs, TIP_("(E)ven: %s, "), WM_bool_as_string(use_even)); if (use_even) { - ofs += BLI_snprintf( + ofs += BLI_snprintf_rlen( str + ofs, sizeof(str) - ofs, TIP_("(F)lipped: %s, "), WM_bool_as_string(flipped)); } - ofs += BLI_snprintf( + ofs += BLI_snprintf_rlen( str + ofs, sizeof(str) - ofs, TIP_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp)); /* done with header string */ diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 9b5f15a2574..2c424d8ace3 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -519,10 +519,11 @@ static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* add temp handler */ WM_event_add_modal_handler(C, op); - op->flag |= OP_IS_MODAL_GRAB_CURSOR; /* XXX maybe we want this with the gizmo only? */ - /* Use when modal input has some transformation to begin with. */ TransInfo *t = op->customdata; + if ((t->flag & T_NO_CURSOR_WRAP) == 0) { + op->flag |= OP_IS_MODAL_GRAB_CURSOR; /* XXX maybe we want this with the gizmo only? */ + } if (UNLIKELY(!is_zero_v4(t->values_modal_offset))) { transformApply(C, t); } @@ -538,7 +539,7 @@ static bool transform_poll_property(const bContext *UNUSED(C), /* Orientation/Constraints. */ { - /* Hide orientation axis if no constraints are set, since it wont be used. */ + /* Hide orientation axis if no constraints are set, since it won't be used. */ PropertyRNA *prop_con = RNA_struct_find_property(op->ptr, "orient_type"); if (!ELEM(prop_con, NULL, prop)) { if (STRPREFIX(prop_id, "constraint")) { diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index b3ed294845d..155250261de 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -445,7 +445,7 @@ int BIF_countTransformOrientation(const bContext *C) return BLI_listbase_count(transform_orientations); } -void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name) +void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char r_name[64]) { if (r_name) { BLI_strncpy(r_name, ts->name, MAX_NAME); @@ -455,7 +455,7 @@ void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3] /* Updates all `BONE_TRANSFORM` flags. * Returns total number of bones with `BONE_TRANSFORM`. - * Note: `transform_convert_pose_transflags_update` has a similar logic. */ + * NOTE: `transform_convert_pose_transflags_update` has a similar logic. */ static int armature_bone_transflags_update_recursive(bArmature *arm, ListBase *lb, const bool do_it) diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 193954fffb6..2619fdf3403 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -41,9 +41,6 @@ #include "RNA_access.h" -#include "SEQ_sequencer.h" -#include "SEQ_time.h" - #include "WM_types.h" #include "ED_gizmo_library.h" @@ -55,12 +52,18 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "SEQ_iterator.h" +#include "SEQ_sequencer.h" +#include "SEQ_time.h" + #include "MEM_guardedalloc.h" #include "transform.h" #include "transform_convert.h" #include "transform_snap.h" +static bool doForceIncrementSnap(const TransInfo *t); + /* this should be passed as an arg for use in snap functions */ #undef BASACT @@ -73,7 +76,10 @@ static void setSnappingCallback(TransInfo *t); /* static void CalcSnapGrid(TransInfo *t, float *vec); */ -static void CalcSnapGeometry(TransInfo *t, float *vec); +static void snap_calc_view3d_fn(TransInfo *t, float *vec); +static void snap_calc_uv_fn(TransInfo *t, float *vec); +static void snap_calc_node_fn(TransInfo *t, float *vec); +static void snap_calc_sequencer_fn(TransInfo *t, float *vec); static void TargetSnapMedian(TransInfo *t); static void TargetSnapCenter(TransInfo *t); @@ -133,6 +139,23 @@ bool activeSnap(const TransInfo *t) ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT); } +bool activeSnap_with_project(const TransInfo *t) +{ + if (!t->tsnap.project) { + return false; + } + + if (!activeSnap(t) || (t->flag & T_NO_PROJECT)) { + return false; + } + + if (doForceIncrementSnap(t)) { + return false; + } + + return true; +} + bool transformModeUseSnap(const TransInfo *t) { ToolSettings *ts = t->settings; @@ -145,10 +168,7 @@ bool transformModeUseSnap(const TransInfo *t) if (t->mode == TFM_RESIZE) { return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_SCALE) != 0; } - if (t->mode == TFM_VERT_SLIDE) { - return true; - } - if (t->mode == TFM_EDGE_SLIDE) { + if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE, TFM_SEQ_SLIDE)) { return true; } @@ -276,6 +296,26 @@ void drawSnapping(const struct bContext *C, TransInfo *t) GPU_blend(GPU_BLEND_NONE); } } + else if (t->spacetype == SPACE_SEQ) { + if (validSnap(t)) { + const ARegion *region = CTX_wm_region(C); + GPU_blend(GPU_BLEND_ALPHA); + uint pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col); + col[3] = 128; + immUniformColor4ubv(col); + float pixelx = BLI_rctf_size_x(®ion->v2d.cur) / BLI_rcti_size_x(®ion->v2d.mask); + immRectf(pos, + t->tsnap.snapPoint[0] - pixelx, + region->v2d.cur.ymax, + t->tsnap.snapPoint[0] + pixelx, + region->v2d.cur.ymin); + immUnbindProgram(); + GPU_blend(GPU_BLEND_NONE); + } + } } eRedrawFlag handleSnapping(TransInfo *t, const wmEvent *event) @@ -299,15 +339,7 @@ eRedrawFlag handleSnapping(TransInfo *t, const wmEvent *event) void applyProject(TransInfo *t) { - if (!t->tsnap.project) { - return; - } - - if (!activeSnap(t) || (t->flag & T_NO_PROJECT)) { - return; - } - - if (doForceIncrementSnap(t)) { + if (!activeSnap_with_project(t)) { return; } @@ -378,7 +410,7 @@ void applyProject(TransInfo *t) transform_data_ext_rotate(td, mat, true); - /* TODO support constraints for rotation too? see ElementRotation */ + /* TODO: support constraints for rotation too? see #ElementRotation. */ } } } @@ -465,10 +497,13 @@ void applySnapping(TransInfo *t, float *vec) /* TODO: add exception for object mode, no need to slow it down then. */ if (current - t->tsnap.last >= 0.01) { t->tsnap.calcSnap(t, vec); - t->tsnap.targetSnap(t); - - t->tsnap.last = current; + if (t->tsnap.targetSnap) { + t->tsnap.targetSnap(t); + } } + + t->tsnap.last = current; + if (validSnap(t)) { t->tsnap.applySnap(t, vec); } @@ -556,6 +591,9 @@ static void initSnappingMode(TransInfo *t) t->tsnap.mode = ts->snap_uv_mode; } + else if (t->spacetype == SPACE_SEQ) { + t->tsnap.mode = SEQ_tool_settings_snap_mode_get(t->scene); + } else { /* force project off when not supported */ if ((ts->snap_mode & SCE_SNAP_MODE_FACE) == 0) { @@ -615,16 +653,12 @@ static void initSnappingMode(TransInfo *t) t->tsnap.mode = SCE_SNAP_MODE_INCREMENT; } } - else if (t->spacetype == SPACE_NODE) { + else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) { setSnappingCallback(t); t->tsnap.modeSelect = SNAP_NOT_SELECTED; } - else if (t->spacetype == SPACE_SEQ) { - /* We do our own snapping currently, so nothing here */ - t->tsnap.mode = SCE_SNAP_MODE_GRID; /* Dummy, should we rather add a NOP mode? */ - } else { - /* Always increment outside of 3D view */ + /* Fallback. */ t->tsnap.mode = SCE_SNAP_MODE_INCREMENT; } @@ -645,6 +679,11 @@ static void initSnappingMode(TransInfo *t) } } } + else if (t->spacetype == SPACE_SEQ) { + if (t->tsnap.seq_context == NULL) { + t->tsnap.seq_context = transform_snap_sequencer_data_alloc(t); + } + } } void initSnapping(TransInfo *t, wmOperator *op) @@ -697,6 +736,9 @@ void initSnapping(TransInfo *t, wmOperator *op) t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) != 0); t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0); } + else if ((t->spacetype == SPACE_SEQ) && (ts->snap_flag & SCE_SNAP_SEQ)) { + t->modifiers |= MOD_SNAP; + } } t->tsnap.target = snap_target; @@ -706,7 +748,11 @@ void initSnapping(TransInfo *t, wmOperator *op) void freeSnapping(TransInfo *t) { - if (t->tsnap.object_context) { + if ((t->spacetype == SPACE_SEQ) && t->tsnap.seq_context) { + transform_snap_sequencer_data_free(t->tsnap.seq_context); + t->tsnap.seq_context = NULL; + } + else if (t->tsnap.object_context) { ED_transform_snap_object_context_destroy(t->tsnap.object_context); t->tsnap.object_context = NULL; } @@ -714,7 +760,20 @@ void freeSnapping(TransInfo *t) static void setSnappingCallback(TransInfo *t) { - t->tsnap.calcSnap = CalcSnapGeometry; + if (t->spacetype == SPACE_VIEW3D) { + t->tsnap.calcSnap = snap_calc_view3d_fn; + } + else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) { + t->tsnap.calcSnap = snap_calc_uv_fn; + } + else if (t->spacetype == SPACE_NODE) { + t->tsnap.calcSnap = snap_calc_node_fn; + } + else if (t->spacetype == SPACE_SEQ) { + t->tsnap.calcSnap = snap_calc_sequencer_fn; + /* The target is calculated along with the snap point. */ + return; + } switch (t->tsnap.target) { case SCE_SNAP_TARGET_CLOSEST: @@ -835,89 +894,105 @@ void getSnapPoint(const TransInfo *t, float vec[3]) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Calc Snap (Generic) +/** \name Calc Snap * \{ */ -static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) +static void snap_calc_view3d_fn(TransInfo *t, float *UNUSED(vec)) { - if (t->spacetype == SPACE_VIEW3D) { - float loc[3]; - float no[3]; - float mval[2]; - bool found = false; - short snap_elem = 0; - float dist_px = SNAP_MIN_DISTANCE; /* Use a user defined value here. */ + BLI_assert(t->spacetype == SPACE_VIEW3D); + float loc[3]; + float no[3]; + float mval[2]; + bool found = false; + short snap_elem = 0; + float dist_px = SNAP_MIN_DISTANCE; /* Use a user defined value here. */ + + mval[0] = t->mval[0]; + mval[1] = t->mval[1]; + + if (t->tsnap.mode & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | + SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { + zero_v3(no); /* objects won't set this */ + snap_elem = snapObjectsTransform(t, mval, &dist_px, loc, no); + found = snap_elem != 0; + } + if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) { + found = peelObjectsTransform( + t, mval, (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0, loc, no, NULL); + + if (found) { + snap_elem = SCE_SNAP_MODE_VOLUME; + } + } - mval[0] = t->mval[0]; - mval[1] = t->mval[1]; + if (found == true) { + copy_v3_v3(t->tsnap.snapPoint, loc); + copy_v3_v3(t->tsnap.snapNormal, no); - if (t->tsnap.mode & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | - SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { - zero_v3(no); /* objects won't set this */ - snap_elem = snapObjectsTransform(t, mval, &dist_px, loc, no); - found = snap_elem != 0; - } - if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) { - found = peelObjectsTransform( - t, mval, (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0, loc, no, NULL); + t->tsnap.status |= POINT_INIT; + } + else { + t->tsnap.status &= ~POINT_INIT; + } - if (found) { - snap_elem = SCE_SNAP_MODE_VOLUME; - } - } + t->tsnap.snapElem = (char)snap_elem; +} + +static void snap_calc_uv_fn(TransInfo *t, float *UNUSED(vec)) +{ + BLI_assert(t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH); + if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) { + float co[2]; + + UI_view2d_region_to_view(&t->region->v2d, t->mval[0], t->mval[1], &co[0], &co[1]); - if (found == true) { - copy_v3_v3(t->tsnap.snapPoint, loc); - copy_v3_v3(t->tsnap.snapNormal, no); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + t->view_layer, NULL, &objects_len); + + float dist_sq = FLT_MAX; + if (ED_uvedit_nearest_uv_multi( + t->scene, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) { + t->tsnap.snapPoint[0] *= t->aspect[0]; + t->tsnap.snapPoint[1] *= t->aspect[1]; t->tsnap.status |= POINT_INIT; } else { t->tsnap.status &= ~POINT_INIT; } - - t->tsnap.snapElem = (char)snap_elem; + MEM_freeN(objects); } - else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) { - if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) { - float co[2]; - - UI_view2d_region_to_view(&t->region->v2d, t->mval[0], t->mval[1], &co[0], &co[1]); +} - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - t->view_layer, NULL, &objects_len); +static void snap_calc_node_fn(TransInfo *t, float *UNUSED(vec)) +{ + BLI_assert(t->spacetype == SPACE_NODE); + if (t->tsnap.mode & (SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y)) { + float loc[2]; + float dist_px = SNAP_MIN_DISTANCE; /* Use a user defined value here. */ + char node_border; - float dist_sq = FLT_MAX; - if (ED_uvedit_nearest_uv_multi( - t->scene, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) { - t->tsnap.snapPoint[0] *= t->aspect[0]; - t->tsnap.snapPoint[1] *= t->aspect[1]; + if (snapNodesTransform(t, t->mval, loc, &dist_px, &node_border)) { + copy_v2_v2(t->tsnap.snapPoint, loc); + t->tsnap.snapNodeBorder = node_border; - t->tsnap.status |= POINT_INIT; - } - else { - t->tsnap.status &= ~POINT_INIT; - } - MEM_freeN(objects); + t->tsnap.status |= POINT_INIT; + } + else { + t->tsnap.status &= ~POINT_INIT; } } - else if (t->spacetype == SPACE_NODE) { - if (t->tsnap.mode & (SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y)) { - float loc[2]; - float dist_px = SNAP_MIN_DISTANCE; /* Use a user defined value here. */ - char node_border; - - if (snapNodesTransform(t, t->mval, loc, &dist_px, &node_border)) { - copy_v2_v2(t->tsnap.snapPoint, loc); - t->tsnap.snapNodeBorder = node_border; +} - t->tsnap.status |= POINT_INIT; - } - else { - t->tsnap.status &= ~POINT_INIT; - } - } +static void snap_calc_sequencer_fn(TransInfo *t, float *UNUSED(vec)) +{ + BLI_assert(t->spacetype == SPACE_SEQ); + if (transform_snap_sequencer_calc(t)) { + t->tsnap.status |= (POINT_INIT | TARGET_INIT); + } + else { + t->tsnap.status &= ~(POINT_INIT | TARGET_INIT); } } @@ -1072,7 +1147,7 @@ static void TargetSnapClosest(TransInfo *t) if (t->options & CTX_OBJECT) { int i; FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; + TransData *td; for (td = tc->data, i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) { const BoundBox *bb = NULL; @@ -1430,28 +1505,6 @@ void snapFrameTransform(TransInfo *t, *r_val = (float)val; } -/*================================================================*/ - -void snapSequenceBounds(TransInfo *t, const int mval[2]) -{ - /* Reuse increment, strictly speaking could be another snap mode, but leave as is. */ - if (!(t->modifiers & MOD_SNAP_INVERT)) { - return; - } - - /* Convert to frame range. */ - float xmouse, ymouse; - UI_view2d_region_to_view(&t->region->v2d, mval[0], mval[1], &xmouse, &ymouse); - const int frame_curr = round_fl_to_int(xmouse); - - /* Now find the closest sequence. */ - const int frame_near = SEQ_time_find_next_prev_edit( - t->scene, frame_curr, SEQ_SIDE_BOTH, true, false, true); - - const int frame_snap = transform_convert_sequencer_get_snap_bound(t); - t->values[0] = frame_near - frame_snap; -} - static void snap_grid_apply( TransInfo *t, const int max_index, const float grid_dist, const float loc[3], float r_out[3]) { @@ -1506,7 +1559,7 @@ bool transform_snap_grid(TransInfo *t, float *val) return true; } -static void snap_increment_apply_ex(TransInfo *UNUSED(t), +static void snap_increment_apply_ex(const TransInfo *UNUSED(t), const int max_index, const float increment_val, const float aspect[3], @@ -1520,8 +1573,8 @@ static void snap_increment_apply_ex(TransInfo *UNUSED(t), } } -static void snap_increment_apply(TransInfo *t, - int max_index, +static void snap_increment_apply(const TransInfo *t, + const int max_index, const float increment_dist, float *r_val) { @@ -1553,7 +1606,7 @@ static void snap_increment_apply(TransInfo *t, snap_increment_apply_ex(t, max_index, increment_dist, asp, r_val, r_val); } -bool transform_snap_increment_ex(TransInfo *t, bool use_local_space, float *r_val) +bool transform_snap_increment_ex(const TransInfo *t, bool use_local_space, float *r_val) { if (!activeSnap(t)) { return false; @@ -1584,7 +1637,7 @@ bool transform_snap_increment_ex(TransInfo *t, bool use_local_space, float *r_va return true; } -bool transform_snap_increment(TransInfo *t, float *r_val) +bool transform_snap_increment(const TransInfo *t, float *r_val) { return transform_snap_increment_ex(t, false, r_val); } diff --git a/source/blender/editors/transform/transform_snap.h b/source/blender/editors/transform/transform_snap.h index c557368ed17..6dfaeab93e6 100644 --- a/source/blender/editors/transform/transform_snap.h +++ b/source/blender/editors/transform/transform_snap.h @@ -54,13 +54,13 @@ void snapFrameTransform(struct TransInfo *t, bool transformModeUseSnap(const TransInfo *t); -bool transform_snap_increment_ex(TransInfo *t, bool use_local_space, float *r_val); -bool transform_snap_increment(TransInfo *t, float *val); +bool transform_snap_increment_ex(const TransInfo *t, bool use_local_space, float *r_val); +bool transform_snap_increment(const TransInfo *t, float *val); bool transform_snap_grid(TransInfo *t, float *val); -void snapSequenceBounds(TransInfo *t, const int mval[2]); - bool activeSnap(const TransInfo *t); +bool activeSnap_with_project(const TransInfo *t); + bool validSnap(const TransInfo *t); void initSnapping(struct TransInfo *t, struct wmOperator *op); @@ -80,3 +80,9 @@ eRedrawFlag updateSelectedSnapPoint(TransInfo *t); void removeSnapPoint(TransInfo *t); float transform_snap_distance_len_squared_fn(TransInfo *t, const float p1[3], const float p2[3]); + +/* transform_snap_sequencer.c */ +struct TransSeqSnapData *transform_snap_sequencer_data_alloc(const TransInfo *t); +void transform_snap_sequencer_data_free(struct TransSeqSnapData *data); +bool transform_snap_sequencer_calc(struct TransInfo *t); +void transform_snap_sequencer_apply_translate(TransInfo *t, float *vec); diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 512f912a532..2d98d756dba 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -255,7 +255,7 @@ static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object * static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob_eval, - Mesh *me_eval, + const Mesh *me_eval, bool use_hide) { SnapObjectData *sod; @@ -535,7 +535,7 @@ static void iter_snap_objects(SnapObjectContext *sctx, * \{ */ /* Store all ray-hits - * Support for storing all depths, not just the first (raycast 'all') */ + * Support for storing all depths, not just the first (ray-cast 'all'). */ struct RayCastAll_Data { void *bvhdata; @@ -626,7 +626,7 @@ static bool raycast_tri_backface_culling_test( return dot_v3v3(no, dir) < 0.0f; } -/* Callback to raycast with backface culling (Mesh). */ +/* Callback to ray-cast with back-face culling (#Mesh). */ static void mesh_looptri_raycast_backface_culling_cb(void *userdata, int index, const BVHTreeRay *ray, @@ -653,7 +653,7 @@ static void mesh_looptri_raycast_backface_culling_cb(void *userdata, } } -/* Callback to raycast with backface culling (EditMesh). */ +/* Callback to ray-cast with back-face culling (#EditMesh). */ static void editmesh_looptri_raycast_backface_culling_cb(void *userdata, int index, const BVHTreeRay *ray, @@ -687,7 +687,7 @@ static bool raycastMesh(SnapObjectContext *sctx, const float ray_start[3], const float ray_dir[3], Object *ob_eval, - Mesh *me_eval, + const Mesh *me_eval, const float obmat[4][4], const uint ob_index, bool use_hide, @@ -1088,7 +1088,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx, case OB_SURF: case OB_FONT: { if (!is_object_active) { - Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval); + const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval); if (mesh_eval) { retval = raycastMesh(sctx, dt->ray_start, @@ -1142,7 +1142,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx, * \param r_loc: Hit location. * \param r_no: Hit normal (optional). * \param r_index: Hit index or -1 when no valid index is found. - * (currently only set to the polygon index when when using ``snap_to == SCE_SNAP_MODE_FACE``). + * (currently only set to the polygon index when using ``snap_to == SCE_SNAP_MODE_FACE``). * \param r_ob: Hit object. * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances). * \param r_hit_list: List of #SnapObjectHitDepth (caller must free). @@ -2777,7 +2777,7 @@ static void snap_obj_fn(SnapObjectContext *sctx, * \param r_loc: Hit location. * \param r_no: Hit normal (optional). * \param r_index: Hit index or -1 when no valid index is found. - * (currently only set to the polygon index when when using ``snap_to == SCE_SNAP_MODE_FACE``). + * (currently only set to the polygon index when using ``snap_to == SCE_SNAP_MODE_FACE``). * \param r_ob: Hit object. * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances). */ diff --git a/source/blender/editors/transform/transform_snap_sequencer.c b/source/blender/editors/transform/transform_snap_sequencer.c new file mode 100644 index 00000000000..d0b730383d5 --- /dev/null +++ b/source/blender/editors/transform/transform_snap_sequencer.c @@ -0,0 +1,275 @@ +/* + * 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 <stdlib.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#include "BKE_context.h" + +#include "ED_screen.h" + +#include "UI_view2d.h" + +#include "SEQ_iterator.h" +#include "SEQ_sequencer.h" + +#include "transform.h" +#include "transform_snap.h" + +typedef struct TransSeqSnapData { + int *source_snap_points; + int *target_snap_points; + int source_snap_point_count; + int target_snap_point_count; + int final_snap_frame; +} TransSeqSnapData; + +/* -------------------------------------------------------------------- */ +/** \name Snap sources + * \{ */ + +static int seq_get_snap_source_points_len(SeqCollection *snap_sources) +{ + return SEQ_collection_len(snap_sources) * 2; +} + +static void seq_snap_source_points_alloc(TransSeqSnapData *snap_data, SeqCollection *snap_sources) +{ + const size_t point_count = seq_get_snap_source_points_len(snap_sources); + snap_data->source_snap_points = MEM_callocN(sizeof(int) * point_count, __func__); + memset(snap_data->source_snap_points, 0, sizeof(int)); + snap_data->source_snap_point_count = point_count; +} + +static int cmp_fn(const void *a, const void *b) +{ + return (*(int *)a - *(int *)b); +} + +static void seq_snap_source_points_build(const TransInfo *UNUSED(t), + TransSeqSnapData *snap_data, + SeqCollection *snap_sources) +{ + int i = 0; + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, snap_sources) { + int left = 0, right = 0; + if (seq->flag & SEQ_LEFTSEL) { + left = right = seq->startdisp; + } + else if (seq->flag & SEQ_RIGHTSEL) { + left = right = seq->enddisp; + } + else { + left = seq->startdisp; + right = seq->enddisp; + } + + snap_data->source_snap_points[i] = left; + snap_data->source_snap_points[i + 1] = right; + i += 2; + BLI_assert(i <= snap_data->source_snap_point_count); + } + + qsort(snap_data->source_snap_points, snap_data->source_snap_point_count, sizeof(int), cmp_fn); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Snap targets + * \{ */ + +static SeqCollection *query_snap_targets(const TransInfo *t) +{ + const ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene, false)); + const short snap_flag = SEQ_tool_settings_snap_flag_get(t->scene); + SeqCollection *collection = SEQ_collection_create(__func__); + LISTBASE_FOREACH (Sequence *, seq, seqbase) { + if ((seq->flag & SELECT)) { + continue; /* Selected are being transformed. */ + } + if ((seq->flag & SEQ_MUTE) && (snap_flag & SEQ_SNAP_IGNORE_MUTED)) { + continue; + } + if (seq->type == SEQ_TYPE_SOUND_RAM && (snap_flag & SEQ_SNAP_IGNORE_SOUND)) { + continue; + } + SEQ_collection_append_strip(seq, collection); + } + return collection; +} + +static int seq_get_snap_target_points_count(const TransInfo *t, + TransSeqSnapData *UNUSED(snap_data), + SeqCollection *snap_targets) +{ + const short snap_mode = t->tsnap.mode; + + int count = 2; /* Strip start and end are always used. */ + + if (snap_mode & SEQ_SNAP_TO_STRIP_HOLD) { + count += 2; + } + + count *= SEQ_collection_len(snap_targets); + + if (snap_mode & SEQ_SNAP_TO_CURRENT_FRAME) { + count++; + } + + return count; +} + +static void seq_snap_target_points_alloc(const TransInfo *t, + TransSeqSnapData *snap_data, + SeqCollection *snap_targets) +{ + const size_t point_count = seq_get_snap_target_points_count(t, snap_data, snap_targets); + snap_data->target_snap_points = MEM_callocN(sizeof(int) * point_count, __func__); + memset(snap_data->target_snap_points, 0, sizeof(int)); + snap_data->target_snap_point_count = point_count; +} + +static void seq_snap_target_points_build(const TransInfo *t, + TransSeqSnapData *snap_data, + SeqCollection *snap_targets) +{ + const Scene *scene = t->scene; + const short snap_mode = t->tsnap.mode; + + int i = 0; + + if (snap_mode & SEQ_SNAP_TO_CURRENT_FRAME) { + snap_data->target_snap_points[i] = CFRA; + i++; + } + + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, snap_targets) { + snap_data->target_snap_points[i] = seq->startdisp; + snap_data->target_snap_points[i + 1] = seq->enddisp; + i += 2; + + if (snap_mode & SEQ_SNAP_TO_STRIP_HOLD) { + int content_start = min_ii(seq->enddisp, seq->start); + int content_end = max_ii(seq->startdisp, seq->start + seq->len); + if (seq->anim_startofs == 0) { + content_start = seq->startdisp; + } + if (seq->anim_endofs == 0) { + content_end = seq->enddisp; + } + snap_data->target_snap_points[i] = content_start; + snap_data->target_snap_points[i + 1] = content_end; + i += 2; + } + } + BLI_assert(i <= snap_data->target_snap_point_count); + qsort(snap_data->target_snap_points, snap_data->target_snap_point_count, sizeof(int), cmp_fn); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Snap utilities + * \{ */ + +static int seq_snap_threshold_get_frame_distance(const TransInfo *t) +{ + const int snap_distance = SEQ_tool_settings_snap_distance_get(t->scene); + const struct View2D *v2d = &t->region->v2d; + return round_fl_to_int(UI_view2d_region_to_view_x(v2d, snap_distance) - + UI_view2d_region_to_view_x(v2d, 0)); +} + +/** \} */ + +TransSeqSnapData *transform_snap_sequencer_data_alloc(const TransInfo *t) +{ + TransSeqSnapData *snap_data = MEM_callocN(sizeof(TransSeqSnapData), __func__); + ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene, false)); + + /* Build arrays of snap points. */ + SeqCollection *snap_sources = SEQ_query_selected_strips(seqbase); + seq_snap_source_points_alloc(snap_data, snap_sources); + seq_snap_source_points_build(t, snap_data, snap_sources); + SEQ_collection_free(snap_sources); + + SeqCollection *snap_targets = query_snap_targets(t); + seq_snap_target_points_alloc(t, snap_data, snap_targets); + seq_snap_target_points_build(t, snap_data, snap_targets); + SEQ_collection_free(snap_targets); + return snap_data; +} + +void transform_snap_sequencer_data_free(TransSeqSnapData *data) +{ + MEM_freeN(data->source_snap_points); + MEM_freeN(data->target_snap_points); + MEM_freeN(data); +} + +bool transform_snap_sequencer_calc(TransInfo *t) +{ + /* Prevent snapping when constrained to Y axis. */ + if (t->con.mode & CON_APPLY && t->con.mode & CON_AXIS1) { + return false; + } + + const TransSeqSnapData *snap_data = t->tsnap.seq_context; + int best_dist = MAXFRAME, best_target_frame = 0, best_source_frame = 0; + + for (int i = 0; i < snap_data->source_snap_point_count; i++) { + int snap_source_frame = snap_data->source_snap_points[i] + round_fl_to_int(t->values[0]); + for (int j = 0; j < snap_data->target_snap_point_count; j++) { + int snap_target_frame = snap_data->target_snap_points[j]; + + int dist = abs(snap_target_frame - snap_source_frame); + if (dist > best_dist) { + continue; + } + + best_dist = dist; + best_target_frame = snap_target_frame; + best_source_frame = snap_source_frame; + } + } + + if (best_dist > seq_snap_threshold_get_frame_distance(t)) { + return false; + } + + t->tsnap.snapPoint[0] = best_target_frame; + t->tsnap.snapTarget[0] = best_source_frame; + return true; +} + +void transform_snap_sequencer_apply_translate(TransInfo *t, float *vec) +{ + *vec += t->tsnap.snapPoint[0] - t->tsnap.snapTarget[0]; +} diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index 7811509ab40..23161028e03 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -202,7 +202,7 @@ static void ed_undo_step_pre(bContext *C, /* App-Handlers (pre). */ { - /* Note: ignore grease pencil for now. */ + /* NOTE: ignore grease pencil for now. */ wm->op_undo_depth++; BKE_callback_exec_id( bmain, &scene->id, (undo_dir == STEP_UNDO) ? BKE_CB_EVT_UNDO_PRE : BKE_CB_EVT_REDO_PRE); @@ -321,7 +321,7 @@ static int ed_undo_step_by_name(bContext *C, const char *undo_name, ReportList * /* FIXME: See comments in `ed_undo_step_direction`. */ if (ED_gpencil_session_active()) { - BLI_assert(!"Not implemented currently."); + BLI_assert_msg(0, "Not implemented currently."); } wmWindowManager *wm = CTX_wm_manager(C); @@ -369,7 +369,7 @@ static int ed_undo_step_by_index(bContext *C, const int undo_index, ReportList * /* FIXME: See comments in `ed_undo_step_direction`. */ if (ED_gpencil_session_active()) { - BLI_assert(!"Not implemented currently."); + BLI_assert_msg(0, "Not implemented currently."); } wmWindowManager *wm = CTX_wm_manager(C); @@ -492,7 +492,7 @@ bool ED_undo_is_legacy_compatible_for_property(struct bContext *C, ID *id) } /** - * Ideally we wont access the stack directly, + * Ideally we won't access the stack directly, * this is needed for modes which handle undo themselves (bypassing #ED_undo_push). * * Using global isn't great, this just avoids doing inline, @@ -528,7 +528,7 @@ static int ed_undo_push_exec(bContext *C, wmOperator *op) { if (G.background) { /* Exception for background mode, see: T60934. - * Note: since the undo stack isn't initialized on startup, background mode behavior + * NOTE: since the undo stack isn't initialized on startup, background mode behavior * won't match regular usage, this is just for scripts to do explicit undo pushes. */ wmWindowManager *wm = CTX_wm_manager(C); if (wm->undo_stack == NULL) { @@ -693,11 +693,11 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op) } if ((WM_operator_repeat_check(C, op)) && (WM_operator_poll(C, op->type)) && - /* note, undo/redo cant run if there are jobs active, + /* NOTE: undo/redo can't run if there are jobs active, * check for screen jobs only so jobs like material/texture/world preview - * (which copy their data), wont stop redo, see T29579], + * (which copy their data), won't stop redo, see T29579], * - * note, - WM_operator_check_ui_enabled() jobs test _must_ stay in sync with this */ + * NOTE: WM_operator_check_ui_enabled() jobs test _must_ stay in sync with this. */ (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY) == 0)) { int retval; @@ -829,7 +829,7 @@ static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE return OPERATOR_CANCELLED; } -/* note: also check ed_undo_step() in top if you change notifiers */ +/* NOTE: also check #ed_undo_step() in top if you change notifiers. */ static int undo_history_exec(bContext *C, wmOperator *op) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "item"); diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c index 9189adaf4d1..7c6ce56eab0 100644 --- a/source/blender/editors/undo/memfile_undo.c +++ b/source/blender/editors/undo/memfile_undo.c @@ -224,9 +224,21 @@ static void memfile_undosys_step_decode(struct bContext *C, /* Tag depsgraph to update data-block for changes that happened between the * current and the target state, see direct_link_id_restore_recalc(). */ - if (id->recalc) { + if (id->recalc != 0) { DEG_id_tag_update_ex(bmain, id, id->recalc); } + + bNodeTree *nodetree = ntreeFromID(id); + if (nodetree != NULL && nodetree->id.recalc != 0) { + DEG_id_tag_update_ex(bmain, &nodetree->id, nodetree->id.recalc); + } + if (GS(id->name) == ID_SCE) { + Scene *scene = (Scene *)id; + if (scene->master_collection != NULL && scene->master_collection->id.recalc != 0) { + DEG_id_tag_update_ex( + bmain, &scene->master_collection->id, scene->master_collection->id.recalc); + } + } } FOREACH_MAIN_ID_END; diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c index ad45686dc75..b4a93eb996c 100644 --- a/source/blender/editors/util/ed_transverts.c +++ b/source/blender/editors/util/ed_transverts.c @@ -54,7 +54,7 @@ void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit) const int mode = tvs->mode; BLI_assert(ED_transverts_check_obedit(obedit) == true); - DEG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); if (obedit->type == OB_MESH) { BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -182,8 +182,8 @@ static void set_mapped_co(void *vuserdata, if (BM_elem_index_get(eve) != TM_INDEX_SKIP) { tv = &tv[BM_elem_index_get(eve)]; - /* be clever, get the closest vertex to the original, - * behaves most logically when the mirror modifier is used for eg T33051*/ + /* Be clever, get the closest vertex to the original, + * behaves most logically when the mirror modifier is used for eg T33051. */ if ((tv->flag & TX_VERT_USE_MAPLOC) == 0) { /* first time */ copy_v3_v3(tv->maploc, co); diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index b80782b51be..7bbdc58474f 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -295,8 +295,11 @@ bool ED_editors_flush_edits(Main *bmain) /* ***** XXX: functions are using old blender names, cleanup later ***** */ -/* now only used in 2d spaces, like time, ipo, nla, sima... */ -/* XXX shift/ctrl not configurable */ +/** + * Now only used in 2D spaces, like time, f-curve, NLA, image, etc. + * + * \note Shift/Control are not configurable key-bindings. + */ void apply_keyb_grid( int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert) { diff --git a/source/blender/editors/util/ed_util_imbuf.c b/source/blender/editors/util/ed_util_imbuf.c index 0f2e280251f..9e05efca3df 100644 --- a/source/blender/editors/util/ed_util_imbuf.c +++ b/source/blender/editors/util/ed_util_imbuf.c @@ -244,7 +244,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event } if (ibuf->zbuf) { - /* TODO, blend depth (not urgent). */ + /* TODO: blend depth (not urgent). */ info->z = ibuf->zbuf[y * ibuf->x + x]; info->zp = &info->z; if (ibuf->zbuf == (int *)ibuf->rect) { @@ -252,7 +252,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event } } if (ibuf->zbuf_float) { - /* TODO, blend depth (not urgent). */ + /* TODO: blend depth (not urgent). */ info->zf = ibuf->zbuf_float[y * ibuf->x + x]; info->zfp = &info->zf; if (ibuf->zbuf_float == ibuf->rect_float) { diff --git a/source/blender/editors/util/select_utils.c b/source/blender/editors/util/select_utils.c index 4e8cf1e92e6..5681edd2f5c 100644 --- a/source/blender/editors/util/select_utils.c +++ b/source/blender/editors/util/select_utils.c @@ -41,7 +41,7 @@ int ED_select_op_action(const eSelectOp sel_op, const bool is_select, const bool case SEL_OP_XOR: return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1); } - BLI_assert(!"invalid sel_op"); + BLI_assert_msg(0, "invalid sel_op"); return -1; } /** @@ -67,7 +67,7 @@ int ED_select_op_action_deselected(const eSelectOp sel_op, case SEL_OP_XOR: return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1); } - BLI_assert(!"invalid sel_op"); + BLI_assert_msg(0, "invalid sel_op"); return -1; } diff --git a/source/blender/editors/uvedit/uvedit_islands.c b/source/blender/editors/uvedit/uvedit_islands.c index 93948b5ae1b..56bcbc63de1 100644 --- a/source/blender/editors/uvedit/uvedit_islands.c +++ b/source/blender/editors/uvedit/uvedit_islands.c @@ -36,6 +36,7 @@ #include "BLI_math.h" #include "BLI_rect.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "DEG_depsgraph.h" diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index e11341429a6..0757e177235 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -608,7 +608,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) /* Projection of point (x, y) over line (x1, y1, x2, y2) along X axis: * new_y = (y2 - y1) / (x2 - x1) * (x - x1) + y1 * Maybe this should be a BLI func? Or is it already existing? - * Could use interp_v2_v2v2, but not sure it's worth it here...*/ + * Could use interp_v2_v2v2, but not sure it's worth it here. */ if (tool_local == UV_STRAIGHTEN_X) { luv->uv[0] = a * (luv->uv[1] - uv_start[1]) + uv_start[0]; } @@ -624,7 +624,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) } } else { - /* error - not a line, needs 3+ points */ + /* error - not a line, needs 3+ points. */ } if (eve_line) { @@ -632,7 +632,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) } } else { - /* error - cant find an endpoint */ + /* error - can't find an endpoint. */ } } @@ -1187,15 +1187,15 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Object *obedit) } BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_TAG)) { /* face: visible */ + if (BM_elem_flag_test(f, BM_ELEM_TAG)) { /* Face: visible. */ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l, BM_ELEM_TAG)) { /* loop: selected*/ + if (BM_elem_flag_test(l, BM_ELEM_TAG)) { /* Loop: selected. */ float uv[2] = {0.0f, 0.0f}; int uv_tot = 0; BM_ITER_ELEM (lsub, &lsubiter, l->v, BM_LOOPS_OF_VERT) { - if (BM_elem_flag_test(lsub->f, BM_ELEM_TAG) && /* face: visible */ - !BM_elem_flag_test(lsub, BM_ELEM_TAG)) /* loop: unselected */ + if (BM_elem_flag_test(lsub->f, BM_ELEM_TAG) && /* Face: visible. */ + !BM_elem_flag_test(lsub, BM_ELEM_TAG)) /* Loop: unselected. */ { luv = BM_ELEM_CD_GET_VOID_P(lsub, cd_loop_uv_offset); add_v2_v2(uv, luv->uv); @@ -1469,9 +1469,14 @@ static int uv_hide_exec(bContext *C, wmOperator *op) if (ts->uv_flag & UV_SYNC_SELECTION) { if (EDBM_mesh_hide(em, swap)) { - EDBM_update_generic(ob->data, true, false); + EDBM_update(ob->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } - return OPERATOR_FINISHED; + continue; } BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -1491,7 +1496,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op) } if (hide) { - /* note, a special case for edges could be used, + /* NOTE: a special case for edges could be used, * for now edges act like verts and get flushed */ if (use_face_center) { if (em->selectmode == SCE_SELECT_FACE) { @@ -1607,9 +1612,14 @@ static int uv_reveal_exec(bContext *C, wmOperator *op) /* call the mesh function if we are in mesh sync sel */ if (ts->uv_flag & UV_SYNC_SELECTION) { if (EDBM_mesh_reveal(em, select)) { - EDBM_update_generic(ob->data, true, false); + EDBM_update(ob->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); } - return OPERATOR_FINISHED; + continue; } if (use_face_center) { if (em->selectmode == SCE_SELECT_FACE) { diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index 7d82884760c..f97403a0919 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -82,10 +82,10 @@ typedef struct PVert { struct PVert *nextlink; union PVertUnion { - PHashKey key; /* construct */ - int id; /* abf/lscm matrix index */ - float distortion; /* area smoothing */ - HeapNode *heaplink; /* edge collapsing */ + PHashKey key; /* Construct. */ + int id; /* ABF/LSCM matrix index. */ + float distortion; /* Area smoothing. */ + HeapNode *heaplink; /* Edge collapsing. */ } u; struct PEdge *edge; @@ -99,10 +99,10 @@ typedef struct PEdge { struct PEdge *nextlink; union PEdgeUnion { - PHashKey key; /* construct */ - int id; /* abf matrix index */ - HeapNode *heaplink; /* fill holes */ - struct PEdge *nextcollapse; /* simplification */ + PHashKey key; /* Construct. */ + int id; /* ABF matrix index. */ + HeapNode *heaplink; /* Fill holes. */ + struct PEdge *nextcollapse; /* Simplification. */ } u; struct PVert *vert; @@ -118,10 +118,10 @@ typedef struct PFace { struct PFace *nextlink; union PFaceUnion { - PHashKey key; /* construct */ - int chart; /* construct splitting*/ - float area3d; /* stretch */ - int id; /* abf matrix index */ + PHashKey key; /* Construct. */ + int chart; /* Construct splitting. */ + float area3d; /* Stretch. */ + int id; /* ABF matrix index. */ } u; struct PEdge *edge; @@ -2154,7 +2154,7 @@ static void p_collapse_cost_vertex(PVert *vert, float *r_mincost, PEdge **r_mine static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed) { - /* move to collapsed_ */ + /* Move to `collapsed_*`. */ PVert *v, *nextv = NULL, *verts = chart->verts; PEdge *e, *nexte = NULL, *edges = chart->edges, *laste = NULL; @@ -2224,7 +2224,7 @@ static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed) static void p_chart_post_split_flush(PChart *chart) { - /* move from collapsed_ */ + /* Move from `collapsed_*`. */ PVert *v, *nextv = NULL; PEdge *e, *nexte = NULL; @@ -2259,7 +2259,7 @@ static void p_chart_post_split_flush(PChart *chart) static void p_chart_simplify_compute(PChart *chart) { /* Computes a list of edge collapses / vertex splits. The collapsed - * simplices go in the chart->collapsed_* lists, The original and + * simplices go in the `chart->collapsed_*` lists, The original and * collapsed may then be view as stacks, where the next collapse/split * is at the top of the respective lists. */ diff --git a/source/blender/editors/uvedit/uvedit_path.c b/source/blender/editors/uvedit/uvedit_path.c index 016a054cf21..2613c5b23a0 100644 --- a/source/blender/editors/uvedit/uvedit_path.c +++ b/source/blender/editors/uvedit/uvedit_path.c @@ -552,7 +552,7 @@ static bool uv_shortest_path_pick_ex(const SpaceImage *sima, if (uv_selectmode & UV_SELECT_EDGE) { /* Special case as we don't use true edge selection, * flush the selection from the vertices. */ - BM_mesh_select_mode_flush_ex(em->bm, SCE_SELECT_VERTEX); + BM_mesh_select_mode_flush_ex(em->bm, SCE_SELECT_VERTEX, BM_SELECT_LEN_FLUSH_RECALC_ALL); } } ED_uvedit_select_sync_flush(scene->toolsettings, em, select); diff --git a/source/blender/editors/uvedit/uvedit_rip.c b/source/blender/editors/uvedit/uvedit_rip.c index e1b9a287457..631b831411f 100644 --- a/source/blender/editors/uvedit/uvedit_rip.c +++ b/source/blender/editors/uvedit/uvedit_rip.c @@ -572,7 +572,7 @@ static UVRipPairs *uv_rip_pairs_from_loop(BMLoop *l_init, rip->loops = BLI_gset_ptr_new(__func__); /* We can rely on this stack being small, as we're walking down two sides of an edge loop, - * so the stack wont be much larger than the total number of fans at any one vertex. */ + * so the stack won't be much larger than the total number of fans at any one vertex. */ BLI_SMALLSTACK_DECLARE(stack, BMLoop *); /* Needed for cases when we walk onto loops which already have a side assigned, @@ -907,7 +907,7 @@ static int uv_rip_exec(bContext *C, wmOperator *op) float aspx, aspy; { - /* Note that we only want to run this on the */ + /* Note that we only want to run this on the. */ Object *obedit = CTX_data_edit_object(C); ED_uvedit_get_aspect(obedit, &aspx, &aspy); } diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index c10e132a4e2..7709b76290f 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -1296,7 +1296,7 @@ static int uv_select_edgering( l_step = uvedit_loop_find_other_radial_loop_with_visible_face( scene, l_step_opposite, cd_loop_uv_offset); if (l_step == NULL) { - /* Ensure we touch the opposite edge if we cant walk over it. */ + /* Ensure we touch the opposite edge if we can't walk over it. */ l_step = l_step_opposite; } } @@ -1351,7 +1351,7 @@ static void uv_select_linked_multi(Scene *scene, BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */ - /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320 + /* NOTE: we had 'use winding' so we don't consider overlapping islands as connected, see T44320 * this made *every* projection split the island into front/back islands. * Keep 'use_winding' to false, see: T50970. * @@ -1381,7 +1381,7 @@ static void uv_select_linked_multi(Scene *scene, BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { bool add_to_stack = true; - if (uv_sync_select && !select_faces) { + if (uv_sync_select) { /* Special case, vertex/edge & sync select being enabled. * * Without this, a second linked select will 'grow' each time as each new @@ -1392,6 +1392,7 @@ static void uv_select_linked_multi(Scene *scene, * - The only other fully selected face is connected or, * - There are no connected fully selected faces UV-connected to this loop. */ + BLI_assert(!select_faces); if (uvedit_face_select_test(scene, l->f, cd_loop_uv_offset)) { /* pass */ } diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 8ebf000baaa..28853bcdedf 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -76,7 +76,7 @@ typedef struct StitchPreviewer { float *preview_polys; /* uvs per polygon. */ uint *uvs_per_polygon; - /*number of preview polygons */ + /* Number of preview polygons. */ uint num_polys; /* preview data. These will be either the previewed vertices or edges * depending on stitch mode settings */ @@ -1069,8 +1069,7 @@ static int stitch_process_data(StitchStateContainer *ssc, } } - /* remember stitchable candidates as places the 'I' button */ - /* will stop at. */ + /* Remember stitchable candidates as places the 'I' button will stop at. */ for (int island_idx = 0; island_idx < state->element_map->totalIslands; island_idx++) { state->island_is_stitchable[island_idx] = island_stitch_data[island_idx].stitchableCandidate ? true : @@ -1747,7 +1746,8 @@ static void stitch_draw_vbo(GPUVertBuf *vbo, GPUPrimType prim_type, const float GPU_batch_discard(batch); } -/* TODO make things pretier : store batches inside StitchPreviewer instead of the bare verts pos */ +/* TODO: make things pretier : store batches inside StitchPreviewer instead of the bare verts pos + */ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg) { @@ -1818,7 +1818,7 @@ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void /* Closing line */ GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]); - /* j = uvs_per_polygon[i] - 1*/ + /* `j = uvs_per_polygon[i] - 1` */ GPU_vertbuf_attr_set( vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + j * 2]); @@ -1980,7 +1980,7 @@ static StitchState *stitch_init(bContext *C, counter++; state->uvs[counter] = element; } - /* pointer arithmetic to the rescue, as always :)*/ + /* Pointer arithmetic to the rescue, as always :). */ map[element - state->element_map->buf] = counter; } } @@ -2007,8 +2007,8 @@ static StitchState *stitch_init(bContext *C, all_edges[counter].first = NULL; all_edges[counter].flag = 0; all_edges[counter].element = element; - /* using an order policy, sort uvs according to address space. This avoids - * Having two different UvEdges with the same uvs on different positions */ + /* Using an order policy, sort UV's according to address space. + * This avoids having two different UvEdges with the same UV's on different positions. */ if (offset1 < offset2) { all_edges[counter].uv1 = offset1; all_edges[counter].uv2 = offset2; @@ -2381,9 +2381,9 @@ static int stitch_init_all(bContext *C, wmOperator *op) StitchState *state = ssc->states[ssc->active_object_index]; ssc->static_island %= state->element_map->totalIslands; - /* If the initial active object doesn't have any stitchable islands */ - /* then no active island will be seen in the UI. Make sure we're on */ - /* a stitchable object and island. */ + /* If the initial active object doesn't have any stitchable islands + * then no active island will be seen in the UI. + * Make sure we're on a stitchable object and island. */ if (!state->island_is_stitchable[ssc->static_island]) { goto_next_island(ssc); state = ssc->states[ssc->active_object_index]; diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 87ae112a237..0e9669d0f60 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -498,7 +498,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, /* pointers to modifier data for unwrap control */ ModifierData *md; SubsurfModifierData *smd_real; - /* modifier initialization data, will control what type of subdivision will happen*/ + /* Modifier initialization data, will control what type of subdivision will happen. */ SubsurfModifierData smd = {{NULL}}; /* Used to hold subsurfed Mesh */ DerivedMesh *derivedMesh, *initialDerived; @@ -509,7 +509,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, MEdge *subsurfedEdges; MPoly *subsurfedPolys; MLoop *subsurfedLoops; - /* number of vertices and faces for subsurfed mesh*/ + /* Number of vertices and faces for subsurfed mesh. */ int numOfEdges, numOfFaces; /* holds a map to editfaces for every subsurfed MFace. @@ -1367,7 +1367,7 @@ static void uv_map_rotation_matrix_ex(float result[4][4], rotup[2][2] = cosf(upangle) / radius; rotup[0][0] = 1.0f / radius; - /* calculate transforms*/ + /* Calculate transforms. */ mul_m4_series(result, rotup, rotside, viewmatrix, rotobj); } @@ -2319,7 +2319,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) const bool use_orthographic = RNA_boolean_get(op->ptr, "orthographic"); - /* Note: objects that aren't touched are set to NULL (to skip clipping). */ + /* NOTE: objects that aren't touched are set to NULL (to skip clipping). */ uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( view_layer, v3d, &objects_len); @@ -2905,7 +2905,7 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob) /* select all uv loops first - pack parameters needs this to make sure charts are registered */ ED_uvedit_select_all(bm); uvedit_unwrap_cube_project(bm, 1.0, false, NULL); - /* set the margin really quickly before the packing operation*/ + /* Set the margin really quickly before the packing operation. */ scene->toolsettings->uvcalc_margin = 0.001f; uvedit_pack_islands(scene, ob, bm); BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0})); |