diff options
Diffstat (limited to 'source/blender/editors')
94 files changed, 2474 insertions, 1625 deletions
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index ebe977420c6..ed4c574537b 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -2300,18 +2300,9 @@ static int animchannels_find_exec(bContext *C, wmOperator *op) if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - /* update filter text, and ensure that filter is enabled if there's something there - * NOTE: we turn the filter off if there's nothing (this is a quick shortcut for dismissing) - */ + /* update filter text */ RNA_string_get(op->ptr, "query", ac.ads->searchstr); - if (ac.ads->searchstr[0]) { - ac.ads->filterflag |= ADS_FILTER_BY_FCU_NAME; - } - else { - ac.ads->filterflag &= ~ADS_FILTER_BY_FCU_NAME; - } - /* redraw */ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); @@ -2693,7 +2684,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, AnimData *adt = ob->adt; /* set selection status */ - if (base->flag & BASE_SELECTABLED) { + if (base->flag & BASE_SELECTABLE) { if (selectmode == SELECT_INVERT) { /* swap select */ ED_object_base_select(base, BA_INVERT); diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 8892fed025a..c59d24bbdf8 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -245,6 +245,18 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction) /* update scene-pointer (no need to check for pinning yet, as not implemented) */ saction->ads.source = (ID *)ac->scene; + /* sync scene's "selected keys only" flag with our "only selected" flag + * XXX: This is a workaround for T55525. We shouldn't really be syncing the flags like this, + * but it's a simpler fix for now than also figuring out how the next/prev keyframe tools + * should work in the 3D View if we allowed full access to the timeline's dopesheet filters + * (i.e. we'd have to figure out where to host those settings, to be on a scene level like + * this flag currently is, along with several other unknowns) + */ + if (ac->scene->flag & SCE_KEYS_NO_SELONLY) + saction->ads.filterflag &= ~ADS_FILTER_ONLYSEL; + else + saction->ads.filterflag |= ADS_FILTER_ONLYSEL; + ac->datatype = ANIMCONT_TIMELINE; ac->data = &saction->ads; @@ -1209,7 +1221,7 @@ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, eAnim_Chan /* only include if this curve is active */ if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) { /* name based filtering... */ - if ( ((ads) && (ads->filterflag & ADS_FILTER_BY_FCU_NAME)) && (owner_id) ) { + if ( ((ads) && (ads->searchstr[0] != '\0')) && (owner_id) ) { if (skip_fcurve_with_name(ads, fcu, channel_type, owner, owner_id)) continue; } @@ -1441,7 +1453,7 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop /* only include if this track is active */ if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) { /* name based filtering... */ - if (((ads) && (ads->filterflag & ADS_FILTER_BY_FCU_NAME)) && (owner_id)) { + if (((ads) && (ads->searchstr[0] != '\0')) && (owner_id)) { bool track_ok = false, strip_ok = false; /* check if the name of the track, or the strips it has are ok... */ @@ -1621,7 +1633,7 @@ static size_t animdata_filter_gpencil_layers_data(ListBase *anim_data, bDopeShee /* active... */ if (!(filter_mode & ANIMFILTER_ACTIVE) || (gpl->flag & GP_LAYER_ACTIVE)) { /* skip layer if the name doesn't match the filter string */ - if ((ads) && (ads->filterflag & ADS_FILTER_BY_FCU_NAME)) { + if ((ads) && (ads->searchstr[0] != '\0')) { if (name_matches_dopesheet_filter(ads, gpl->info) == false) continue; } @@ -1713,7 +1725,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi */ if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) { /* layer visibility - we check both object and base, since these may not be in sync yet */ - if ((base->flag & BASE_VISIBLED) == 0) continue; + if ((base->flag & BASE_VISIBLE) == 0) continue; /* outliner restrict-flag */ if (ob->restrictflag & OB_RESTRICT_VIEW) continue; @@ -1729,7 +1741,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi * objects by the grouped status is on * - used to ease the process of doing multiple-character choreographies */ - if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) { + if (ads->filter_grp != NULL) { if (BKE_collection_has_object_recursive(ads->filter_grp, ob) == 0) continue; } @@ -2852,7 +2864,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m */ if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) { /* layer visibility - we check both object and base, since these may not be in sync yet */ - if ((base->flag & BASE_VISIBLED) == 0) + if ((base->flag & BASE_VISIBLE) == 0) return false; /* outliner restrict-flag */ @@ -2896,7 +2908,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m * objects by the grouped status is on * - used to ease the process of doing multiple-character choreographies */ - if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) { + if (ads->filter_grp != NULL) { if (BKE_collection_has_object_recursive(ads->filter_grp, ob) == 0) return false; } diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 98b57fcbd71..640239ccc60 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -202,6 +202,10 @@ set(ICON_NAMES group_uvs rna rna_add + mouse_lmb + mouse_mmb + mouse_rmb + mouse_drag outliner_ob_empty outliner_ob_mesh outliner_ob_curve diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 943191c8892..fee336ea768 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -690,6 +690,7 @@ void ANIM_list_elem_update(struct Main *bmain, struct Scene *scene, bAnimListEle void ANIM_sync_animchannels_to_data(const struct bContext *C); void ANIM_center_frame(struct bContext *C, int smooth_viewtx); + /* ************************************************* */ /* OPERATORS */ @@ -716,6 +717,10 @@ void ED_animedit_unlink_action(struct bContext *C, struct ID *id, struct AnimData *adt, struct bAction *act, struct ReportList *reports, bool force_delete); + +/* Drivers Editor - Utility to set up UI correctly */ +void ED_drivers_editor_init(struct bContext *C, struct ScrArea *sa); + /* ************************************************ */ #endif /* __ED_ANIM_API_H__ */ diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index a9c9e8c0fbd..32504db6498 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -225,14 +225,9 @@ typedef struct MirrTopoStore_t { } MirrTopoStore_t; bool ED_mesh_mirrtopo_recalc_check( - struct Mesh *me, struct DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store); -bool ED_mesh_mirrtopo_recalc_check__real_mesh( - struct Mesh *me, struct Mesh *dm, MirrTopoStore_t *mesh_topo_store); + struct Mesh *me, struct Mesh *me_eval, MirrTopoStore_t *mesh_topo_store); void ED_mesh_mirrtopo_init( - struct Mesh *me, struct DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store, - const bool skip_em_vert_array_init); -void ED_mesh_mirrtopo_init__real_mesh( - struct Mesh *me, struct Mesh *dm, MirrTopoStore_t *mesh_topo_store, + struct Mesh *me, struct Mesh *me_eval, MirrTopoStore_t *mesh_topo_store, const bool skip_em_vert_array_init); void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store); @@ -322,22 +317,17 @@ int join_mesh_shapes_exec(struct bContext *C, struct wmOperator *op); /* mirror lookup api */ int ED_mesh_mirror_spatial_table( - struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, const float co[3], char mode); -int ED_mesh_mirror_spatial_table__real_mesh( - struct Object *ob, struct BMEditMesh *em, struct Mesh *mesh, const float co[3], char mode); -int ED_mesh_mirror_topo_table(struct Object *ob, struct DerivedMesh *dm, char mode); -int ED_mesh_mirror_topo_table__real_mesh(struct Object *ob, struct Mesh *mesh, char mode); + struct Object *ob, struct BMEditMesh *em, struct Mesh *me_eval, const float co[3], char mode); +int ED_mesh_mirror_topo_table(struct Object *ob, struct Mesh *me_eval, char mode); /* 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 DerivedMesh *dm, int index, const bool use_topology); -int mesh_get_x_mirror_vert__real_mesh(struct Object *ob, struct Mesh *mesh, int index, const bool use_topology); +int mesh_get_x_mirror_vert(struct Object *ob, struct Mesh *me_eval, int index, const bool use_topology); struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em, struct BMVert *eve, const float co[3], int index, const bool use_topology); -int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm); -int *mesh_get_x_mirror_faces__real_mesh(struct Object *ob, struct BMEditMesh *em, struct Mesh *mesh); +int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em, struct Mesh *me_eval); int ED_mesh_mirror_get_vert(struct Object *ob, int index); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index d8a31e93a87..29f7edaebf0 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -40,6 +40,7 @@ struct Base; struct EnumPropertyItem; struct ID; struct Main; +struct Menu; struct ModifierData; struct Object; struct ReportList; @@ -58,12 +59,14 @@ struct PointerRNA; struct PropertyRNA; struct EnumPropertyItem; struct Depsgraph; +struct uiLayout; #include "DNA_object_enums.h" /* object_edit.c */ struct Object *ED_object_context(struct bContext *C); /* context.object */ struct Object *ED_object_active_context(struct bContext *C); /* context.object or context.active_object */ +void ED_hide_collections_menu_draw(const struct bContext *C, struct uiLayout *layout); /* object_ops.c */ void ED_operatortypes_object(void); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 9fcefc1e4b1..cb4048ac63e 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -60,6 +60,8 @@ struct Main; struct wmMsgBus; struct wmMsgSubscribeKey; struct wmMsgSubscribeValue; +struct wmOperatorType; +struct IDProperty; /* regions */ void ED_region_do_listen( @@ -311,6 +313,21 @@ int ED_operator_posemode_local(struct bContext *C); int ED_operator_mask(struct bContext *C); int ED_operator_camera(struct bContext *C); +/* screen_user_menu.c */ + +struct bUserMenu *ED_screen_user_menu_find(struct bContext *C); +struct bUserMenu *ED_screen_user_menu_ensure(struct bContext *C); + + +struct bUserMenuItem_Op *ED_screen_user_menu_item_find_operator( + struct ListBase *lb, + struct wmOperatorType *ot, struct IDProperty *prop, short opcontext); +void ED_screen_user_menu_item_add_operator( + struct ListBase *lb, const char *ui_name, + struct wmOperatorType *ot, struct IDProperty *prop, short opcontext); +void ED_screen_user_menu_item_remove( + struct ListBase *lb, struct bUserMenuItem *umi); +void ED_screen_user_menu_register(void); /* Cache display helpers */ @@ -333,4 +350,3 @@ void ED_area_type_hud_ensure(struct bContext *C, struct ScrArea *sa); #define ED_KEYMAP_HEADER 64 #endif /* __ED_SCREEN_H__ */ - diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 343bffa0082..68aeccdcc32 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -98,11 +98,28 @@ typedef struct ViewDepths { bool damaged; } ViewDepths; + +/* Rotate 3D cursor on placement. */ +enum eV3DCursorOrient { + V3D_CURSOR_ORIENT_NONE = 0, + V3D_CURSOR_ORIENT_VIEW, + V3D_CURSOR_ORIENT_GEOM, +}; + struct View3DCursor *ED_view3d_cursor3d_get(struct Scene *scene, struct View3D *v3d); -void ED_view3d_cursor3d_calc_mat3(const struct Scene *scene, const struct View3D *v3d, float mat[3][3]); -void ED_view3d_cursor3d_calc_mat4(const struct Scene *scene, const struct View3D *v3d, float mat[4][4]); -void ED_view3d_cursor3d_position(struct bContext *C, float fp[3], const int mval[2]); -void ED_view3d_cursor3d_update(struct bContext *C, const int mval[2]); +void ED_view3d_cursor3d_calc_mat3(const struct Scene *scene, const struct View3D *v3d, float mat[3][3]); +void ED_view3d_cursor3d_calc_mat4(const struct Scene *scene, const struct View3D *v3d, float mat[4][4]); +void ED_view3d_cursor3d_position( + struct bContext *C, const int mval[2], + const bool use_depth, + float cursor_co[3]); +void ED_view3d_cursor3d_position_rotation( + struct bContext *C, const int mval[2], + const bool use_depth, enum eV3DCursorOrient orientation, + float cursor_co[3], float cursor_quat[4]); +void ED_view3d_cursor3d_update( + struct bContext *C, const int mval[2], + bool use_depth, enum eV3DCursorOrient orientation); struct Camera *ED_view3d_camera_data_get(struct View3D *v3d, struct RegionView3D *rv3d); diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 659f6c97696..75e835ff1d3 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -273,10 +273,14 @@ DEF_ICON(RNA_ADD) DEF_ICON(BLANK093) DEF_ICON(BLANK094) DEF_ICON(BLANK095) - DEF_ICON(BLANK096) - DEF_ICON(BLANK097) - DEF_ICON(BLANK098) - DEF_ICON(BLANK099) +#endif + +DEF_ICON(MOUSE_LMB) +DEF_ICON(MOUSE_MMB) +DEF_ICON(MOUSE_RMB) +DEF_ICON(MOUSE_DRAG) + +#ifndef DEF_ICON_BLANK_SKIP DEF_ICON(BLANK100) DEF_ICON(BLANK101) DEF_ICON(BLANK102) @@ -292,8 +296,10 @@ DEF_ICON(RNA_ADD) DEF_ICON(BLANK112) DEF_ICON(BLANK113) DEF_ICON(BLANK114) - DEF_ICON(BLANK115) - DEF_ICON(BLANK116) +#endif +DEF_ICON(RESTRICT_VIEW_OFF) +DEF_ICON(RESTRICT_VIEW_ON) +#ifndef DEF_ICON_BLANK_SKIP DEF_ICON(BLANK116b) #endif @@ -319,8 +325,8 @@ DEF_ICON(OUTLINER_OB_LIGHTPROBE) #endif DEF_ICON(RESTRICT_COLOR_OFF) DEF_ICON(RESTRICT_COLOR_ON) -DEF_ICON(RESTRICT_VIEW_OFF) -DEF_ICON(RESTRICT_VIEW_ON) +DEF_ICON(HIDE_OFF) +DEF_ICON(HIDE_ON) DEF_ICON(RESTRICT_SELECT_OFF) DEF_ICON(RESTRICT_SELECT_ON) DEF_ICON(RESTRICT_RENDER_OFF) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 0b4817c8049..d4285f5a96e 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -418,6 +418,7 @@ uiPopupMenu *UI_popup_menu_begin_ex( struct bContext *C, const char *title, const char *block_name, int icon) ATTR_NONNULL(); void UI_popup_menu_end(struct bContext *C, struct uiPopupMenu *head); +bool UI_popup_menu_end_or_cancel(struct bContext *C, struct uiPopupMenu *head); struct uiLayout *UI_popup_menu_layout(uiPopupMenu *head); void UI_popup_menu_reports(struct bContext *C, struct ReportList *reports) ATTR_NONNULL(); @@ -534,6 +535,8 @@ void UI_block_flag_enable(uiBlock *block, int flag); void UI_block_flag_disable(uiBlock *block, int flag); void UI_block_translate(uiBlock *block, int x, int y); +bool UI_block_is_empty(const uiBlock *block); + int UI_but_return_value_get(uiBut *but); void UI_but_drag_set_id(uiBut *but, struct ID *id); @@ -1062,6 +1065,7 @@ void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C); void uiTemplateHeader3D(uiLayout *layout, struct bContext *C); void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C); void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C); +void uiTemplateCursorKeymap(uiLayout *layout, struct bContext *C); void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr); void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name); void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color); diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index 07ba3b90e11..882db88879d 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -44,6 +44,7 @@ set(SRC interface.c interface_align.c interface_anim.c + interface_context_menu.c interface_draw.c interface_eyedropper.c interface_eyedropper_color.c @@ -56,7 +57,6 @@ set(SRC interface_layout.c interface_ops.c interface_panel.c - interface_regions.c interface_region_color_picker.c interface_region_hud.c interface_region_menu_pie.c @@ -65,6 +65,7 @@ set(SRC interface_region_popup.c interface_region_search.c interface_region_tooltip.c + interface_regions.c interface_style.c interface_templates.c interface_utils.c diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 8c37054098b..a36f534807c 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -4031,6 +4031,16 @@ int UI_blocklist_min_y_get(ListBase *lb) return min; } +bool UI_block_is_empty(const uiBlock *block) +{ + for (const uiBut *but = block->buttons.first; but; but = but->next) { + if (!ELEM(but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) { + return false; + } + } + return true; +} + void UI_block_direction_set(uiBlock *block, char direction) { block->direction = direction; @@ -4780,4 +4790,3 @@ void UI_exit(void) ui_resources_free(); ui_but_clipboard_free(); } - diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c new file mode 100644 index 00000000000..cda81ba79cf --- /dev/null +++ b/source/blender/editors/interface/interface_context_menu.c @@ -0,0 +1,756 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/interface/interface_context_menu.c + * \ingroup edinterface + * + * Generic context popup menus. + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" + +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "BKE_addon.h" +#include "BKE_context.h" +#include "BKE_idprop.h" +#include "BKE_screen.h" + +#include "ED_screen.h" +#include "ED_keyframing.h" + +#include "UI_interface.h" + +#include "interface_intern.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +/* This hack is needed because we don't have a good way to re-reference keymap items once added: T42944 */ +#define USE_KEYMAP_ADD_HACK + +/* -------------------------------------------------------------------- */ +/** \name Button Context Menu + * \{ */ + +static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) +{ + uiBut *but = (uiBut *)arg1; + + if (but->optype) { + char shortcut_str[128]; + + IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + + /* complex code to change name of button */ + if (WM_key_event_operator_string( + C, but->optype->idname, but->opcontext, prop, true, + shortcut_str, sizeof(shortcut_str))) + { + ui_but_add_shortcut(but, shortcut_str, true); + } + else { + /* simply strip the shortcut */ + ui_but_add_shortcut(but, NULL, true); + } + } +} + +static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) +{ + wmWindowManager *wm = CTX_wm_manager(C); + uiBlock *block; + uiBut *but = (uiBut *)arg; + wmKeyMap *km; + wmKeyMapItem *kmi; + PointerRNA ptr; + uiLayout *layout; + uiStyle *style = UI_style_get_dpi(); + IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + + kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, true, &km); + BLI_assert(kmi != NULL); + + RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); + + block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); + UI_block_func_handle_set(block, but_shortcut_name_func, but); + UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT); + UI_block_direction_set(block, UI_DIR_CENTER_Y); + + layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style); + + uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); + + UI_block_bounds_set_popup(block, 6, -50, 26); + + return block; +} + +#ifdef USE_KEYMAP_ADD_HACK +static int g_kmi_id_hack; +#endif + +static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) +{ + wmWindowManager *wm = CTX_wm_manager(C); + uiBlock *block; + uiBut *but = (uiBut *)arg; + wmKeyMap *km; + wmKeyMapItem *kmi; + PointerRNA ptr; + uiLayout *layout; + uiStyle *style = UI_style_get_dpi(); + IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + int kmi_id; + + /* XXX this guess_opname can potentially return a different keymap than being found on adding later... */ + km = WM_keymap_guess_opname(C, but->optype->idname); + kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0); + kmi_id = kmi->id; + + /* copy properties, prop can be NULL for reset */ + if (prop) + prop = IDP_CopyProperty(prop); + WM_keymap_properties_reset(kmi, prop); + + /* update and get pointers again */ + WM_keyconfig_update(wm); + + km = WM_keymap_guess_opname(C, but->optype->idname); + kmi = WM_keymap_item_find_id(km, kmi_id); + + RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); + + block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); + UI_block_func_handle_set(block, but_shortcut_name_func, but); + UI_block_direction_set(block, UI_DIR_CENTER_Y); + + layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style); + + uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); + + UI_block_bounds_set_popup(block, 6, -50, 26); + +#ifdef USE_KEYMAP_ADD_HACK + g_kmi_id_hack = kmi_id; +#endif + return block; +} + +static void menu_add_shortcut_cancel(struct bContext *C, void *arg1) +{ + uiBut *but = (uiBut *)arg1; + wmKeyMap *km; + wmKeyMapItem *kmi; +#ifndef USE_KEYMAP_ADD_HACK + IDProperty *prop; +#endif + int kmi_id; + +#ifdef USE_KEYMAP_ADD_HACK + km = WM_keymap_guess_opname(C, but->optype->idname); + kmi_id = g_kmi_id_hack; + UNUSED_VARS(but); +#else + prop = (but->opptr) ? but->opptr->data : NULL; + kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km); +#endif + + kmi = WM_keymap_item_find_id(km, kmi_id); + WM_keymap_remove_item(km, kmi); +} + +static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) +{ + uiBut *but = (uiBut *)arg1; + UI_popup_block_invoke(C, menu_change_shortcut, but); +} + +static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) +{ + uiBut *but = (uiBut *)arg1; + wmKeyMap *km; + wmKeyMapItem *kmi; + IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + + kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, true, &km); + BLI_assert(kmi != NULL); + + WM_keymap_remove_item(km, kmi); + + but_shortcut_name_func(C, but, 0); +} + +static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) +{ + uiBut *but = (uiBut *)arg1; + UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL); +} + +static void popup_user_menu_add_or_replace_func(bContext *C, void *arg1, void *UNUSED(arg2)) +{ + uiBut *but = arg1; + bUserMenu *um = ED_screen_user_menu_ensure(C); + + char drawstr[sizeof(but->drawstr)]; + STRNCPY(drawstr, but->drawstr); + if (but->flag & UI_BUT_HAS_SEP_CHAR) { + char *sep = strrchr(drawstr, UI_SEP_CHAR); + if (sep) { + *sep = '\0'; + } + } + ED_screen_user_menu_item_add_operator( + &um->items, drawstr, + but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext); +} + +static void popup_user_menu_remove_func(bContext *UNUSED(C), void *arg1, void *arg2) +{ + bUserMenu *um = arg1; + bUserMenuItem *umi = arg2; + ED_screen_user_menu_item_remove(&um->items, umi); +} + +static void ui_but_menu_add_path_operators(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop) +{ + const PropertySubType subtype = RNA_property_subtype(prop); + wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true); + char filepath[FILE_MAX]; + char dir[FILE_MAXDIR]; + char file[FILE_MAXFILE]; + PointerRNA props_ptr; + + BLI_assert(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)); + UNUSED_VARS_NDEBUG(subtype); + + RNA_property_string_get(ptr, prop, filepath); + BLI_split_dirfile(filepath, dir, file, sizeof(dir), sizeof(file)); + + if (file[0]) { + BLI_assert(subtype == PROP_FILEPATH); + uiItemFullO_ptr( + layout, ot, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open File Externally"), + ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &props_ptr); + RNA_string_set(&props_ptr, "filepath", filepath); + } + + uiItemFullO_ptr( + layout, ot, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Location Externally"), + ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &props_ptr); + RNA_string_set(&props_ptr, "filepath", dir); +} + +bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) +{ + /* having this menu for some buttons makes no sense */ + if (but->type == UI_BTYPE_IMAGE) { + return false; + } + + uiPopupMenu *pup; + uiLayout *layout; + + { + uiStringInfo label = {BUT_GET_LABEL, NULL}; + + /* highly unlikely getting the label ever fails */ + UI_but_string_info_get(C, but, &label, NULL); + + pup = UI_popup_menu_begin(C, label.strinfo ? label.strinfo : "", ICON_NONE); + layout = UI_popup_menu_layout(pup); + if (label.strinfo) { + MEM_freeN(label.strinfo); + } + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); + } + + if (but->rnapoin.data && but->rnaprop) { + PointerRNA *ptr = &but->rnapoin; + PropertyRNA *prop = but->rnaprop; + const PropertyType type = RNA_property_type(prop); + const PropertySubType subtype = RNA_property_subtype(prop); + bool is_anim = RNA_property_animateable(ptr, prop); + bool is_editable = RNA_property_editable(ptr, prop); + /*bool is_idprop = RNA_property_is_idprop(prop);*/ /* XXX does not work as expected, not strictly needed */ + bool is_set = RNA_property_is_set(ptr, prop); + + /* second slower test, saved people finding keyframe items in menus when its not possible */ + if (is_anim) + is_anim = RNA_property_path_from_ID_check(&but->rnapoin, but->rnaprop); + + /* determine if we can key a single component of an array */ + const bool is_array = RNA_property_array_length(&but->rnapoin, but->rnaprop) != 0; + const bool is_array_component = (is_array && but->rnaindex != -1); + + const int static_override_status = RNA_property_static_override_status(ptr, prop, -1); + const bool is_static_overridable = (static_override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0; + + const int dynamic_override_status = RNA_property_dynamic_override_status(ptr, prop, -1); + const bool is_dynamic_overridable = (dynamic_override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0; + + /* Keyframes */ + if (but->flag & UI_BUT_ANIMATED_KEY) { + /* Set the (button_pointer, button_prop) and pointer data for Python access to the hovered ui element. */ + uiLayoutSetContextFromBut(layout, but); + + /* replace/delete keyfraemes */ + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframes"), + ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Single Keyframe"), + ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframes"), + ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Keyframe"), + ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 0); + } + else { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframe"), + ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframe"), + ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1); + } + + /* keyframe settings */ + uiItemS(layout); + + + } + else if (but->flag & UI_BUT_DRIVEN) { + /* pass */ + } + else if (is_anim) { + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframes"), + ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Single Keyframe"), + ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0); + } + else { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"), + ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); + } + } + + if ((but->flag & UI_BUT_ANIMATED) && (but->rnapoin.type != &RNA_NlaStrip)) { + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"), + ICON_KEY_DEHLT, "ANIM_OT_keyframe_clear_button", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Single Keyframes"), + ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0); + } + else { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"), + ICON_KEY_DEHLT, "ANIM_OT_keyframe_clear_button", "all", 1); + } + } + + /* Drivers */ + if (but->flag & UI_BUT_DRIVEN) { + uiItemS(layout); + + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Drivers"), + ICON_X, "ANIM_OT_driver_button_remove", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Driver"), + ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0); + } + else { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"), + ICON_X, "ANIM_OT_driver_button_remove", "all", 1); + } + + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"), + ICON_NONE, "ANIM_OT_copy_driver_button"); + if (ANIM_driver_can_paste()) { + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), + ICON_NONE, "ANIM_OT_paste_driver_button"); + } + + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Edit Driver"), + ICON_DRIVER, "ANIM_OT_driver_button_edit"); + + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"), + ICON_NONE, "SCREEN_OT_drivers_editor_show"); + } + else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) { + /* pass */ + } + else if (is_anim) { + uiItemS(layout); + + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"), + ICON_DRIVER, "ANIM_OT_driver_button_add"); + + if (ANIM_driver_can_paste()) { + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), + ICON_NONE, "ANIM_OT_paste_driver_button"); + } + + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"), + ICON_NONE, "SCREEN_OT_drivers_editor_show"); + } + + /* Keying Sets */ + /* TODO: check on modifyability of Keying Set when doing this */ + if (is_anim) { + uiItemS(layout); + + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add All to Keying Set"), + ICON_KEYINGSET, "ANIM_OT_keyingset_button_add", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single to Keying Set"), + ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 0); + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"), + ICON_NONE, "ANIM_OT_keyingset_button_remove"); + } + else { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Keying Set"), + ICON_KEYINGSET, "ANIM_OT_keyingset_button_add", "all", 1); + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"), + ICON_NONE, "ANIM_OT_keyingset_button_remove"); + } + } + + /* Dynamic Override Operators */ + if (is_editable && is_dynamic_overridable) { + uiItemS(layout); + uiItemFullO(layout, "SCENE_OT_view_layer_override_add", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); + } + + if (is_static_overridable) { + wmOperatorType *ot; + PointerRNA op_ptr; + /* Override Operators */ + uiItemS(layout); + + if (but->flag & UI_BUT_OVERRIDEN) { + if (is_array_component) { +#if 0 /* Disabled for now. */ + ot = WM_operatortype_find("UI_OT_override_type_set_button", false); + uiItemFullO_ptr( + layout, ot, "Overrides Type", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", true); + uiItemFullO_ptr( + layout, ot, "Single Override Type", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", false); +#endif + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Overrides"), + ICON_X, "UI_OT_override_remove_button", "all", true); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Single Override"), + ICON_X, "UI_OT_override_remove_button", "all", false); + } + else { +#if 0 /* Disabled for now. */ + uiItemFullO( + layout, "UI_OT_override_type_set_button", "Override Type", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", false); +#endif + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Override"), + ICON_X, "UI_OT_override_remove_button", "all", true); + } + } + else { + if (is_array_component) { + ot = WM_operatortype_find("UI_OT_override_type_set_button", false); + uiItemFullO_ptr( + layout, ot, "Define Overrides", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", true); + uiItemFullO_ptr( + layout, ot, "Define Single Override", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", false); + } + else { + uiItemFullO( + layout, "UI_OT_override_type_set_button", "Define Override", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", false); + } + } + } + + uiItemS(layout); + + /* Property Operators */ + + /* Copy Property Value + * Paste Property Value */ + + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset All to Default Values"), + ICON_LOOP_BACK, "UI_OT_reset_default_button", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Single to Default Value"), + ICON_NONE, "UI_OT_reset_default_button", "all", 0); + } + else { + uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"), + ICON_LOOP_BACK, "UI_OT_reset_default_button", "all", 1); + } + if (is_editable /*&& is_idprop*/ && is_set) { + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unset"), + ICON_NONE, "UI_OT_unset_property_button"); + } + + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy All To Selected"), + ICON_NONE, "UI_OT_copy_to_selected_button", "all", true); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Single To Selected"), + ICON_NONE, "UI_OT_copy_to_selected_button", "all", false); + } + else { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy To Selected"), + ICON_NONE, "UI_OT_copy_to_selected_button", "all", true); + } + + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"), + ICON_NONE, "UI_OT_copy_data_path_button"); + + uiItemS(layout); + + if (type == PROP_STRING && ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)) { + ui_but_menu_add_path_operators(layout, ptr, prop); + uiItemS(layout); + } + } + + /* Operator buttons */ + if (but->optype) { + uiBlock *block = uiLayoutGetBlock(layout); + uiBut *but2; + IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + int w = uiLayoutGetWidth(layout); + wmKeyMap *km; + /* We want to know if this op has a shortcut, be it hotkey or not. */ + wmKeyMapItem *kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, false, &km); + + /* We do have a shortcut, but only keyboard ones are editbale that way... */ + if (kmi) { + if (ISKEYBOARD(kmi->type)) { +#if 0 /* would rather use a block but, but gets weirdly positioned... */ + uiDefBlockBut( + block, menu_change_shortcut, but, "Change Shortcut", + 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, ""); +#endif + + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_HAND, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + UI_but_func_set(but2, popup_change_shortcut_func, but, NULL); + + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_NONE, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + UI_but_func_set(but2, remove_shortcut_func, but, NULL); + } + else { + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_HAND, IFACE_("Non-Keyboard Shortcut"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, + TIP_("Only keyboard shortcuts can be edited that way, " + "please use User Preferences otherwise")); + UI_but_flag_enable(but2, UI_BUT_DISABLED); + } + } + /* only show 'add' if there's a suitable key map for it to go in */ + else if (WM_keymap_guess_opname(C, but->optype->idname)) { + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_HAND, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Shortcut"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + UI_but_func_set(but2, popup_add_shortcut_func, but, NULL); + } + + uiItemS(layout); + + { + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_MENU_PANEL, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Favorites Menu"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, + "Add to a user defined context menu (stored in the user preferences)"); + UI_but_func_set(but2, popup_user_menu_add_or_replace_func, but, NULL); + + bUserMenu *um = ED_screen_user_menu_find(C); + if (um) { + bUserMenuItem_Op *umi_op = ED_screen_user_menu_item_find_operator( + &um->items, but->optype, prop, but->opcontext); + if (umi_op != NULL) { + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_CANCEL, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Favorites Menu"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + UI_but_func_set(but2, popup_user_menu_remove_func, um, umi_op); + } + } + } + + /* Set the operator pointer for python access */ + uiLayoutSetContextFromBut(layout, but); + + uiItemS(layout); + } + + /* Show header tools for header buttons. */ + if (ui_block_is_menu(but->block) == false) { + ARegion *ar = CTX_wm_region(C); + if (ar && (ar->regiontype == RGN_TYPE_HEADER)) { + uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL); + uiItemS(layout); + } + } + + { /* Docs */ + char buf[512]; + + if (UI_but_online_manual_id(but, buf, sizeof(buf))) { + PointerRNA ptr_props; + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), + ICON_URL, "WM_OT_doc_view_manual_ui_context"); + + uiItemFullO( + layout, "WM_OT_doc_view", + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), + ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr_props); + RNA_string_set(&ptr_props, "doc_id", buf); + + /* XXX inactive option, not for public! */ +#if 0 + uiItemFullO( + layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr_props); + RNA_string_set(&ptr_props, "doc_id", buf); + RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop)); +#endif + } + } + + if (but->optype) { + uiItemO(layout, NULL, + ICON_NONE, "UI_OT_copy_python_command_button"); + } + + /* perhaps we should move this into (G.debug & G_DEBUG) - campbell */ + if (U.flag & USER_DEVELOPER_UI) { + if (ui_block_is_menu(but->block) == false) { + uiItemFullO(layout, "UI_OT_editsource", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); + } + } + + if (BKE_addon_find(&U.addons, "ui_translate")) { + uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); + } + + MenuType *mt = WM_menutype_find("WM_MT_button_context", true); + if (mt) { + UI_menutype_draw(C, mt, uiLayoutColumn(layout, false)); + } + + return UI_popup_menu_end_or_cancel(C, pup); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Panel Context Menu + * \{ */ + +/** + * menu to show when right clicking on the panel header + */ +void ui_popup_context_menu_for_panel(bContext *C, ARegion *ar, Panel *pa) +{ + bScreen *sc = CTX_wm_screen(C); + const bool has_panel_category = UI_panel_category_is_visible(ar); + const bool any_item_visible = has_panel_category; + PointerRNA ptr; + uiPopupMenu *pup; + uiLayout *layout; + + if (!any_item_visible) { + return; + } + + RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr); + + pup = UI_popup_menu_begin(C, IFACE_("Panel"), ICON_NONE); + layout = UI_popup_menu_layout(pup); + + if (has_panel_category) { + char tmpstr[80]; + BLI_snprintf(tmpstr, sizeof(tmpstr), "%s" UI_SEP_CHAR_S "%s", IFACE_("Pin"), IFACE_("Shift+Left Mouse")); + uiItemR(layout, &ptr, "use_pin", 0, tmpstr, ICON_NONE); + + /* evil, force shortcut flag */ + { + uiBlock *block = uiLayoutGetBlock(layout); + uiBut *but = block->buttons.last; + but->flag |= UI_BUT_HAS_SEP_CHAR; + } + } + UI_popup_menu_end(C, pup); +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 1ff05fa85cc..bb54f26131a 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -27,7 +27,6 @@ * \ingroup edinterface */ - #include <float.h> #include <limits.h> #include <math.h> @@ -40,22 +39,18 @@ #include "DNA_brush_types.h" -#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "BLI_math.h" #include "BLI_listbase.h" #include "BLI_linklist.h" -#include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_string_utf8.h" #include "BLI_string_cursor_utf8.h" #include "BLI_rect.h" #include "BLI_utildefines.h" -#include "BLT_translation.h" - #include "PIL_time.h" #include "BKE_colorband.h" @@ -63,7 +58,6 @@ #include "BKE_brush.h" #include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_idprop.h" #include "BKE_report.h" #include "BKE_screen.h" #include "BKE_tracking.h" @@ -72,7 +66,6 @@ #include "ED_screen.h" #include "ED_undo.h" -#include "ED_keyframing.h" #include "UI_interface.h" #include "UI_view2d.h" @@ -89,6 +82,7 @@ #ifdef WITH_INPUT_IME # include "wm_window.h" +# include "BLT_translation.h" # include "BLT_lang.h" #endif @@ -111,9 +105,6 @@ #define UI_MAX_PASSWORD_STR 128 -/* This hack is needed because we don't have a good way to re-reference keymap items once added: T42944 */ -#define USE_KEYMAP_ADD_HACK - /* proto */ static int ui_do_but_EXIT(bContext *C, uiBut *but, struct uiHandleButtonData *data, const wmEvent *event); static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b); @@ -1300,7 +1291,6 @@ typedef struct uiDragToggleHandle { bool is_init; bool is_set; float but_cent_start[2]; - eButType but_type_start; bool xy_lock[2]; int xy_init[2]; @@ -1308,7 +1298,7 @@ typedef struct uiDragToggleHandle { } uiDragToggleHandle; static bool ui_drag_toggle_set_xy_xy( - bContext *C, ARegion *ar, const bool is_set, const eButType but_type_start, + bContext *C, ARegion *ar, const bool is_set, const int xy_src[2], const int xy_dst[2]) { /* popups such as layers won't re-evaluate on redraw */ @@ -1332,7 +1322,7 @@ static bool ui_drag_toggle_set_xy_xy( if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) { /* execute the button */ - if (ui_drag_toggle_but_is_supported(but) && but->type == but_type_start) { + if (ui_drag_toggle_but_is_supported(but)) { /* is it pressed? */ bool is_set_but = ui_drag_toggle_but_is_pushed(but); if (is_set_but != is_set) { @@ -1404,7 +1394,7 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const /* touch all buttons between last mouse coord and this one */ - do_draw = ui_drag_toggle_set_xy_xy(C, ar, drag_info->is_set, drag_info->but_type_start, drag_info->xy_last, xy); + do_draw = ui_drag_toggle_set_xy_xy(C, ar, drag_info->is_set, drag_info->xy_last, xy); if (do_draw) { ED_region_tag_redraw(ar); @@ -1783,7 +1773,6 @@ static bool ui_but_drag_init( drag_info->is_set = ui_drag_toggle_but_is_pushed(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); - drag_info->but_type_start = but->type; copy_v2_v2_int(drag_info->xy_init, &event->x); copy_v2_v2_int(drag_info->xy_last, &event->x); @@ -6495,602 +6484,6 @@ static int ui_do_but_TRACKPREVIEW( return WM_UI_HANDLER_CONTINUE; } -static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) -{ - uiBut *but = (uiBut *)arg1; - - if (but->optype) { - char shortcut_str[128]; - - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; - - /* complex code to change name of button */ - if (WM_key_event_operator_string( - C, but->optype->idname, but->opcontext, prop, true, - shortcut_str, sizeof(shortcut_str))) - { - ui_but_add_shortcut(but, shortcut_str, true); - } - else { - /* simply strip the shortcut */ - ui_but_add_shortcut(but, NULL, true); - } - } -} - -static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) -{ - wmWindowManager *wm = CTX_wm_manager(C); - uiBlock *block; - uiBut *but = (uiBut *)arg; - wmKeyMap *km; - wmKeyMapItem *kmi; - PointerRNA ptr; - uiLayout *layout; - uiStyle *style = UI_style_get_dpi(); - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; - - kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, true, &km); - BLI_assert(kmi != NULL); - - RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); - - block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); - UI_block_func_handle_set(block, but_shortcut_name_func, but); - UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT); - UI_block_direction_set(block, UI_DIR_CENTER_Y); - - layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style); - - uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); - - UI_block_bounds_set_popup(block, 6, -50, 26); - - return block; -} - -#ifdef USE_KEYMAP_ADD_HACK -static int g_kmi_id_hack; -#endif - -static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) -{ - wmWindowManager *wm = CTX_wm_manager(C); - uiBlock *block; - uiBut *but = (uiBut *)arg; - wmKeyMap *km; - wmKeyMapItem *kmi; - PointerRNA ptr; - uiLayout *layout; - uiStyle *style = UI_style_get_dpi(); - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; - int kmi_id; - - /* XXX this guess_opname can potentially return a different keymap than being found on adding later... */ - km = WM_keymap_guess_opname(C, but->optype->idname); - kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0); - kmi_id = kmi->id; - - /* copy properties, prop can be NULL for reset */ - if (prop) - prop = IDP_CopyProperty(prop); - WM_keymap_properties_reset(kmi, prop); - - /* update and get pointers again */ - WM_keyconfig_update(wm); - - km = WM_keymap_guess_opname(C, but->optype->idname); - kmi = WM_keymap_item_find_id(km, kmi_id); - - RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); - - block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); - UI_block_func_handle_set(block, but_shortcut_name_func, but); - UI_block_direction_set(block, UI_DIR_CENTER_Y); - - layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style); - - uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); - - UI_block_bounds_set_popup(block, 6, -50, 26); - -#ifdef USE_KEYMAP_ADD_HACK - g_kmi_id_hack = kmi_id; -#endif - return block; -} - -static void menu_add_shortcut_cancel(struct bContext *C, void *arg1) -{ - uiBut *but = (uiBut *)arg1; - wmKeyMap *km; - wmKeyMapItem *kmi; -#ifndef USE_KEYMAP_ADD_HACK - IDProperty *prop; -#endif - int kmi_id; - -#ifdef USE_KEYMAP_ADD_HACK - km = WM_keymap_guess_opname(C, but->optype->idname); - kmi_id = g_kmi_id_hack; - UNUSED_VARS(but); -#else - prop = (but->opptr) ? but->opptr->data : NULL; - kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km); -#endif - - kmi = WM_keymap_item_find_id(km, kmi_id); - WM_keymap_remove_item(km, kmi); -} - -static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) -{ - uiBut *but = (uiBut *)arg1; - UI_popup_block_invoke(C, menu_change_shortcut, but); -} - -static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) -{ - uiBut *but = (uiBut *)arg1; - wmKeyMap *km; - wmKeyMapItem *kmi; - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; - - kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, true, &km); - BLI_assert(kmi != NULL); - - WM_keymap_remove_item(km, kmi); - - but_shortcut_name_func(C, but, 0); -} - -static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) -{ - uiBut *but = (uiBut *)arg1; - UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL); -} - -/** - * menu to chow when right clicking on the panel header - */ -void ui_panel_menu(bContext *C, ARegion *ar, Panel *pa) -{ - bScreen *sc = CTX_wm_screen(C); - const bool has_panel_category = UI_panel_category_is_visible(ar); - const bool any_item_visible = has_panel_category; - PointerRNA ptr; - uiPopupMenu *pup; - uiLayout *layout; - - if (!any_item_visible) { - return; - } - - RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr); - - pup = UI_popup_menu_begin(C, IFACE_("Panel"), ICON_NONE); - layout = UI_popup_menu_layout(pup); - - if (has_panel_category) { - char tmpstr[80]; - BLI_snprintf(tmpstr, sizeof(tmpstr), "%s" UI_SEP_CHAR_S "%s", IFACE_("Pin"), IFACE_("Shift+Left Mouse")); - uiItemR(layout, &ptr, "use_pin", 0, tmpstr, ICON_NONE); - - /* evil, force shortcut flag */ - { - uiBlock *block = uiLayoutGetBlock(layout); - uiBut *but = block->buttons.last; - but->flag |= UI_BUT_HAS_SEP_CHAR; - } - } - UI_popup_menu_end(C, pup); -} - -static void ui_but_menu_add_path_operators(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop) -{ - const PropertySubType subtype = RNA_property_subtype(prop); - wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true); - char filepath[FILE_MAX]; - char dir[FILE_MAXDIR]; - char file[FILE_MAXFILE]; - PointerRNA props_ptr; - - BLI_assert(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)); - UNUSED_VARS_NDEBUG(subtype); - - RNA_property_string_get(ptr, prop, filepath); - BLI_split_dirfile(filepath, dir, file, sizeof(dir), sizeof(file)); - - if (file[0]) { - BLI_assert(subtype == PROP_FILEPATH); - uiItemFullO_ptr( - layout, ot, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open File Externally"), - ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &props_ptr); - RNA_string_set(&props_ptr, "filepath", filepath); - } - - uiItemFullO_ptr( - layout, ot, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Location Externally"), - ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &props_ptr); - RNA_string_set(&props_ptr, "filepath", dir); -} - -static bool ui_but_menu(bContext *C, uiBut *but) -{ - uiPopupMenu *pup; - uiLayout *layout; - MenuType *mt = WM_menutype_find("WM_MT_button_context", true); - bool is_array, is_array_component; - uiStringInfo label = {BUT_GET_LABEL, NULL}; - wmOperatorType *ot; - PointerRNA op_ptr; - -/* if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)*/ -/* return 0;*/ - - /* having this menu for some buttons makes no sense */ - if (but->type == UI_BTYPE_IMAGE) { - return false; - } - - /* highly unlikely getting the label ever fails */ - UI_but_string_info_get(C, but, &label, NULL); - - pup = UI_popup_menu_begin(C, label.strinfo ? label.strinfo : "", ICON_NONE); - layout = UI_popup_menu_layout(pup); - if (label.strinfo) - MEM_freeN(label.strinfo); - - uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); - - if (but->rnapoin.data && but->rnaprop) { - PointerRNA *ptr = &but->rnapoin; - PropertyRNA *prop = but->rnaprop; - const PropertyType type = RNA_property_type(prop); - const PropertySubType subtype = RNA_property_subtype(prop); - bool is_anim = RNA_property_animateable(ptr, prop); - bool is_editable = RNA_property_editable(ptr, prop); - /*bool is_idprop = RNA_property_is_idprop(prop);*/ /* XXX does not work as expected, not strictly needed */ - bool is_set = RNA_property_is_set(ptr, prop); - - const int static_override_status = RNA_property_static_override_status(ptr, prop, -1); - const bool is_static_overridable = (static_override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0; - - const int dynamic_override_status = RNA_property_dynamic_override_status(ptr, prop, -1); - const bool is_dynamic_overridable = (dynamic_override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0; - - /* second slower test, saved people finding keyframe items in menus when its not possible */ - if (is_anim) - is_anim = RNA_property_path_from_ID_check(&but->rnapoin, but->rnaprop); - - /* determine if we can key a single component of an array */ - is_array = RNA_property_array_length(&but->rnapoin, but->rnaprop) != 0; - is_array_component = (is_array && but->rnaindex != -1); - - /* Keyframes */ - if (but->flag & UI_BUT_ANIMATED_KEY) { - /* replace/delete keyfraemes */ - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframes"), - ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Single Keyframe"), - ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframes"), - ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Keyframe"), - ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 0); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframe"), - ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframe"), - ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1); - } - - /* keyframe settings */ - uiItemS(layout); - - - } - else if (but->flag & UI_BUT_DRIVEN) { - /* pass */ - } - else if (is_anim) { - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframes"), - ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Single Keyframe"), - ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"), - ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); - } - } - - if ((but->flag & UI_BUT_ANIMATED) && (but->rnapoin.type != &RNA_NlaStrip)) { - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"), - ICON_KEY_DEHLT, "ANIM_OT_keyframe_clear_button", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Single Keyframes"), - ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"), - ICON_KEY_DEHLT, "ANIM_OT_keyframe_clear_button", "all", 1); - } - } - - /* Drivers */ - if (but->flag & UI_BUT_DRIVEN) { - uiItemS(layout); - - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Drivers"), - ICON_X, "ANIM_OT_driver_button_remove", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Driver"), - ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"), - ICON_X, "ANIM_OT_driver_button_remove", "all", 1); - } - - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"), - ICON_NONE, "ANIM_OT_copy_driver_button"); - if (ANIM_driver_can_paste()) { - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), - ICON_NONE, "ANIM_OT_paste_driver_button"); - } - - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Edit Driver"), - ICON_DRIVER, "ANIM_OT_driver_button_edit"); - - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"), - ICON_NONE, "SCREEN_OT_drivers_editor_show"); - } - else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) { - /* pass */ - } - else if (is_anim) { - uiItemS(layout); - - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"), - ICON_DRIVER, "ANIM_OT_driver_button_add"); - - if (ANIM_driver_can_paste()) { - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), - ICON_NONE, "ANIM_OT_paste_driver_button"); - } - - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"), - ICON_NONE, "SCREEN_OT_drivers_editor_show"); - } - - /* Keying Sets */ - /* TODO: check on modifyability of Keying Set when doing this */ - if (is_anim) { - uiItemS(layout); - - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add All to Keying Set"), - ICON_KEYINGSET, "ANIM_OT_keyingset_button_add", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single to Keying Set"), - ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 0); - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"), - ICON_NONE, "ANIM_OT_keyingset_button_remove"); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Keying Set"), - ICON_KEYINGSET, "ANIM_OT_keyingset_button_add", "all", 1); - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"), - ICON_NONE, "ANIM_OT_keyingset_button_remove"); - } - } - - /* Dynamic Override Operators */ - if (is_editable && is_dynamic_overridable) { - uiItemS(layout); - uiItemFullO(layout, "SCENE_OT_view_layer_override_add", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); - } - - if (is_static_overridable) { - /* Static Override Operators */ - uiItemS(layout); - - if (but->flag & UI_BUT_OVERRIDEN) { - if (is_array_component) { -#if 0 /* Disabled for now. */ - ot = WM_operatortype_find("UI_OT_override_type_set_button", false); - uiItemFullO_ptr(layout, ot, "Overrides Type", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_boolean_set(&op_ptr, "all", true); - uiItemFullO_ptr(layout, ot, "Single Override Type", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_boolean_set(&op_ptr, "all", false); -#endif - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Overrides"), - ICON_X, "UI_OT_override_remove_button", "all", true); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Single Override"), - ICON_X, "UI_OT_override_remove_button", "all", false); - } - else { -#if 0 /* Disabled for now. */ - uiItemFullO(layout, "UI_OT_override_type_set_button", "Override Type", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_boolean_set(&op_ptr, "all", false); -#endif - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Override"), - ICON_X, "UI_OT_override_remove_button", "all", true); - } - } - else { - if (is_array_component) { - ot = WM_operatortype_find("UI_OT_override_type_set_button", false); - uiItemFullO_ptr(layout, ot, "Define Overrides", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_boolean_set(&op_ptr, "all", true); - uiItemFullO_ptr(layout, ot, "Define Single Override", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_boolean_set(&op_ptr, "all", false); - } - else { - uiItemFullO(layout, "UI_OT_override_type_set_button", "Define Override", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_boolean_set(&op_ptr, "all", false); - } - } - } - - uiItemS(layout); - - /* Property Operators */ - - /* Copy Property Value - * Paste Property Value */ - - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset All to Default Values"), - ICON_LOOP_BACK, "UI_OT_reset_default_button", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Single to Default Value"), - ICON_NONE, "UI_OT_reset_default_button", "all", 0); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"), - ICON_LOOP_BACK, "UI_OT_reset_default_button", "all", 1); - } - if (is_editable /*&& is_idprop*/ && is_set) { - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unset"), - ICON_NONE, "UI_OT_unset_property_button"); - } - - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy All To Selected"), - ICON_NONE, "UI_OT_copy_to_selected_button", "all", true); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Single To Selected"), - ICON_NONE, "UI_OT_copy_to_selected_button", "all", false); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy To Selected"), - ICON_NONE, "UI_OT_copy_to_selected_button", "all", true); - } - - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"), - ICON_NONE, "UI_OT_copy_data_path_button"); - - uiItemS(layout); - - if (type == PROP_STRING && ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)) { - ui_but_menu_add_path_operators(layout, ptr, prop); - uiItemS(layout); - } - } - - /* Operator buttons */ - if (but->optype) { - uiBlock *block = uiLayoutGetBlock(layout); - uiBut *but2; - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; - int w = uiLayoutGetWidth(layout); - wmKeyMap *km; - /* We want to know if this op has a shortcut, be it hotkey or not. */ - wmKeyMapItem *kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, false, &km); - - /* We do have a shortcut, but only keyboard ones are editbale that way... */ - if (kmi) { - if (ISKEYBOARD(kmi->type)) { -#if 0 /* would rather use a block but, but gets weirdly positioned... */ - uiDefBlockBut(block, menu_change_shortcut, but, "Change Shortcut", - 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, ""); -#endif - - but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_HAND, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"), - 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); - UI_but_func_set(but2, popup_change_shortcut_func, but, NULL); - - but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_NONE, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"), - 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); - UI_but_func_set(but2, remove_shortcut_func, but, NULL); - } - else { - but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_HAND, IFACE_("Non-Keyboard Shortcut"), - 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Only keyboard shortcuts can be edited that way, " - "please use User Preferences otherwise")); - UI_but_flag_enable(but2, UI_BUT_DISABLED); - } - } - /* only show 'add' if there's a suitable key map for it to go in */ - else if (WM_keymap_guess_opname(C, but->optype->idname)) { - but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_HAND, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Shortcut"), - 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); - UI_but_func_set(but2, popup_add_shortcut_func, but, NULL); - } - - /* Set the operator pointer for python access */ - uiLayoutSetContextFromBut(layout, but); - - uiItemS(layout); - } - - /* Show header tools for header buttons. */ - if (ui_block_is_menu(but->block) == false) { - ARegion *ar = CTX_wm_region(C); - if (ar && (ar->regiontype == RGN_TYPE_HEADER)) { - uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL); - uiItemS(layout); - } - } - - { /* Docs */ - char buf[512]; - - if (UI_but_online_manual_id(but, buf, sizeof(buf))) { - PointerRNA ptr_props; - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), - ICON_URL, "WM_OT_doc_view_manual_ui_context"); - - uiItemFullO( - layout, "WM_OT_doc_view", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), - ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr_props); - RNA_string_set(&ptr_props, "doc_id", buf); - - /* XXX inactive option, not for public! */ -#if 0 - uiItemFullO( - layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr_props); - RNA_string_set(&ptr_props, "doc_id", buf); - RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop)); -#endif - } - } - - if (but->optype) { - uiItemO(layout, NULL, - ICON_NONE, "UI_OT_copy_python_command_button"); - } - - /* perhaps we should move this into (G.debug & G_DEBUG) - campbell */ - if (ui_block_is_menu(but->block) == false) { - uiItemFullO(layout, "UI_OT_editsource", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); - } - uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); - - mt = WM_menutype_find("WM_MT_button_context", true); - if (mt) { - UI_menutype_draw(C, mt, uiLayoutColumn(layout, false)); - } - - UI_popup_menu_end(C, pup); - - return true; -} - static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *event) { uiHandleButtonData *data; @@ -7134,7 +6527,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * (event->val == KM_PRESS)) { /* RMB has two options now */ - if (ui_but_menu(C, but)) { + if (ui_popup_context_menu_for_button(C, but)) { return WM_UI_HANDLER_BREAK; } } @@ -9602,6 +8995,11 @@ static int ui_handle_menu_event( } #endif + /* Don't handle double click events, rehandle as regular press/release. */ + if (retval == WM_UI_HANDLER_CONTINUE && event->val == KM_DBL_CLICK) { + return retval; + } + /* if we set a menu return value, ensure we continue passing this on to * lower menus and buttons, so always set continue then, and if we are * inside the region otherwise, ensure we swallow the event */ @@ -10182,6 +9580,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE { ARegion *ar; uiBut *but; + int retval = WM_UI_HANDLER_CONTINUE; ar = CTX_wm_menu(C); if (!ar) @@ -10225,29 +9624,32 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE if ((but_other->flag & UI_BUT_DISABLED) == 0) { ui_handle_button_activate(C, ar, but_other, BUTTON_ACTIVATE_OVER); button_activate_state(C, but_other, BUTTON_STATE_MENU_OPEN); + retval = WM_UI_HANDLER_BREAK; } } else if (data->state == BUTTON_STATE_MENU_OPEN) { - int retval; - /* handle events for menus and their buttons recursively, * this will handle events from the top to the bottom menu */ - if (data->menu) + if (data->menu) { retval = ui_handle_menus_recursive(C, event, data->menu, 0, false, false, false); + } /* handle events for the activated button */ if ((data->menu && (retval == WM_UI_HANDLER_CONTINUE)) || (event->type == TIMER)) { - if (data->menu && data->menu->menuretval) + if (data->menu && data->menu->menuretval) { ui_handle_button_return_submenu(C, event, but); - else - ui_handle_button_event(C, event, but); + retval = WM_UI_HANDLER_BREAK; + } + else { + retval = ui_handle_button_event(C, event, but); + } } } else { /* handle events for the activated button */ - ui_handle_button_event(C, event, but); + retval = ui_handle_button_event(C, event, but); } } @@ -10258,6 +9660,14 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE /* delayed apply callbacks */ ui_apply_but_funcs_after(C); + /* Don't handle double-click events, + * these will be converted into regular clicks which we handle. */ + if (retval == WM_UI_HANDLER_CONTINUE) { + if (event->val == KM_DBL_CLICK) { + return WM_UI_HANDLER_CONTINUE; + } + } + /* we block all events, this is modal interaction */ return WM_UI_HANDLER_BREAK; } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 539dd05b242..a8feaedf717 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -858,10 +858,10 @@ static void ui_studiolight_kill_icon_preview_job(wmWindowManager *wm, int icon_i icon->obj = NULL; } -static void ui_studiolight_free_function(StudioLight * sl, void* data) +static void ui_studiolight_free_function(StudioLight *sl, void *data) { wmWindowManager *wm = data; - + // get icons_id, get icons and kill wm jobs if (sl->icon_id_radiance) { ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_radiance); @@ -920,7 +920,7 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi di->data.buffer.image = img; wmJob *wm_job = WM_jobs_get(wm, CTX_wm_window(C), icon, "StudioLight Icon", 0, WM_JOB_TYPE_STUDIOLIGHT); - Icon** tmp = MEM_callocN(sizeof(Icon*), __func__); + Icon **tmp = MEM_callocN(sizeof(Icon *), __func__); *tmp = icon; WM_jobs_customdata_set(wm_job, tmp, MEM_freeN); WM_jobs_timer(wm_job, 0.01, 0, NC_WINDOW); @@ -1647,4 +1647,3 @@ void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspec { icon_draw_size(x, y, icon_id, aspect, alpha, NULL, ICON_SIZE_PREVIEW, size, false); } - diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 6f029b81e92..f29d73e564b 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -706,7 +706,6 @@ float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]); void ui_but_add_shortcut(uiBut *but, const char *key_str, const bool do_strip); void ui_but_clipboard_free(void); -void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa); uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new); uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new); @@ -818,6 +817,10 @@ void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, fl void ui_but_anim_decorate_cb(struct bContext *C, void *arg_but, void *arg_dummy); void ui_but_anim_decorate_update_from_flag(uiBut *but); +/* interface_context_menu.c */ +bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but); +void ui_popup_context_menu_for_panel(struct bContext *C, struct ARegion *ar, struct Panel *pa); + /* interface_eyedropper.c */ struct wmKeyMap *eyedropper_modal_keymap(struct wmKeyConfig *keyconf); struct wmKeyMap *eyedropper_colorband_modal_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 3784ab635be..05af133616e 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -67,6 +67,9 @@ /* Show an icon button after each RNA button to use to quickly set keyframes, * this is a way to display animation/driven/override status, see T54951. */ #define UI_PROP_DECORATE +/* Alternate draw mode where some buttons can use single icon width, + * giving more room for the text at the expense of nicely aligned text. */ +#define UI_PROP_SEP_ICON_WIDTH_EXCEPTION /************************ Structs and Defines *************************/ @@ -1595,9 +1598,19 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index } else { const PropertySubType subtype = RNA_property_subtype(prop); - uiLayout *layout_split = uiLayoutSplit( - layout_row ? layout_row : layout, - UI_ITEM_PROP_SEP_DIVIDE, true); + uiLayout *layout_split; +#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION + if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) { + w = UI_UNIT_X; + layout_split = uiLayoutRow(layout_row ? layout_row : layout, true); + } + else +#endif /* UI_PROP_SEP_ICON_WIDTH_EXCEPTION */ + { + layout_split = uiLayoutSplit( + layout_row ? layout_row : layout, + UI_ITEM_PROP_SEP_DIVIDE, true); + } layout_split->space = 0; uiLayout *layout_sub = uiLayoutColumn(layout_split, true); layout_sub->space = 0; @@ -3171,12 +3184,12 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem) .litem_y = litem->y, .space_x = space_x, .space_y = space_y, - }), + }), &((UILayoutGridFlowOutput) { .tot_items = &gflow->tot_items, .global_avg_w = &avg_w, .global_max_h = &max_h, - })); + })); if (gflow->tot_items == 0) { litem->w = litem->h = 0; @@ -3258,11 +3271,11 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem) .space_y = space_y, .tot_columns = gflow->tot_columns, .tot_rows = gflow->tot_rows, - }), + }), &((UILayoutGridFlowOutput) { .tot_w = &tot_w, .tot_h = &tot_h, - })); + })); litem->w = tot_w; litem->h = tot_h; @@ -3306,13 +3319,13 @@ static void ui_litem_layout_grid_flow(uiLayout *litem) .space_y = space_y, .tot_columns = gflow->tot_columns, .tot_rows = gflow->tot_rows, - }), + }), &((UILayoutGridFlowOutput) { .cos_x_array = cos_x, .cos_y_array = cos_y, .widths_array = widths, .heights_array = heights, - })); + })); for (item = litem->items.first, i = 0; item; item = item->next, i++) { const int col = gflow->row_major ? i % gflow->tot_columns : i / gflow->tot_rows; diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 6fcede58737..aad48d13277 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1004,6 +1004,7 @@ static int editsource_exec(bContext *C, wmOperator *op) ui_editsource_active_but_set(but); /* redraw and get active button python info */ + ED_region_do_layout(C, ar); ED_region_do_draw(C, ar); ar->do_draw = false; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index e383ae42f8c..5d029685810 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -2254,7 +2254,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons } else if (event->type == RIGHTMOUSE) { if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { - ui_panel_menu(C, ar, block->panel); + ui_popup_context_menu_for_panel(C, ar, block->panel); retval = WM_UI_HANDLER_BREAK; break; } diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c index 569f50a9c75..1a49010ad9d 100644 --- a/source/blender/editors/interface/interface_region_hud.c +++ b/source/blender/editors/interface/interface_region_hud.c @@ -329,7 +329,10 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *sa) /* We shouldn't need to do this every time :S */ /* XXX, this is evil! - it also makes the menu show on first draw. :( */ + ARegion *ar_prev = CTX_wm_region(C); + CTX_wm_region_set((bContext *)C, ar); hud_region_layout(C, ar); + CTX_wm_region_set((bContext *)C, ar_prev); } /** \} */ diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c index a6046e551c6..b9222a75803 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.c +++ b/source/blender/editors/interface/interface_region_menu_popup.c @@ -458,6 +458,21 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup) MEM_freeN(pup); } +bool UI_popup_menu_end_or_cancel(bContext *C, uiPopupMenu *pup) +{ + if (!UI_block_is_empty(pup->block)) { + UI_popup_menu_end(C, pup); + return true; + } + else { + UI_block_layout_resolve(pup->block, NULL, NULL); + MEM_freeN(pup->block->handle); + UI_block_free(C, pup->block); + MEM_freeN(pup); + return false; + } +} + uiLayout *UI_popup_menu_layout(uiPopupMenu *pup) { return pup->layout; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 22487f29977..c2bea466015 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1356,8 +1356,7 @@ static uiLayout *draw_modifier( UI_block_emboss_set(block, UI_EMBOSS); /* modifier name */ - md->scene = scene; - if (mti->isDisabled && mti->isDisabled(md, 0)) { + if (mti->isDisabled && mti->isDisabled(scene, md, 0)) { uiLayoutSetRedAlert(row, true); } uiItemR(row, &ptr, "name", 0, "", ICON_NONE); @@ -1748,7 +1747,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) /* enabled */ UI_block_emboss_set(block, UI_EMBOSS_NONE); uiItemR(row, &ptr, "mute", 0, "", - (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF); + (con->flag & CONSTRAINT_OFF) ? ICON_HIDE_ON : ICON_HIDE_OFF); UI_block_emboss_set(block, UI_EMBOSS); uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); @@ -4263,18 +4262,18 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) /* make a box around the report to make it stand out */ UI_block_align_begin(block); - but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", 0, 0, UI_UNIT_X + 10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); + but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", 0, 0, UI_UNIT_X + 5, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); /* set the report's bg color in but->col - UI_BTYPE_ROUNDBOX feature */ rgb_float_to_uchar(but->col, rti->col); but->col[3] = 255; - but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, + but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", UI_UNIT_X + 5, 0, UI_UNIT_X + width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); - but->col[0] = but->col[1] = but->col[2] = unit_float_to_uchar_clamp(rti->grayscale); - but->col[3] = 255; UI_block_align_end(block); + UI_GetThemeColorShade3ubv(TH_BACK, 20, but->col); + but->col[3] = 255; /* icon and report message on top */ icon = UI_icon_from_report_type(report->type); @@ -4292,10 +4291,28 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) UI_block_emboss_set(block, UI_EMBOSS); - uiDefBut(block, UI_BTYPE_LABEL, 0, report->message, UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, + uiDefBut(block, UI_BTYPE_LABEL, 0, report->message, UI_UNIT_X + 5, 0, UI_UNIT_X + width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); } + +void uiTemplateCursorKeymap(uiLayout *layout, struct bContext *C) +{ + wmWindow *win = CTX_wm_window(C); + for (int i = 0; i < 3; i++) { + uiLayout *box = uiLayoutRow(layout, true); + for (int j = 0; j < 2; j++) { + const char *msg = WM_window_cursor_keymap_status_get(win, i, j); + if ((j == 0) || (msg != NULL)) { + uiItemL(box, msg, j == 0 ? (ICON_MOUSE_LMB + i) : ICON_MOUSE_DRAG); + } + } + if (i != 2) { + uiItemSpacer(layout); + } + } +} + /********************************* Keymap *************************************/ static void keymap_item_modified(bContext *UNUSED(C), void *kmi_p, void *UNUSED(unused)) diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 4bc3aaaf842..a6f58fc056a 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -230,16 +230,16 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}} static const int tria_ofs[ROUNDBOX_TRIA_MAX] = { [ROUNDBOX_TRIA_NONE] = 0, [ROUNDBOX_TRIA_ARROWS] = 0, - [ROUNDBOX_TRIA_SCROLL] = 6, - [ROUNDBOX_TRIA_MENU] = 22, - [ROUNDBOX_TRIA_CHECK] = 28, - [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 34, + [ROUNDBOX_TRIA_SCROLL] = 12, + [ROUNDBOX_TRIA_MENU] = 28, + [ROUNDBOX_TRIA_CHECK] = 34, + [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 40, }; static const int tria_vcount[ROUNDBOX_TRIA_MAX] = { [ROUNDBOX_TRIA_NONE] = 0, - [ROUNDBOX_TRIA_ARROWS] = 3, + [ROUNDBOX_TRIA_ARROWS] = 6, [ROUNDBOX_TRIA_SCROLL] = 16, - [ROUNDBOX_TRIA_MENU] = 3, + [ROUNDBOX_TRIA_MENU] = 6, [ROUNDBOX_TRIA_CHECK] = 6, [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 3, }; @@ -296,8 +296,8 @@ static uint32_t set_tria_vertex( int tria_type, int tria_v, int tria_id, int jit_v) { uint32_t *data = GWN_vertbuf_raw_step(vflag_step); - if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS, ROUNDBOX_TRIA_MENU)) { - tria_v += tria_id * 3; + if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS)) { + tria_v += tria_id * tria_vcount[ROUNDBOX_TRIA_ARROWS]; } *data = tria_ofs[tria_type] + tria_v; *data |= jit_v << 6; @@ -308,7 +308,7 @@ static uint32_t set_tria_vertex( static void roundbox_batch_add_tria(Gwn_VertBufRaw *vflag_step, int tria, uint32_t last_data) { - const int tria_num = ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW) ? 1 : 2; + const int tria_num = ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU) ? 1 : 2; /* for each tria */ for (int t = 0; t < tria_num; ++t) { for (int j = 0; j < WIDGET_AA_JITTER; j++) { @@ -335,7 +335,7 @@ Gwn_Batch *ui_batch_roundbox_widget_get(int tria) vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */ if (tria) { vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria1 */ - if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW)) { + if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU)) { vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */ } } @@ -1500,6 +1500,8 @@ float UI_text_clip_middle_ex( BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); } + BLI_assert(strwidth <= okwidth); + return strwidth; } @@ -2657,18 +2659,22 @@ static void widget_state_pie_menu_item(uiWidgetType *wt, int state) copy_v4_v4_char(wt->wcol.inner, wt->wcol.item); wt->wcol.inner[3] = 64; } - /* regular disabled */ - else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { - widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); - } - /* regular active */ - else if (state & UI_SELECT) { - copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel); - copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); - } - else if (state & UI_ACTIVE) { - copy_v4_v4_char(wt->wcol.inner, wt->wcol.item); - copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); + else { + /* regular active */ + if (state & (UI_SELECT | UI_ACTIVE)) { + copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); + } + else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { + /* regular disabled */ + widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); + } + + if (state & UI_SELECT) { + copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel); + } + else if (state & UI_ACTIVE) { + copy_v4_v4_char(wt->wcol.inner, wt->wcol.item); + } } } @@ -2685,14 +2691,19 @@ static void widget_state_menu_item(uiWidgetType *wt, int state) copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); wt->wcol.inner[3] = 64; } - /* regular disabled */ - else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { - widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); - } - /* regular active */ - else if (state & UI_ACTIVE) { - copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); - copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); + else { + /* regular active */ + if (state & UI_ACTIVE) { + copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); + } + else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { + /* regular disabled */ + widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); + } + + if (state & UI_ACTIVE) { + copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); + } } } diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 8bd41b874f5..a04b25672de 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -48,9 +48,9 @@ #include "BKE_addon.h" #include "BKE_appdir.h" #include "BKE_colorband.h" -#include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_mesh_runtime.h" #include "BIF_gl.h" @@ -1856,9 +1856,9 @@ void init_userdef_do_versions(Main *bmain) U.fcu_inactive_alpha = 0.25f; } - /* signal for derivedmesh to use colorband */ + /* signal for evaluated mesh to use colorband */ /* run in case this was on and is now off in the user prefs [#28096] */ - vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, UI_GetTheme()->tv3d.vertex_unreferenced); + BKE_mesh_runtime_color_band_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, UI_GetTheme()->tv3d.vertex_unreferenced); if (!USER_VERSION_ATLEAST(192, 0)) { strcpy(U.sounddir, "/"); @@ -2920,7 +2920,7 @@ void init_userdef_do_versions(Main *bmain) U.flag &= ~( USER_FLAG_DEPRECATED_1 | USER_FLAG_DEPRECATED_2 | USER_FLAG_DEPRECATED_3 | USER_FLAG_DEPRECATED_6 | USER_FLAG_DEPRECATED_7 | - USER_FLAG_DEPRECATED_9 | USER_FLAG_DEPRECATED_10); + USER_FLAG_DEPRECATED_9 | USER_DEVELOPER_UI); U.uiflag &= ~( USER_UIFLAG_DEPRECATED_7); U.transopts &= ~( diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index cf4d8ebf05d..405c19f1c1d 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -33,13 +33,14 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "DNA_meshdata_types.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" -#include "BKE_DerivedMesh.h" +#include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_global.h" #include "BKE_mesh.h" -#include "BKE_context.h" #include "BIF_gl.h" @@ -61,7 +62,7 @@ void paintface_flush_flags(Object *ob, short flag) { Mesh *me = BKE_mesh_from_object(ob); - DerivedMesh *dm = ob->derivedFinal; + Mesh *me_eval = ob->runtime.mesh_eval; MPoly *polys, *mp_orig; const int *index_array = NULL; int totpoly; @@ -80,14 +81,14 @@ void paintface_flush_flags(Object *ob, short flag) BKE_mesh_flush_select_from_polys(me); } - if (dm == NULL) + if (me_eval == NULL) return; /* Mesh polys => Final derived polys */ - if ((index_array = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX))) { - polys = dm->getPolyArray(dm); - totpoly = dm->getNumPolys(dm); + if ((index_array = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) { + polys = me_eval->mpoly; + totpoly = me_eval->totpoly; /* loop over final derived polys */ for (i = 0; i < totpoly; i++) { @@ -474,8 +475,8 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten void paintvert_flush_flags(Object *ob) { Mesh *me = BKE_mesh_from_object(ob); - DerivedMesh *dm = ob->derivedFinal; - MVert *dm_mvert, *dm_mv; + Mesh *me_eval = ob->runtime.mesh_eval; + MVert *mvert_eval, *mv; const int *index_array = NULL; int totvert; int i; @@ -487,28 +488,28 @@ void paintvert_flush_flags(Object *ob) * since this could become slow for realtime updates (circle-select for eg) */ BKE_mesh_flush_select_from_verts(me); - if (dm == NULL) + if (me_eval == NULL) return; - index_array = dm->getVertDataArray(dm, CD_ORIGINDEX); + index_array = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX); - dm_mvert = dm->getVertArray(dm); - totvert = dm->getNumVerts(dm); + mvert_eval = me_eval->mvert; + totvert = me_eval->totvert; - dm_mv = dm_mvert; + mv = mvert_eval; if (index_array) { int orig_index; - for (i = 0; i < totvert; i++, dm_mv++) { + for (i = 0; i < totvert; i++, mv++) { orig_index = index_array[i]; if (orig_index != ORIGINDEX_NONE) { - dm_mv->flag = me->mvert[index_array[i]].flag; + mv->flag = me->mvert[index_array[i]].flag; } } } else { - for (i = 0; i < totvert; i++, dm_mv++) { - dm_mv->flag = me->mvert[i].flag; + for (i = 0; i < totvert; i++, mv++) { + mv->flag = me->mvert[i].flag; } } diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index c51a57e27b3..2041852c9ee 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -657,7 +657,7 @@ void MESH_OT_bevel(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING; RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures"); - prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 1.0f); + prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 100.0f); RNA_def_property_float_array_funcs_runtime(prop, NULL, NULL, mesh_ot_bevel_offset_range_func); RNA_def_int(ot->srna, "segments", 1, 1, SEGMENTS_HARD_MAX, "Segments", "Segments for curved edge", 1, 8); RNA_def_float(ot->srna, "profile", 0.5f, PROFILE_HARD_MIN, 1.0f, "Profile", diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 64e6b477abe..5481c52269d 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -1035,7 +1035,7 @@ void EDBM_verts_mirror_cache_begin_ex( BM_mesh_elem_index_ensure(bm, BM_VERT); if (use_topology) { - ED_mesh_mirrtopo_init__real_mesh(me, NULL, &mesh_topo_store, true); + ED_mesh_mirrtopo_init(me, NULL, &mesh_topo_store, true); } else { tree = BLI_kdtree_new(bm->totvert); diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 46b84f328cc..b4588257412 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -584,8 +584,8 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e MEM_freeN(me->edit_btmesh); me->edit_btmesh = NULL; - /* load_editMesh free's pointers used by CustomData layers which might be used by DerivedMesh too, - * so signal to re-create DerivedMesh here (sergey) */ + /* load_editMesh free's pointers used by CustomData layers which might be used by evaluated mesh too, + * so signal to re-create evaluated mesh here (sergey) */ DEG_id_tag_update(&me->id, 0); } diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c index 4c078d2ac8b..4b526915551 100644 --- a/source/blender/editors/mesh/mesh_mirror.c +++ b/source/blender/editors/mesh/mesh_mirror.c @@ -32,9 +32,9 @@ #include "BLI_bitmap.h" #include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "DNA_object_types.h" -#include "BKE_DerivedMesh.h" #include "BLI_kdtree.h" #include "BKE_editmesh.h" #include "BKE_library.h" @@ -52,11 +52,11 @@ static struct { void *tree; } MirrKdStore = {NULL}; /* mode is 's' start, or 'e' end, or 'u' use */ /* if end, ob can be NULL */ -int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, const float co[3], char mode) +int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, Mesh *me_eval, const float co[3], char mode) { if (mode == 'u') { /* use table */ if (MirrKdStore.tree == NULL) - ED_mesh_mirror_spatial_table(ob, em, dm, NULL, 's'); + ED_mesh_mirror_spatial_table(ob, em, me_eval, NULL, 's'); if (MirrKdStore.tree) { KDTreeNearest nearest; @@ -72,11 +72,11 @@ int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, co } else if (mode == 's') { /* start table */ Mesh *me = ob->data; - const bool use_em = (!dm && em && me->edit_btmesh == em); - const int totvert = use_em ? em->bm->totvert : dm ? dm->getNumVerts(dm) : me->totvert; + const bool use_em = (!me_eval && em && me->edit_btmesh == em); + const int totvert = use_em ? em->bm->totvert : me_eval ? me_eval->totvert : me->totvert; if (MirrKdStore.tree) /* happens when entering this call without ending it */ - ED_mesh_mirror_spatial_table(ob, em, dm, co, 'e'); + ED_mesh_mirror_spatial_table(ob, em, me_eval, co, 'e'); MirrKdStore.tree = BLI_kdtree_new(totvert); @@ -93,73 +93,7 @@ int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, co } } else { - MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert; - int i; - - for (i = 0; i < totvert; i++, mvert++) { - BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co); - } - } - - BLI_kdtree_balance(MirrKdStore.tree); - } - else if (mode == 'e') { /* end table */ - if (MirrKdStore.tree) { - BLI_kdtree_free(MirrKdStore.tree); - MirrKdStore.tree = NULL; - } - } - else { - BLI_assert(0); - } - - return 0; -} - -/* mode is 's' start, or 'e' end, or 'u' use */ -/* if end, ob can be NULL */ -int ED_mesh_mirror_spatial_table__real_mesh(Object *ob, BMEditMesh *em, Mesh *mesh, const float co[3], char mode) -{ - if (mode == 'u') { /* use table */ - if (MirrKdStore.tree == NULL) - ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, NULL, 's'); - - if (MirrKdStore.tree) { - KDTreeNearest nearest; - const int i = BLI_kdtree_find_nearest(MirrKdStore.tree, co, &nearest); - - if (i != -1) { - if (nearest.dist < KD_THRESH) { - return i; - } - } - } - return -1; - } - else if (mode == 's') { /* start table */ - Mesh *me = ob->data; - const bool use_em = (!mesh && em && me->edit_btmesh == em); - const int totvert = use_em ? em->bm->totvert : mesh ? mesh->totvert : me->totvert; - - if (MirrKdStore.tree) /* happens when entering this call without ending it */ - ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, co, 'e'); - - MirrKdStore.tree = BLI_kdtree_new(totvert); - - if (use_em) { - BMVert *eve; - BMIter iter; - int i; - - /* this needs to be valid for index lookups later (callers need) */ - BM_mesh_elem_table_ensure(em->bm, BM_VERT); - - BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { - BLI_kdtree_insert(MirrKdStore.tree, i, eve->co); - } - } - else { - MVert *mvert = mesh ? mesh->mvert : me->mvert; + MVert *mvert = me_eval ? me_eval->mvert : me->mvert; int i; for (i = 0; i < totvert; i++, mvert++) { @@ -209,46 +143,15 @@ static int mirrtopo_vert_sort(const void *v1, const void *v2) return 0; } -bool ED_mesh_mirrtopo_recalc_check(Mesh *me, DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store) -{ - const bool is_editmode = (me->edit_btmesh != NULL); - int totvert; - int totedge; - - if (dm) { - totvert = dm->getNumVerts(dm); - totedge = dm->getNumEdges(dm); - } - else if (me->edit_btmesh) { - totvert = me->edit_btmesh->bm->totvert; - totedge = me->edit_btmesh->bm->totedge; - } - else { - totvert = me->totvert; - totedge = me->totedge; - } - - if ((mesh_topo_store->index_lookup == NULL) || - (mesh_topo_store->prev_is_editmode != is_editmode) || - (totvert != mesh_topo_store->prev_vert_tot) || - (totedge != mesh_topo_store->prev_edge_tot)) - { - return true; - } - else { - return false; - } - -} -bool ED_mesh_mirrtopo_recalc_check__real_mesh(Mesh *me, Mesh *dm, MirrTopoStore_t *mesh_topo_store) +bool ED_mesh_mirrtopo_recalc_check(Mesh *me, Mesh *me_eval, MirrTopoStore_t *mesh_topo_store) { const bool is_editmode = (me->edit_btmesh != NULL); int totvert; int totedge; - if (dm) { - totvert = dm->totvert; - totedge = dm->totedge; + if (me_eval) { + totvert = me_eval->totvert; + totedge = me_eval->totedge; } else if (me->edit_btmesh) { totvert = me->edit_btmesh->bm->totvert; @@ -272,33 +175,13 @@ bool ED_mesh_mirrtopo_recalc_check__real_mesh(Mesh *me, Mesh *dm, MirrTopoStore_ } - void ED_mesh_mirrtopo_init( - Mesh *me, DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store, - const bool skip_em_vert_array_init) -{ - Mesh *fake_mesh = NULL; - - if (dm != NULL) { - /* ED_real_mesh_mirrtopo_init() only uses the counts, not the actual data */ - fake_mesh = BKE_mesh_new_nomain(dm->getNumVerts(dm), dm->getNumEdges(dm), dm->getNumTessFaces(dm), - dm->getNumLoops(dm), dm->getNumPolys(dm)); - } - - ED_mesh_mirrtopo_init__real_mesh(me, fake_mesh, mesh_topo_store, skip_em_vert_array_init); - - if (dm != NULL) { - BKE_id_free(NULL, fake_mesh); - } -} - -void ED_mesh_mirrtopo_init__real_mesh( - Mesh *me, Mesh *dm, MirrTopoStore_t *mesh_topo_store, + Mesh *me, Mesh *me_eval, MirrTopoStore_t *mesh_topo_store, const bool skip_em_vert_array_init) { const bool is_editmode = (me->edit_btmesh != NULL); MEdge *medge = NULL, *med; - BMEditMesh *em = dm ? NULL : me->edit_btmesh; + BMEditMesh *em = me_eval ? NULL : me->edit_btmesh; /* editmode*/ BMEdge *eed; @@ -327,7 +210,7 @@ void ED_mesh_mirrtopo_init__real_mesh( totvert = em->bm->totvert; } else { - totvert = dm ? dm->totvert : me->totvert; + totvert = me_eval ? me_eval->totvert : me->totvert; } topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr"); @@ -343,8 +226,8 @@ void ED_mesh_mirrtopo_init__real_mesh( } } else { - totedge = dm ? dm->totedge : me->totedge; - medge = dm ? dm->medge : me->medge; + totedge = me_eval ? me_eval->totedge : me->totedge; + medge = me_eval ? me_eval->medge : me->medge; for (a = 0, med = medge; a < totedge; a++, med++) { const unsigned int i1 = med->v1, i2 = med->v2; diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 6c8de1a481e..537056cd1ba 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -34,9 +34,10 @@ #include "MEM_guardedalloc.h" -#include "DNA_mesh_types.h" #include "DNA_key_types.h" #include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -49,11 +50,11 @@ #include "BKE_context.h" #include "BKE_deform.h" -#include "BKE_DerivedMesh.h" #include "BKE_key.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_mesh.h" +#include "BKE_mesh_iterators.h" #include "BKE_mesh_runtime.h" #include "BKE_material.h" #include "BKE_object.h" @@ -612,7 +613,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) Depsgraph *depsgraph = CTX_data_depsgraph(C); Mesh *me = (Mesh *)ob->data; Mesh *selme = NULL; - DerivedMesh *dm = NULL; + Mesh *me_deformed = NULL; Key *key = me->key; KeyBlock *kb; bool ok = false, nonequal_verts = false; @@ -646,7 +647,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) /* first key added, so it was the basis. initialize it with the existing mesh */ kb = BKE_keyblock_add(key, NULL); - BKE_keyblock_convert_from_mesh(me, kb); + BKE_keyblock_convert_from_mesh(me, key, kb); } /* now ready to add new keys from selected meshes */ @@ -658,15 +659,15 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) selme = (Mesh *)base->object->data; if (selme->totvert == me->totvert) { - dm = mesh_get_derived_deform(depsgraph, scene, base->object, CD_MASK_BAREMESH); + me_deformed = mesh_get_eval_deform(depsgraph, scene, base->object, CD_MASK_BAREMESH); - if (!dm) continue; + if (!me_deformed) { + continue; + } kb = BKE_keyblock_add(key, base->object->id.name + 2); - DM_to_meshkey(dm, me, kb); - - dm->release(dm); + BKE_mesh_runtime_eval_to_meshkey(me_deformed, me, kb); } } } @@ -690,40 +691,15 @@ static MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1}; /* mode is 's' start, or 'e' end, or 'u' use */ /* if end, ob can be NULL */ /* note, is supposed return -1 on error, which callers are currently checking for, but is not used so far */ -int ED_mesh_mirror_topo_table( - Object *ob, DerivedMesh *dm, char mode) +int ED_mesh_mirror_topo_table(Object *ob, Mesh *me_eval, char mode) { if (mode == 'u') { /* use table */ - if (ED_mesh_mirrtopo_recalc_check(ob->data, dm, &mesh_topo_store)) { - ED_mesh_mirror_topo_table(ob, dm, 's'); + if (ED_mesh_mirrtopo_recalc_check(ob->data, me_eval, &mesh_topo_store)) { + ED_mesh_mirror_topo_table(ob, me_eval, 's'); } } else if (mode == 's') { /* start table */ - ED_mesh_mirrtopo_init(ob->data, dm, &mesh_topo_store, false); - } - else if (mode == 'e') { /* end table */ - ED_mesh_mirrtopo_free(&mesh_topo_store); - } - else { - BLI_assert(0); - } - - return 0; -} - -/* mode is 's' start, or 'e' end, or 'u' use */ -/* if end, ob can be NULL */ -/* note, is supposed return -1 on error, which callers are currently checking for, but is not used so far */ -int ED_mesh_mirror_topo_table__real_mesh( - Object *ob, Mesh *mesh, char mode) -{ - if (mode == 'u') { /* use table */ - if (ED_mesh_mirrtopo_recalc_check__real_mesh(ob->data, mesh, &mesh_topo_store)) { - ED_mesh_mirror_topo_table__real_mesh(ob, mesh, 's'); - } - } - else if (mode == 's') { /* start table */ - ED_mesh_mirrtopo_init__real_mesh(ob->data, mesh, &mesh_topo_store, false); + ED_mesh_mirrtopo_init(ob->data, me_eval, &mesh_topo_store, false); } else if (mode == 'e') { /* end table */ ED_mesh_mirrtopo_free(&mesh_topo_store); @@ -738,39 +714,7 @@ int ED_mesh_mirror_topo_table__real_mesh( /** \} */ -static int mesh_get_x_mirror_vert_spatial(Object *ob, DerivedMesh *dm, int index) -{ - Mesh *me = ob->data; - MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert; - float vec[3]; - - mvert = &mvert[index]; - vec[0] = -mvert->co[0]; - vec[1] = mvert->co[1]; - vec[2] = mvert->co[2]; - - return ED_mesh_mirror_spatial_table(ob, NULL, dm, vec, 'u'); -} - -static int mesh_get_x_mirror_vert_topo(Object *ob, DerivedMesh *dm, int index) -{ - if (ED_mesh_mirror_topo_table(ob, dm, 'u') == -1) - return -1; - - return mesh_topo_store.index_lookup[index]; -} - -int mesh_get_x_mirror_vert(Object *ob, DerivedMesh *dm, int index, const bool use_topology) -{ - if (use_topology) { - return mesh_get_x_mirror_vert_topo(ob, dm, index); - } - else { - return mesh_get_x_mirror_vert_spatial(ob, dm, index); - } -} - -static int mesh_get_x_mirror_vert_spatial__real_mesh(Object *ob, Mesh *mesh, int index) +static int mesh_get_x_mirror_vert_spatial(Object *ob, Mesh *mesh, int index) { Mesh *me = ob->data; MVert *mvert = mesh ? mesh->mvert : me->mvert; @@ -781,24 +725,24 @@ static int mesh_get_x_mirror_vert_spatial__real_mesh(Object *ob, Mesh *mesh, int vec[1] = mvert->co[1]; vec[2] = mvert->co[2]; - return ED_mesh_mirror_spatial_table__real_mesh(ob, NULL, mesh, vec, 'u'); + return ED_mesh_mirror_spatial_table(ob, NULL, mesh, vec, 'u'); } -static int mesh_get_x_mirror_vert_topo__real_mesh(Object *ob, Mesh *mesh, int index) +static int mesh_get_x_mirror_vert_topo(Object *ob, Mesh *mesh, int index) { - if (ED_mesh_mirror_topo_table__real_mesh(ob, mesh, 'u') == -1) + if (ED_mesh_mirror_topo_table(ob, mesh, 'u') == -1) return -1; return mesh_topo_store.index_lookup[index]; } -int mesh_get_x_mirror_vert__real_mesh(Object *ob, Mesh *mesh, int index, const bool use_topology) +int mesh_get_x_mirror_vert(Object *ob, Mesh *me_eval, int index, const bool use_topology) { if (use_topology) { - return mesh_get_x_mirror_vert_topo__real_mesh(ob, mesh, index); + return mesh_get_x_mirror_vert_topo(ob, me_eval, index); } else { - return mesh_get_x_mirror_vert_spatial__real_mesh(ob, mesh, index); + return mesh_get_x_mirror_vert_spatial(ob, me_eval, index); } } @@ -995,68 +939,8 @@ static bool mirror_facecmp(const void *a, const void *b) return (mirror_facerotation((MFace *)a, (MFace *)b) == -1); } -/* BMESH_TODO, convert to MPoly (functions above also) */ -int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, DerivedMesh *dm) -{ - Mesh *me = ob->data; - MVert *mv, *mvert; - MFace mirrormf, *mf, *hashmf, *mface; - GHash *fhash; - int *mirrorverts, *mirrorfaces; - - BLI_assert(em == NULL); /* Does not work otherwise, currently... */ - - const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; - const int totvert = dm ? dm->getNumVerts(dm) : me->totvert; - const int totface = dm ? dm->getNumTessFaces(dm) : me->totface; - int a; - - mirrorverts = MEM_callocN(sizeof(int) * totvert, "MirrorVerts"); - mirrorfaces = MEM_callocN(sizeof(int) * 2 * totface, "MirrorFaces"); - - mvert = dm ? dm->getVertArray(dm) : me->mvert; - mface = dm ? dm->getTessFaceArray(dm) : me->mface; - - ED_mesh_mirror_spatial_table(ob, em, dm, NULL, 's'); - - for (a = 0, mv = mvert; a < totvert; a++, mv++) - mirrorverts[a] = mesh_get_x_mirror_vert(ob, dm, a, use_topology); - - ED_mesh_mirror_spatial_table(ob, em, dm, NULL, 'e'); - - fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface); - for (a = 0, mf = mface; a < totface; a++, mf++) - BLI_ghash_insert(fhash, mf, mf); - - for (a = 0, mf = mface; a < totface; a++, mf++) { - mirrormf.v1 = mirrorverts[mf->v3]; - mirrormf.v2 = mirrorverts[mf->v2]; - mirrormf.v3 = mirrorverts[mf->v1]; - mirrormf.v4 = (mf->v4) ? mirrorverts[mf->v4] : 0; - - /* make sure v4 is not 0 if a quad */ - if (mf->v4 && mirrormf.v4 == 0) { - SWAP(unsigned int, mirrormf.v1, mirrormf.v3); - SWAP(unsigned int, mirrormf.v2, mirrormf.v4); - } - - hashmf = BLI_ghash_lookup(fhash, &mirrormf); - if (hashmf) { - mirrorfaces[a * 2] = hashmf - mface; - mirrorfaces[a * 2 + 1] = mirror_facerotation(&mirrormf, hashmf); - } - else - mirrorfaces[a * 2] = -1; - } - - BLI_ghash_free(fhash, NULL, NULL); - MEM_freeN(mirrorverts); - - return mirrorfaces; -} - /* This is a Mesh-based copy of mesh_get_x_mirror_faces() */ -int *mesh_get_x_mirror_faces__real_mesh(Object *ob, BMEditMesh *em, Mesh *mesh) +int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval) { Mesh *me = ob->data; MVert *mv, *mvert; @@ -1067,22 +951,22 @@ int *mesh_get_x_mirror_faces__real_mesh(Object *ob, BMEditMesh *em, Mesh *mesh) BLI_assert(em == NULL); /* Does not work otherwise, currently... */ const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; - const int totvert = mesh ? mesh->totvert : me->totvert; - const int totface = mesh ? mesh->totface : me->totface; + const int totvert = me_eval ? me_eval->totvert : me->totvert; + const int totface = me_eval ? me_eval->totface : me->totface; int a; mirrorverts = MEM_callocN(sizeof(int) * totvert, "MirrorVerts"); mirrorfaces = MEM_callocN(sizeof(int) * 2 * totface, "MirrorFaces"); - mvert = mesh ? mesh->mvert : me->mvert; - mface = mesh ? mesh->mface : me->mface; + mvert = me_eval ? me_eval->mvert : me->mvert; + mface = me_eval ? me_eval->mface : me->mface; - ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, NULL, 's'); + ED_mesh_mirror_spatial_table(ob, em, me_eval, NULL, 's'); for (a = 0, mv = mvert; a < totvert; a++, mv++) - mirrorverts[a] = mesh_get_x_mirror_vert__real_mesh(ob, mesh, a, use_topology); + mirrorverts[a] = mesh_get_x_mirror_vert(ob, me_eval, a, use_topology); - ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, NULL, 'e'); + ED_mesh_mirror_spatial_table(ob, em, me_eval, NULL, 'e'); fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface); for (a = 0, mf = mface; a < totface; a++, mf++) @@ -1322,7 +1206,7 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int } else { /* derived mesh to find deformed locations */ - DerivedMesh *dm = mesh_get_derived_final(vc.depsgraph, vc.scene, ob, CD_MASK_BAREMESH); + Mesh *me_eval = mesh_get_eval_final(vc.depsgraph, vc.scene, ob, CD_MASK_BAREMESH); ARegion *ar = vc.ar; RegionView3D *rv3d = ar->regiondata; @@ -1334,7 +1218,7 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int ED_view3d_init_mats_rv3d(ob, rv3d); - if (dm == NULL) { + if (me_eval == NULL) { return false; } @@ -1345,9 +1229,7 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int data.len_best = FLT_MAX; data.v_idx_best = -1; - dm->foreachMappedVert(dm, ed_mesh_pick_vert__mapFunc, &data, DM_FOREACH_NOP); - - dm->release(dm); + BKE_mesh_foreach_mapped_vert(me_eval, ed_mesh_pick_vert__mapFunc, &data, MESH_FOREACH_NOP); if (data.v_idx_best == -1) { return false; diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index dd358b95722..ac3f8d58de8 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -946,7 +946,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv /* add under the mouse */ ED_object_location_from_view(C, ob->loc); - ED_view3d_cursor3d_position(C, ob->loc, event->mval); + ED_view3d_cursor3d_position(C, event->mval, false, ob->loc); } BKE_object_empty_draw_type_set(ob, OB_EMPTY_IMAGE); @@ -1013,7 +1013,21 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; ob = ED_object_add_type(C, OB_LAMP, get_lamp_defname(type), loc, rot, false, layer); - BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius")); + + float size = RNA_float_get(op->ptr, "radius"); + /* Better defaults for lamp size. */ + switch (type) { + case LA_LOCAL: + case LA_SPOT: + break; + case LA_AREA: + size *= 4.0f; + break; + default: + size *= 0.5f; + break; + } + BKE_object_obdata_size_init(ob, size); la = (Lamp *)ob->data; la->type = type; @@ -1070,7 +1084,7 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) const int mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin}; ED_object_location_from_view(C, loc); - ED_view3d_cursor3d_position(C, loc, mval); + ED_view3d_cursor3d_position(C, mval, false, loc); RNA_float_set_array(op->ptr, "location", loc); } } @@ -1097,8 +1111,6 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) /* works without this except if you try render right after, see: 22027 */ DEG_relations_tag_update(bmain); - DEG_id_tag_update(&collection->id, 0); - DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); @@ -2002,9 +2014,6 @@ static int convert_exec(bContext *C, wmOperator *op) } FOREACH_SCENE_OBJECT_END; } - - /* delete object should renew depsgraph */ - DEG_relations_tag_update(bmain); } // XXX ED_object_editmode_enter(C, 0); @@ -2079,7 +2088,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer DEG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA); base = BKE_view_layer_base_find(view_layer, ob); - if ((base != NULL) && (base->flag & BASE_VISIBLED)) { + if ((base != NULL) && (base->flag & BASE_VISIBLE)) { BKE_collection_object_add_from(bmain, scene, ob, obn); } else { @@ -2426,7 +2435,7 @@ static int add_named_exec(bContext *C, wmOperator *op) const int mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin}; ED_object_location_from_view(C, basen->object->loc); - ED_view3d_cursor3d_position(C, basen->object->loc, mval); + ED_view3d_cursor3d_position(C, mval, false, basen->object->loc); } ED_object_base_select(basen, BA_SELECT); diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index a8da5c038b4..8ad0d09a9fb 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -118,6 +118,7 @@ typedef struct MultiresBakerJobData { /* data passing to multires-baker job */ typedef struct { + Scene *scene; ListBase data; bool bake_clear; /* Clear the images before baking */ int bake_filter; /* Bake-filter, aka margin */ @@ -241,7 +242,7 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l tmp_mmd.lvl = *lvl; tmp_mmd.sculptlvl = *lvl; - dm = multires_make_derived_from_derived(cddm, &tmp_mmd, ob, 0); + dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, 0); cddm->release(cddm); return dm; @@ -268,7 +269,7 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l tmp_mmd.lvl = mmd->totlvl; tmp_mmd.sculptlvl = mmd->totlvl; - dm = multires_make_derived_from_derived(cddm, &tmp_mmd, ob, 0); + dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, 0); cddm->release(cddm); return dm; @@ -371,6 +372,7 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) multires_force_update(ob); /* copy data stored in job descriptor */ + bkr.scene = scene; bkr.bake_filter = scene->r.bake_filter; bkr.mode = scene->r.bake_mode; bkr.use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH; @@ -413,6 +415,7 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj) Object *ob; /* backup scene settings, so their changing in UI would take no effect on baker */ + bkj->scene = scene; bkj->bake_filter = scene->r.bake_filter; bkj->mode = scene->r.bake_mode; bkj->use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH; @@ -474,6 +477,7 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa MultiresBakeRender bkr = {NULL}; /* copy data stored in job descriptor */ + bkr.scene = bkj->scene; bkr.bake_filter = bkj->bake_filter; bkr.mode = bkj->mode; bkr.use_lores_mesh = bkj->use_lores_mesh; diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index db81c51cc90..788f0826848 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -40,7 +40,6 @@ #include "BKE_context.h" #include "BKE_data_transfer.h" -#include "BKE_DerivedMesh.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_remap.h" #include "BKE_mesh_runtime.h" @@ -137,20 +136,17 @@ static const EnumPropertyItem *dt_layers_select_src_itemf( Scene *scene = CTX_data_scene(C); if (ob_src) { - DerivedMesh *dm_src; - CustomData *ldata; + Mesh *me_eval; int num_data, i; - /* XXX Is this OK? */ - dm_src = mesh_get_derived_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPUV); - ldata = dm_src->getLoopDataLayout(dm_src); - num_data = CustomData_number_of_layers(ldata, CD_MLOOPUV); + me_eval = mesh_get_eval_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPUV); + num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV); RNA_enum_item_add_separator(&item, &totitem); for (i = 0; i < num_data; i++) { tmp_item.value = i; - tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPUV, i); + tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(&me_eval->ldata, CD_MLOOPUV, i); RNA_enum_item_add(&item, &totitem, &tmp_item); } } @@ -160,20 +156,17 @@ static const EnumPropertyItem *dt_layers_select_src_itemf( Scene *scene = CTX_data_scene(C); if (ob_src) { - DerivedMesh *dm_src; - CustomData *ldata; + Mesh *me_eval; int num_data, i; - /* XXX Is this OK? */ - dm_src = mesh_get_derived_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL); - ldata = dm_src->getLoopDataLayout(dm_src); - num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL); + me_eval = mesh_get_eval_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL); + num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL); RNA_enum_item_add_separator(&item, &totitem); for (i = 0; i < num_data; i++) { tmp_item.value = i; - tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPCOL, i); + tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(&me_eval->ldata, CD_MLOOPCOL, i); RNA_enum_item_add(&item, &totitem, &tmp_item); } } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 45ad4bfd196..e14842c0daa 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -146,6 +146,238 @@ Object *ED_object_active_context(bContext *C) return ob; } +/* ********************** object hiding *************************** */ + +static int object_hide_poll(bContext *C) +{ + if (CTX_wm_space_outliner(C) != NULL) { + return ED_outliner_collections_editor_poll(C); + } + else { + return ED_operator_view3d_active(C); + } +} + +static int object_hide_view_clear_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + const bool select = RNA_boolean_get(op->ptr, "select"); + bool changed = false; + + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (base->flag & BASE_HIDDEN) { + base->flag &= ~BASE_HIDDEN; + changed = true; + + if (select) { + ED_object_base_select(base, BA_SELECT); + } + } + } + + if (!changed) { + return OPERATOR_CANCELLED; + } + + BKE_layer_collection_sync(scene, view_layer); + DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_hide_view_clear(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Show Hidden Objects"; + ot->description = "Reveal temporarily hidden objects"; + ot->idname = "OBJECT_OT_hide_view_clear"; + + /* api callbacks */ + ot->exec = object_hide_view_clear_exec; + ot->poll = object_hide_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + PropertyRNA *prop = RNA_def_boolean(ot->srna, "select", false, "Select", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); +} + +static int object_hide_view_set_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + const bool unselected = RNA_boolean_get(op->ptr, "unselected"); + + /* Do nothing if no objects was selected. */ + bool have_selected = false; + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (base->flag & BASE_VISIBLE) { + if (base->flag & BASE_SELECTED) { + have_selected = true; + break; + } + } + } + + if (!have_selected) { + return OPERATOR_CANCELLED; + } + + /* Hide selected or unselected objects. */ + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (!(base->flag & BASE_VISIBLE)) { + continue; + } + + if (!unselected) { + if (base->flag & BASE_SELECTED) { + ED_object_base_select(base, BA_DESELECT); + base->flag |= BASE_HIDDEN; + } + } + else { + if (!(base->flag & BASE_SELECTED)) { + ED_object_base_select(base, BA_DESELECT); + base->flag |= BASE_HIDDEN; + } + } + } + + BKE_layer_collection_sync(scene, view_layer); + DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_hide_view_set(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Hide Objects"; + ot->description = "Temporarily hide objects from the viewport"; + ot->idname = "OBJECT_OT_hide_view_set"; + + /* api callbacks */ + ot->exec = object_hide_view_set_exec; + ot->poll = object_hide_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + PropertyRNA *prop; + prop = RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); +} + +static int object_hide_collection_exec(bContext *C, wmOperator *op) +{ + int index = RNA_int_get(op->ptr, "collection_index"); + bool extend = (CTX_wm_window(C)->eventstate->shift != 0); + + if (CTX_wm_window(C)->eventstate->alt != 0) { + index += 10; + } + + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index); + + if (!lc) { + return OPERATOR_CANCELLED; + } + + BKE_layer_collection_set_visible(scene, view_layer, lc, extend); + + DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + + return OPERATOR_FINISHED; +} + +#define COLLECTION_INVALID_INDEX -1 + +void ED_hide_collections_menu_draw(const bContext *C, uiLayout *layout) +{ + ViewLayer *view_layer = CTX_data_view_layer(C); + LayerCollection *lc_scene = view_layer->layer_collections.first; + + uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN); + + for (LayerCollection *lc = lc_scene->layer_collections.first; lc; lc = lc->next) { + int index = BKE_layer_collection_findindex(view_layer, lc); + uiLayout *row = uiLayoutRow(layout, false); + + if (lc->collection->flag & COLLECTION_RESTRICT_VIEW) { + continue; + } + + if ((view_layer->runtime_flag & VIEW_LAYER_HAS_HIDE) && + !(lc->runtime_flag & LAYER_COLLECTION_HAS_VISIBLE_OBJECTS)) + { + uiLayoutSetActive(row, false); + } + + int icon = ICON_NONE; + if (BKE_layer_collection_has_selected_objects(view_layer, lc)) { + icon = ICON_LAYER_ACTIVE; + } + else if (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) { + icon = ICON_LAYER_USED; + } + + uiItemIntO(row, + lc->collection->id.name + 2, + icon, + "OBJECT_OT_hide_collection", + "collection_index", + index); + } +} + +static int object_hide_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + /* Immediately execute if collection index was specified. */ + int index = RNA_int_get(op->ptr, "collection_index"); + if (index != COLLECTION_INVALID_INDEX) { + return object_hide_collection_exec(C, op); + } + + /* Open popup menu. */ + const char *title = CTX_IFACE_(op->type->translation_context, op->type->name); + uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_GROUP); + uiLayout *layout = UI_popup_menu_layout(pup); + + ED_hide_collections_menu_draw(C, layout); + + UI_popup_menu_end(C, pup); + + return OPERATOR_INTERFACE; +} + +void OBJECT_OT_hide_collection(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Hide Objects By Collection"; + ot->description = "Show only objects in collection (Shift to extend)"; + ot->idname = "OBJECT_OT_hide_collection"; + + /* api callbacks */ + ot->exec = object_hide_collection_exec; + ot->invoke = object_hide_collection_invoke; + ot->poll = ED_operator_view3d_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* Properties. */ + PropertyRNA *prop; + prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX, + "Collection Index", "Index of the collection to change visibility", 0, INT_MAX); + RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); +} /* ******************* toggle editmode operator ***************** */ @@ -654,7 +886,6 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev Base *base; Curve *cu, *cu1; Nurb *nu; - bool do_depgraph_update = false; if (ID_IS_LINKED(scene)) return; @@ -811,8 +1042,8 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev else if (event == 22) { /* Copy the constraint channels over */ BKE_constraints_copy(&base->object->constraints, &ob->constraints, true); - - do_depgraph_update = true; + DEG_id_tag_update(&base->object->id, DEG_TAG_COPY_ON_WRITE); + DEG_relations_tag_update(bmain); } else if (event == 23) { base->object->softflag = ob->softflag; @@ -823,6 +1054,9 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev if (!modifiers_findByType(base->object, eModifierType_Softbody)) { BLI_addhead(&base->object->modifiers, modifier_new(eModifierType_Softbody)); } + + DEG_id_tag_update(&base->object->id, DEG_TAG_COPY_ON_WRITE); + DEG_relations_tag_update(bmain); } else if (event == 26) { #if 0 // XXX old animation system @@ -863,9 +1097,6 @@ static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short ev } } } - - if (do_depgraph_update) - DEG_relations_tag_update(bmain); } static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, ViewLayer *view_layer, Object *obedit) @@ -1548,8 +1779,6 @@ bool ED_object_editmode_calc_active_center(Object *obedit, const bool select_onl return false; } -#define COLLECTION_INVALID_INDEX -1 - static int move_to_collection_poll(bContext *C) { if (CTX_wm_space_outliner(C) != NULL) { @@ -1630,7 +1859,7 @@ static int move_to_collection_exec(bContext *C, wmOperator *op) is_link ? "linked" : "moved", collection->id.name + 2); - DEG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); @@ -1869,5 +2098,3 @@ void OBJECT_OT_link_to_collection(wmOperatorType *ot) "Name of the newly added collection"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } - -#undef COLLECTION_INVALID_INDEX diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index 8a52b6c5ef5..53cabe3759e 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -47,6 +47,7 @@ #include "BKE_report.h" #include "BKE_object.h" +#include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "ED_screen.h" @@ -153,6 +154,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) if (!BKE_collection_object_cyclic_check(bmain, base->object, collection)) { BKE_collection_object_add(bmain, collection, base->object); + DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE); updated = true; } else { @@ -223,6 +225,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { BKE_collection_object_remove(bmain, collection, base->object, false); + DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE); ok = 1; } CTX_DATA_END; @@ -315,6 +318,7 @@ static int collection_objects_remove_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { BKE_collection_object_remove(bmain, collection, base->object, false); + DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE); updated = true; } CTX_DATA_END; @@ -366,6 +370,7 @@ static int collection_create_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selected_bases) { BKE_collection_object_add(bmain, collection, base->object); + DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE); } CTX_DATA_END; @@ -555,7 +560,7 @@ static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select o CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) { if (BKE_collection_has_object_recursive(collection, base->object)) { ED_object_base_select(base, BA_SELECT); } diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 18251a25b73..f7179912f52 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -76,6 +76,9 @@ void OBJECT_OT_drop_named_material(struct wmOperatorType *ot); void OBJECT_OT_unlink_data(struct wmOperatorType *ot); /* object_edit.c */ +void OBJECT_OT_hide_view_set(struct wmOperatorType *ot); +void OBJECT_OT_hide_view_clear(struct wmOperatorType *ot); +void OBJECT_OT_hide_collection(struct wmOperatorType *ot); void OBJECT_OT_mode_set(struct wmOperatorType *ot); void OBJECT_OT_mode_set_or_submode(struct wmOperatorType *ot); void OBJECT_OT_editmode_toggle(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 425a0acff17..9d7ca44ce16 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -324,8 +324,6 @@ static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md, ob->mode &= ~OB_MODE_PARTICLE_EDIT; } - DEG_relations_tag_update(bmain); - BLI_remlink(&ob->modifiers, md); modifier_free(md); BKE_object_free_derived_caches(ob); @@ -529,9 +527,7 @@ static int modifier_apply_shape( { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - md->scene = scene; - - if (mti->isDisabled && mti->isDisabled(md, 0)) { + if (mti->isDisabled && mti->isDisabled(scene, md, 0)) { BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); return 0; } @@ -570,7 +566,7 @@ static int modifier_apply_shape( /* if that was the first key block added, then it was the basis. * Initialize it with the mesh, and add another for the modifier */ kb = BKE_keyblock_add(key, NULL); - BKE_keyblock_convert_from_mesh(me, kb); + BKE_keyblock_convert_from_mesh(me, key, kb); } kb = BKE_keyblock_add(key, md->name); @@ -589,9 +585,7 @@ static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scen { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - md->scene = scene; - - if (mti->isDisabled && mti->isDisabled(md, 0)) { + if (mti->isDisabled && mti->isDisabled(scene, md, 0)) { BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); return 0; } @@ -1156,13 +1150,14 @@ static int multires_poll(bContext *C) static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires); if (!mmd) return OPERATOR_CANCELLED; - multiresModifier_del_levels(mmd, ob, 1); + multiresModifier_del_levels(mmd, scene, ob, 1); ED_object_iter_other(CTX_data_main(C), ob, true, ED_object_multires_update_totlevels_cb, @@ -1200,13 +1195,14 @@ void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot) static int multires_subdivide_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires); if (!mmd) return OPERATOR_CANCELLED; - multiresModifier_subdivide(mmd, ob, 0, mmd->simple); + multiresModifier_subdivide(mmd, scene, ob, 0, mmd->simple); ED_object_iter_other(CTX_data_main(C), ob, true, ED_object_multires_update_totlevels_cb, @@ -1423,13 +1419,14 @@ void OBJECT_OT_multires_external_pack(wmOperatorType *ot) /********************* multires apply base ***********************/ static int multires_base_apply_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires); if (!mmd) return OPERATOR_CANCELLED; - multiresModifier_base_apply(mmd, ob); + multiresModifier_base_apply(mmd, scene, ob); DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index c5df7fc21f8..89dd54b6f64 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -247,6 +247,10 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_data_transfer); WM_operatortype_append(OBJECT_OT_datalayout_transfer); WM_operatortype_append(OBJECT_OT_surfacedeform_bind); + + WM_operatortype_append(OBJECT_OT_hide_view_clear); + WM_operatortype_append(OBJECT_OT_hide_view_set); + WM_operatortype_append(OBJECT_OT_hide_collection); } void ED_operatormacros_object(void) @@ -293,7 +297,7 @@ void ED_keymap_object(wmKeyConfig *keyconf) RNA_enum_set(kmi->ptr, "mode", OB_MODE_EDIT); RNA_boolean_set(kmi->ptr, "toggle", true); - kmi = WM_keymap_add_menu_pie(keymap, "VIEW3D_PIE_object_mode", TABKEY, KM_CLICK_DRAG, 0, 0); + kmi = WM_keymap_add_menu_pie(keymap, "VIEW3D_MT_object_mode_pie", TABKEY, KM_CLICK_DRAG, 0, 0); WM_keymap_add_item(keymap, "OBJECT_OT_origin_set", CKEY, KM_PRESS, KM_ALT | KM_SHIFT | KM_CTRL, 0); @@ -404,6 +408,19 @@ void ED_keymap_object(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "OBJECT_OT_move_to_collection", MKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "OBJECT_OT_link_to_collection", MKEY, KM_PRESS, KM_SHIFT, 0); + + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "unselected", false); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "unselected", true); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_collection", HKEY, KM_PRESS, KM_CTRL, 0); + + /* Collection switching. */ + for (int i = 0; i < 10; i++) { + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_collection", ZEROKEY + i, KM_PRESS, KM_ANY, 0); + RNA_int_set(kmi->ptr, "collection_index", (i == 0) ? 10 : i); + } } void ED_keymap_proportional_cycle(struct wmKeyConfig *UNUSED(keyconf), struct wmKeyMap *keymap) diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index a114b2cc6d5..f2e996237cf 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1419,6 +1419,7 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst static int make_links_data_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); Main *bmain = CTX_data_main(C); const int type = RNA_enum_get(op->ptr, "type"); Object *ob_src; @@ -1503,7 +1504,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) } break; case MAKE_LINKS_MODIFIERS: - BKE_object_link_modifiers(ob_dst, ob_src); + BKE_object_link_modifiers(scene, ob_dst, ob_src); DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); break; case MAKE_LINKS_FONTS: diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index ce29125ac79..7d7871c0326 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -100,7 +100,7 @@ void ED_object_base_select(Base *base, eObjectSelect_Mode mode) if (base) { switch (mode) { case BA_SELECT: - if ((base->flag & BASE_SELECTABLED) != 0) { + if ((base->flag & BASE_SELECTABLE) != 0) { base->flag |= BASE_SELECTED; } break; @@ -229,7 +229,7 @@ static bool object_select_all_by_obdata(bContext *C, void *obdata) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) { if (base->object->data == obdata) { ED_object_base_select(base, BA_SELECT); changed = true; @@ -247,7 +247,7 @@ static bool object_select_all_by_material(bContext *C, Material *mat) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) { Object *ob = base->object; Material *mat1; int a; @@ -274,7 +274,7 @@ static bool object_select_all_by_dup_group(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) { Collection *dup_group_other = (base->object->transflag & OB_DUPLICOLLECTION) ? base->object->dup_group : NULL; if (dup_group == dup_group_other) { ED_object_base_select(base, BA_SELECT); @@ -294,7 +294,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_SELECTABLED) != 0)) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) { /* loop through other particles*/ ParticleSystem *psys; @@ -322,7 +322,7 @@ static bool object_select_all_by_library(bContext *C, Library *lib) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) { if (lib == base->object->id.lib) { ED_object_base_select(base, BA_SELECT); changed = true; @@ -340,7 +340,7 @@ static bool object_select_all_by_library_obdata(bContext *C, Library *lib) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) { if (base->object->data && lib == ((ID *)base->object->data)->lib) { ED_object_base_select(base, BA_SELECT); changed = true; @@ -568,7 +568,7 @@ static bool select_grouped_collection(bContext *C, Object *ob) /* Select object collection = ob_collections[0]; CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) { if (BKE_collection_has_object(collection, base->object)) { ED_object_base_select(base, BA_SELECT); changed = true; @@ -931,7 +931,7 @@ static int object_select_same_collection_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) { if (BKE_collection_has_object(collection, base->object)) { ED_object_base_select(base, BA_SELECT); } diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index e926540408e..cfdeeffc434 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -410,6 +410,8 @@ typedef struct PEData { BVHTreeFromMesh shape_bvh; Depsgraph *depsgraph; + RNG *rng; + const int *mval; rcti *rect; float rad; @@ -484,6 +486,22 @@ static void PE_free_shape_tree(PEData *data) free_bvhtree_from_mesh(&data->shape_bvh); } +static void PE_create_random_generator(PEData *data) +{ + uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); + rng_seed ^= GET_UINT_FROM_POINTER(data->ob); + rng_seed ^= GET_UINT_FROM_POINTER(data->edit); + data->rng = BLI_rng_new(rng_seed); +} + +static void PE_free_random_generator(PEData *data) +{ + if (data->rng != NULL) { + BLI_rng_free(data->rng); + data->rng = NULL; + } +} + /*************************** selection utilities *******************************/ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[2]) @@ -2999,7 +3017,7 @@ static void PE_mirror_x( /* Note: In case psys uses Mesh tessface indices, we mirror final Mesh itself, not orig mesh. Avoids an (impossible) * mesh -> orig -> mesh tessface indices conversion... */ - mirrorfaces = mesh_get_x_mirror_faces__real_mesh(ob, NULL, use_dm_final_indices ? psmd_eval->mesh_final : NULL); + mirrorfaces = mesh_get_x_mirror_faces(ob, NULL, use_dm_final_indices ? psmd_eval->mesh_final : NULL); if (!edit->mirror_cache) PE_update_mirror_cache(ob, psys); @@ -3181,8 +3199,11 @@ static void brush_cut(PEData *data, int pa_index) int k, cut, keys= (int)pow(2.0, (double)pset->draw_step); int screen_co[2]; + BLI_assert(data->rng != NULL); /* blunt scissors */ - if (BLI_frand() > data->cutfac) return; + if (BLI_rng_get_float(data->rng) > data->cutfac) { + return; + } /* don't cut hidden */ if (edit->points[pa_index].flag & PEP_HIDE) @@ -4040,6 +4061,7 @@ static int brush_edit_init(bContext *C, wmOperator *op) /* cache view depths and settings for re-use */ PE_set_view3d_data(C, &bedit->data); + PE_create_random_generator(&bedit->data); return 1; } @@ -4088,7 +4110,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) if (((pset->brushtype == PE_BRUSH_ADD) ? (sqrtf(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0)) || bedit->first) { - PEData data= bedit->data; + PEData data = bedit->data; data.context = C; // TODO(mai): why isnt this set in bedit->data? view3d_operator_needs_opengl(C); @@ -4273,6 +4295,7 @@ static void brush_edit_exit(wmOperator *op) { BrushEdit *bedit= op->customdata; + PE_free_random_generator(&bedit->data); MEM_freeN(bedit); } diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c index f62b72679d0..1b6325e31bf 100644 --- a/source/blender/editors/physics/rigidbody_constraint.c +++ b/source/blender/editors/physics/rigidbody_constraint.c @@ -94,6 +94,8 @@ bool ED_rigidbody_constraint_add(Main *bmain, Scene *scene, Object *ob, int type DEG_relations_tag_update(bmain); DEG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&rbw->constraints->id, DEG_TAG_COPY_ON_WRITE); + return true; } @@ -102,8 +104,10 @@ void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob) RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); BKE_rigidbody_remove_constraint(scene, ob); - if (rbw) + if (rbw) { BKE_collection_object_remove(bmain, rbw->constraints, ob, false); + DEG_id_tag_update(&rbw->constraints->id, DEG_TAG_COPY_ON_WRITE); + } DEG_relations_tag_update(bmain); DEG_id_tag_update(&ob->id, OB_RECALC_OB); diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index bdfbc47b22f..6ea0212199e 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -125,6 +125,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re DEG_relations_tag_update(bmain); DEG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&rbw->group->id, DEG_TAG_COPY_ON_WRITE); return true; } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 6a5844e323f..1385baa51ad 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -819,7 +819,7 @@ static void screen_render_cancel(bContext *C, wmOperator *op) static void clean_viewport_memory_base(Base *base) { - if ((base->flag & BASE_VISIBLED) == 0) { + if ((base->flag & BASE_VISIBLE) == 0) { return; } diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index cdd79f43a72..d47291ca82f 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -176,9 +176,6 @@ typedef struct ShaderPreview { Main *bmain; Main *pr_main; - - void *gl_context; - bool gl_context_owner; } ShaderPreview; typedef struct IconPreviewSize { @@ -194,8 +191,6 @@ typedef struct IconPreview { void *owner; ID *id; ListBase sizes; - - void *gl_context; } IconPreview; /* *************************** Preview for buttons *********************** */ @@ -428,7 +423,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty (*matar)[actcol] = mat; } else if (base->object->type == OB_LAMP) { - base->flag |= BASE_VISIBLED; + base->flag |= BASE_VISIBLE; } } } @@ -746,10 +741,6 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs /* set this for all previews, default is react to G.is_break still */ RE_test_break_cb(re, sp, shader_preview_break); - if (sp->gl_context) { - RE_gl_context_set(re, sp->gl_context); - } - /* lens adjust */ oldlens = ((Camera *)sce->camera->data)->lens; if (sizex > sp->sizey) @@ -869,10 +860,6 @@ static void shader_preview_free(void *customdata) } MEM_freeN(sp->lampcopy); } - if (sp->gl_context_owner && sp->gl_context) { - WM_opengl_context_dispose(sp->gl_context); - sp->gl_context = NULL; - } MEM_freeN(sp); } @@ -1088,8 +1075,6 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short sp->pr_rect = cur_size->rect; sp->id = ip->id; sp->bmain = ip->bmain; - sp->gl_context = ip->gl_context; - sp->gl_context_owner = false; if (is_render) { BLI_assert(ip->id); @@ -1106,11 +1091,6 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short common_preview_startjob(sp, stop, do_update, progress); shader_preview_free(sp); } - - if (ip->gl_context) { - WM_opengl_context_dispose(ip->gl_context); - ip->gl_context = NULL; - } } static void icon_preview_endjob(void *customdata) @@ -1194,17 +1174,8 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r /* render all resolutions from suspended job too */ old_ip = WM_jobs_customdata_get(wm_job); - if (old_ip) { + if (old_ip) BLI_movelisttolist(&ip->sizes, &old_ip->sizes); - /* NOTE: This assumes that it will be the same thread - * that will be used when resuming the job. */ - ip->gl_context = old_ip->gl_context; - } - - if (ip->gl_context == NULL) { - /* Create context in the main thread. */ - ip->gl_context = WM_opengl_context_create(); - } /* customdata for preview thread */ ip->bmain = CTX_data_main(C); @@ -1235,7 +1206,7 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M { Object *ob = CTX_data_active_object(C); wmJob *wm_job; - ShaderPreview *sp, *old_sp; + ShaderPreview *sp; Scene *scene = CTX_data_scene(C); short id_type = GS(id->name); @@ -1252,21 +1223,6 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW); sp = MEM_callocN(sizeof(ShaderPreview), "shader preview"); - /* Reuse previous gl context. */ - old_sp = WM_jobs_customdata_get(wm_job); - if (old_sp) { - /* NOTE: This assumes that it will be the same thread - * that will be used when resuming the job. */ - old_sp->gl_context_owner = false; /* Don't free it */ - sp->gl_context = old_sp->gl_context; - } - - if (sp->gl_context == NULL) { - /* Create context in the main thread. */ - sp->gl_context = WM_opengl_context_create(); - } - sp->gl_context_owner = true; - /* customdata for preview thread */ sp->scene = scene; sp->depsgraph = CTX_data_depsgraph(C); diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt index 29b9971eabb..ee114eba3c5 100644 --- a/source/blender/editors/screen/CMakeLists.txt +++ b/source/blender/editors/screen/CMakeLists.txt @@ -47,6 +47,7 @@ set(SRC screen_draw.c screen_edit.c screen_ops.c + screen_user_menu.c screendump.c workspace_edit.c workspace_layout_edit.c diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 864150be9da..f56a27d1bb4 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -115,7 +115,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } else if (CTX_data_equals(member, "selectable_objects")) { for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (((base->flag & BASE_VISIBLED) != 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (((base->flag & BASE_VISIBLE) != 0) && ((base->flag & BASE_SELECTABLE) != 0)) { CTX_data_id_list_add(result, &base->object->id); } } @@ -165,7 +165,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } else if (CTX_data_equals(member, "selectable_bases")) { for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if ((base->flag & BASE_SELECTABLED) != 0) { + if ((base->flag & BASE_SELECTABLE) != 0) { CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); } } @@ -195,7 +195,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult else if (CTX_data_equals(member, "editable_bases")) { /* Visible + Editable, but not necessarily selected */ for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if ((base->flag & BASE_VISIBLED) != 0) { + if ((base->flag & BASE_VISIBLE) != 0) { if (0 == BKE_object_is_libdata(base->object)) { CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); } diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 4d7533d575c..e4de3cdfa38 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -961,7 +961,7 @@ static void screen_cursor_set(wmWindow *win, const int xy[2]) ScrArea *sa; for (sa = screen->areabase.first; sa; sa = sa->next) - if ((az = is_in_area_actionzone(sa, xy))) + if ((az = ED_area_actionzone_find_xy(sa, xy))) break; if (sa) { @@ -1003,7 +1003,7 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) ED_screen_areas_iter(win, scr, area_iter) { if (xy[0] > area_iter->totrct.xmin && xy[0] < area_iter->totrct.xmax) { if (xy[1] > area_iter->totrct.ymin && xy[1] < area_iter->totrct.ymax) { - if (is_in_area_actionzone(area_iter, xy) == NULL) { + if (ED_area_actionzone_refresh_xy(area_iter, xy) == NULL) { sa = area_iter; break; } @@ -1073,7 +1073,7 @@ int ED_screen_area_active(const bContext *C) ScrArea *sa = CTX_wm_area(C); if (win && sc && sa) { - AZone *az = is_in_area_actionzone(sa, &win->eventstate->x); + AZone *az = ED_area_actionzone_find_xy(sa, &win->eventstate->x); ARegion *ar; if (az && az->type == AZONE_REGION) @@ -1680,6 +1680,7 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph) for (sc = bmain->screen.first; sc; sc = sc->id.next) { BKE_screen_view3d_scene_sync(sc, scene); } + DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE); } #endif diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h index b02198764e0..2c343fb9d70 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -67,7 +67,8 @@ ScrEdge *screen_find_active_scredge( const wmWindow *win, const bScreen *screen, const int mx, const int my); -struct AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]); +struct AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2]); +struct AZone *ED_area_actionzone_refresh_xy(ScrArea *sa, const int xy[2]); /* screen_context.c */ int ed_screen_context( diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index c2dab7e22dd..d74a9ed288c 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -669,7 +669,7 @@ static void fullscreen_click_rcti_init(rcti *rect, const short x1, const short y BLI_rcti_init(rect, x, x + icon_size, y, y + icon_size); } -AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]) +static AZone *area_actionzone_refresh_xy(ScrArea *sa, const int xy[2], const bool test_only) { AZone *az = NULL; @@ -677,102 +677,117 @@ AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]) if (BLI_rcti_isect_pt_v(&az->rect, xy)) { if (az->type == AZONE_AREA) { /* no triangle intersect but a hotspot circle based on corner */ - int radius = (xy[0] - az->x1) * (xy[0] - az->x1) + (xy[1] - az->y1) * (xy[1] - az->y1); - - if (radius <= AZONESPOT * AZONESPOT) + int radius_sq = SQUARE(xy[0] - az->x1) + SQUARE(xy[1] - az->y1); + if (radius_sq <= SQUARE(AZONESPOT)) { break; + } } else if (az->type == AZONE_REGION) { break; } else if (az->type == AZONE_FULLSCREEN) { - int mouse_radius, spot_radius, fadein_radius, fadeout_radius; rcti click_rect; - fullscreen_click_rcti_init(&click_rect, az->x1, az->y1, az->x2, az->y2); + const bool click_isect = BLI_rcti_isect_pt_v(&click_rect, xy); - if (BLI_rcti_isect_pt_v(&click_rect, xy)) { - az->alpha = 1.0f; + if (test_only) { + if (click_isect) { + break; + } } else { - mouse_radius = (xy[0] - az->x2) * (xy[0] - az->x2) + (xy[1] - az->y2) * (xy[1] - az->y2); - spot_radius = AZONESPOT * AZONESPOT; - fadein_radius = AZONEFADEIN * AZONEFADEIN; - fadeout_radius = AZONEFADEOUT * AZONEFADEOUT; - - if (mouse_radius < spot_radius) { + if (click_isect) { az->alpha = 1.0f; } - else if (mouse_radius < fadein_radius) { - az->alpha = 1.0f; - } - else if (mouse_radius < fadeout_radius) { - az->alpha = 1.0f - ((float)(mouse_radius - fadein_radius)) / ((float)(fadeout_radius - fadein_radius)); - } else { - az->alpha = 0.0f; + const int mouse_sq = SQUARE(xy[0] - az->x2) + SQUARE(xy[1] - az->y2); + const int spot_sq = SQUARE(AZONESPOT); + const int fadein_sq = SQUARE(AZONEFADEIN); + const int fadeout_sq = SQUARE(AZONEFADEOUT); + + if (mouse_sq < spot_sq) { + az->alpha = 1.0f; + } + else if (mouse_sq < fadein_sq) { + az->alpha = 1.0f; + } + else if (mouse_sq < fadeout_sq) { + az->alpha = 1.0f - ((float)(mouse_sq - fadein_sq)) / ((float)(fadeout_sq - fadein_sq)); + } + else { + az->alpha = 0.0f; + } + + /* fade in/out but no click */ + az = NULL; } - /* fade in/out but no click */ - az = NULL; + /* XXX force redraw to show/hide the action zone */ + ED_area_tag_redraw(sa); + break; } - - /* XXX force redraw to show/hide the action zone */ - ED_area_tag_redraw_no_rebuild(sa); - break; } else if (az->type == AZONE_REGION_SCROLL) { ARegion *ar = az->ar; View2D *v2d = &ar->v2d; const short isect_value = UI_view2d_mouse_in_scrollers(ar, v2d, xy[0], xy[1]); - bool redraw = false; - - if (isect_value == 'h') { - if (az->direction == AZ_SCROLL_HOR) { - az->alpha = 1.0f; - v2d->alpha_hor = 255; - v2d->size_hor = V2D_SCROLL_HEIGHT; - redraw = true; - } - } - else if (isect_value == 'v') { - if (az->direction == AZ_SCROLL_VERT) { - az->alpha = 1.0f; - v2d->alpha_vert = 255; - v2d->size_vert = V2D_SCROLL_WIDTH; - redraw = true; + if (test_only) { + if (isect_value != 0) { + break; } } else { - const int local_xy[2] = {xy[0] - ar->winrct.xmin, xy[1] - ar->winrct.ymin}; - float dist_fac = 0.0f, alpha = 0.0f; - - if (az->direction == AZ_SCROLL_HOR) { - dist_fac = BLI_rcti_length_y(&v2d->hor, local_xy[1]) / AZONEFADEIN; - CLAMP(dist_fac, 0.0f, 1.0f); - alpha = 1.0f - dist_fac; + bool redraw = false; - v2d->alpha_hor = alpha * 255; - v2d->size_hor = round_fl_to_int(V2D_SCROLL_HEIGHT - - ((V2D_SCROLL_HEIGHT - V2D_SCROLL_HEIGHT_MIN) * dist_fac)); + if (isect_value == 'h') { + if (az->direction == AZ_SCROLL_HOR) { + az->alpha = 1.0f; + v2d->alpha_hor = 255; + v2d->size_hor = V2D_SCROLL_HEIGHT; + redraw = true; + } } - else if (az->direction == AZ_SCROLL_VERT) { - dist_fac = BLI_rcti_length_x(&v2d->vert, local_xy[0]) / AZONEFADEIN; - CLAMP(dist_fac, 0.0f, 1.0f); - alpha = 1.0f - dist_fac; - - v2d->alpha_vert = alpha * 255; - v2d->size_vert = round_fl_to_int(V2D_SCROLL_WIDTH - - ((V2D_SCROLL_WIDTH - V2D_SCROLL_WIDTH_MIN) * dist_fac)); + else if (isect_value == 'v') { + if (az->direction == AZ_SCROLL_VERT) { + az->alpha = 1.0f; + v2d->alpha_vert = 255; + v2d->size_vert = V2D_SCROLL_WIDTH; + redraw = true; + } + } + else { + const int local_xy[2] = {xy[0] - ar->winrct.xmin, xy[1] - ar->winrct.ymin}; + float dist_fac = 0.0f, alpha = 0.0f; + + if (az->direction == AZ_SCROLL_HOR) { + dist_fac = BLI_rcti_length_y(&v2d->hor, local_xy[1]) / AZONEFADEIN; + CLAMP(dist_fac, 0.0f, 1.0f); + alpha = 1.0f - dist_fac; + + v2d->alpha_hor = alpha * 255; + v2d->size_hor = round_fl_to_int( + V2D_SCROLL_HEIGHT - + ((V2D_SCROLL_HEIGHT - V2D_SCROLL_HEIGHT_MIN) * dist_fac)); + } + else if (az->direction == AZ_SCROLL_VERT) { + dist_fac = BLI_rcti_length_x(&v2d->vert, local_xy[0]) / AZONEFADEIN; + CLAMP(dist_fac, 0.0f, 1.0f); + alpha = 1.0f - dist_fac; + + v2d->alpha_vert = alpha * 255; + v2d->size_vert = round_fl_to_int( + V2D_SCROLL_WIDTH - + ((V2D_SCROLL_WIDTH - V2D_SCROLL_WIDTH_MIN) * dist_fac)); + } + az->alpha = alpha; + redraw = true; } - az->alpha = alpha; - redraw = true; - } - if (redraw) { - ED_area_tag_redraw_no_rebuild(sa); + if (redraw) { + ED_area_tag_redraw_no_rebuild(sa); + } + /* Don't return! */ } - /* Don't return! */ } } } @@ -780,6 +795,15 @@ AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]) return az; } +AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2]) +{ + return area_actionzone_refresh_xy(sa, xy, true); +} + +AZone *ED_area_actionzone_refresh_xy(ScrArea *sa, const int xy[2]) +{ + return area_actionzone_refresh_xy(sa, xy, false); +} static void actionzone_exit(wmOperator *op) { @@ -817,7 +841,7 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type) static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ScrArea *sa = CTX_wm_area(C); - AZone *az = is_in_area_actionzone(sa, &event->x); + AZone *az = ED_area_actionzone_find_xy(sa, &event->x); sActionzoneData *sad; /* quick escape */ @@ -878,7 +902,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) WM_window_screen_rect_calc(win, &screen_rect); /* once we drag outside the actionzone, register a gesture * check we're not on an edge so join finds the other area */ - is_gesture = ((is_in_area_actionzone(sad->sa1, &event->x) != sad->az) && + is_gesture = ((ED_area_actionzone_find_xy(sad->sa1, &event->x) != sad->az) && (screen_area_map_find_active_scredge( AREAMAP_FROM_SCREEN(sc), &screen_rect, event->x, event->y) == NULL)); } @@ -4808,7 +4832,7 @@ void ED_keymap_screen(wmKeyConfig *keyconf) /* tests */ WM_keymap_add_item(keymap, "SCREEN_OT_region_quadview", QKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); - WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_history", F3KEY, KM_PRESS, 0, 0); + WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_history", RKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_item(keymap, "SCREEN_OT_repeat_last", RKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_verify_item(keymap, "SCREEN_OT_region_flip", F5KEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "SCREEN_OT_redo_last", F6KEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c new file mode 100644 index 00000000000..d942602c896 --- /dev/null +++ b/source/blender/editors/screen/screen_user_menu.c @@ -0,0 +1,164 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/screen/screen_user_menu.c + * \ingroup spview3d + */ + +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <float.h> + +#include "DNA_scene_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "BLT_translation.h" + +#include "BKE_blender_user_menu.h" +#include "BKE_context.h" +#include "BKE_screen.h" +#include "BKE_idprop.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +/* -------------------------------------------------------------------- */ +/** \name Menu Type + * \{ */ + +bUserMenu *ED_screen_user_menu_find(bContext *C) +{ + SpaceLink *sl = CTX_wm_space_data(C); + const char *context = CTX_data_mode_string(C); + return BKE_blender_user_menu_find(&U.user_menus, sl->spacetype, context); +} + +bUserMenu *ED_screen_user_menu_ensure(bContext *C) +{ + SpaceLink *sl = CTX_wm_space_data(C); + const char *context = CTX_data_mode_string(C); + return BKE_blender_user_menu_ensure(&U.user_menus, sl->spacetype, context); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Menu Item + * \{ */ + +bUserMenuItem_Op *ED_screen_user_menu_item_find_operator( + ListBase *lb, + wmOperatorType *ot, IDProperty *prop, short opcontext) +{ + for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) { + if (umi->type == USER_MENU_TYPE_OPERATOR) { + bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi; + if (STREQ(ot->idname, umi_op->opname) && + (opcontext == umi_op->opcontext) && + (IDP_EqualsProperties(prop, umi_op->prop))) + { + return umi_op; + } + } + } + return NULL; +} + +void ED_screen_user_menu_item_add_operator( + ListBase *lb, const char *ui_name, + wmOperatorType *ot, IDProperty *prop, short opcontext) +{ + bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)BKE_blender_user_menu_item_add(lb, USER_MENU_TYPE_OPERATOR); + umi_op->opcontext = opcontext; + if (!STREQ(ui_name, ot->name)) { + BLI_strncpy(umi_op->item.ui_name, ui_name, OP_MAX_TYPENAME); + } + BLI_strncpy(umi_op->opname, ot->idname, OP_MAX_TYPENAME); + umi_op->prop = prop ? IDP_CopyProperty(prop) : NULL; +} + +void ED_screen_user_menu_item_remove(ListBase *lb, bUserMenuItem *umi) +{ + BLI_remlink(lb, umi); + BKE_blender_user_menu_item_free(umi); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Menu Definition + * \{ */ + +static void screen_user_menu_draw(const bContext *C, Menu *menu) +{ + SpaceLink *sl = CTX_wm_space_data(C); + const char *context = CTX_data_mode_string(C); + bUserMenu *um_array[] = { + BKE_blender_user_menu_find(&U.user_menus, sl->spacetype, context), + (sl->spacetype != SPACE_TOPBAR) ? BKE_blender_user_menu_find(&U.user_menus, SPACE_TOPBAR, context) : NULL, + }; + for (int um_index = 0; um_index < ARRAY_SIZE(um_array); um_index++) { + bUserMenu *um = um_array[um_index]; + if (um == NULL) { + continue; + } + for (bUserMenuItem *umi = um->items.first; umi; umi = umi->next) { + if (umi->type == USER_MENU_TYPE_OPERATOR) { + bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi; + IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL; + uiItemFullO( + menu->layout, umi_op->opname, umi->ui_name[0] ? umi->ui_name : NULL, + ICON_NONE, prop, umi_op->opcontext, 0, NULL); + } + else if (umi->type == USER_MENU_TYPE_SEP) { + uiItemS(menu->layout); + } + } + } +} + +void ED_screen_user_menu_register(void) +{ + MenuType *mt = MEM_callocN(sizeof(MenuType), __func__); + strcpy(mt->idname, "SCREEN_MT_user_menu"); + strcpy(mt->label, "Quick Favorites"); + strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + mt->draw = screen_user_menu_draw; + WM_menutype_add(mt); +} + +/** \} */ diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c index af0b828ae39..e2100ceb066 100644 --- a/source/blender/editors/sculpt_paint/paint_curve.c +++ b/source/blender/editors/sculpt_paint/paint_curve.c @@ -714,7 +714,7 @@ static int paintcurve_cursor_invoke(bContext *C, wmOperator *UNUSED(op), const w break; } default: - ED_view3d_cursor3d_update(C, event->mval); + ED_view3d_cursor3d_update(C, event->mval, true, V3D_CURSOR_ORIENT_VIEW); break; } diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index ac5b0624d56..4deec54a5b3 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -46,7 +46,6 @@ #include "BKE_pbvh.h" #include "BKE_ccg.h" #include "BKE_context.h" -#include "BKE_DerivedMesh.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_multires.h" diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 93fa3aac0d7..3c097095ddc 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -46,15 +46,16 @@ #include "IMB_imbuf_types.h" #include "DNA_brush_types.h" +#include "DNA_mesh_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "BKE_colorband.h" #include "BKE_context.h" -#include "BKE_DerivedMesh.h" #include "BKE_brush.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_mesh.h" #include "BKE_node.h" #include "BKE_paint.h" #include "BKE_undo_system.h" @@ -1055,6 +1056,7 @@ static int texture_paint_toggle_poll(bContext *C) static int texture_paint_toggle_exec(bContext *C, wmOperator *op) { struct wmMsgBus *mbus = CTX_wm_message_bus(C); + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); const int mode_flag = OB_MODE_TEXTURE_PAINT; @@ -1070,14 +1072,13 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) ob->mode &= ~mode_flag; if (U.glreslimit != 0) - GPU_free_images(); - GPU_paint_set_mipmap(1); + GPU_free_images(bmain); + GPU_paint_set_mipmap(bmain, 1); toggle_paint_cursor(C, 0); } else { bScreen *sc; - Main *bmain = CTX_data_main(C); Image *ima = NULL; ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; @@ -1122,12 +1123,16 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) BKE_paint_init(bmain, scene, ePaintTextureProjective, PAINT_CURSOR_TEXTURE_PAINT); if (U.glreslimit != 0) - GPU_free_images(); - GPU_paint_set_mipmap(0); + GPU_free_images(bmain); + GPU_paint_set_mipmap(bmain, 0); toggle_paint_cursor(C, 1); } + Mesh *me = BKE_mesh_from_object(ob); + BLI_assert(me != NULL); + DEG_id_tag_update(&me->id, DEG_TAG_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene); WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 62bc379241f..bbf1da2d584 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -58,6 +58,7 @@ #include "DNA_brush_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" @@ -65,7 +66,6 @@ #include "BKE_colorband.h" #include "BKE_context.h" #include "BKE_colortools.h" -#include "BKE_DerivedMesh.h" #include "BKE_idprop.h" #include "BKE_brush.h" #include "BKE_image.h" diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index f22e6f514e6..4a338e65d79 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -45,7 +45,6 @@ #include "BKE_pbvh.h" #include "BKE_ccg.h" #include "BKE_context.h" -#include "BKE_DerivedMesh.h" #include "BKE_multires.h" #include "BKE_paint.h" #include "BKE_subsurf.h" diff --git a/source/blender/editors/sculpt_paint/paint_vertex_proj.c b/source/blender/editors/sculpt_paint/paint_vertex_proj.c index cacfdc2dbba..602bfe1ab8e 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_proj.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_proj.c @@ -28,7 +28,7 @@ * \ingroup edsculpt * * Utility functions for getting vertex locations while painting - * (since they may be instanced multiple times in a DerivedMesh) + * (since they may be instanced multiple times in an evaluated mesh) */ #include "MEM_guardedalloc.h" @@ -39,8 +39,9 @@ #include "DNA_mesh_types.h" #include "DNA_object_types.h" -#include "BKE_DerivedMesh.h" +#include "BKE_DerivedMesh.h" /* XXX To be removed, only used for DMCoNo struct */ #include "BKE_context.h" +#include "BKE_mesh_iterators.h" #include "BKE_mesh_runtime.h" #include "DEG_depsgraph.h" @@ -107,24 +108,10 @@ static void vpaint_proj_dm_map_cosnos_init( struct VertProjHandle *vp_handle) { Mesh *me = ob->data; - DerivedMesh *dm; + Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); - dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); - - if (dm->foreachMappedVert) { - memset(vp_handle->vcosnos, 0, sizeof(DMCoNo) * me->totvert); - dm->foreachMappedVert(dm, vpaint_proj_dm_map_cosnos_init__map_cb, vp_handle, DM_FOREACH_USE_NORMAL); - } - else { - DMCoNo *v_co_no = vp_handle->vcosnos; - int a; - for (a = 0; a < me->totvert; a++, v_co_no++) { - dm->getVertCo(dm, a, v_co_no->co); - dm->getVertNo(dm, a, v_co_no->no); - } - } - - dm->release(dm); + memset(vp_handle->vcosnos, 0, sizeof(*vp_handle->vcosnos) * me->totvert); + BKE_mesh_foreach_mapped_vert(me_eval, vpaint_proj_dm_map_cosnos_init__map_cb, vp_handle, MESH_FOREACH_USE_NORMAL); } @@ -185,21 +172,13 @@ static void vpaint_proj_dm_map_cosnos_update( Scene *scene = vp_handle->scene; Object *ob = vp_handle->ob; Mesh *me = ob->data; - DerivedMesh *dm; + Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); /* quick sanity check - we shouldn't have to run this if there are no modifiers */ BLI_assert(BLI_listbase_is_empty(&ob->modifiers) == false); - dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); - - /* highly unlikely this will become unavailable once painting starts (perhaps with animated modifiers) */ - if (LIKELY(dm->foreachMappedVert)) { - copy_vn_fl(vp_handle->dists_sq, me->totvert, FLT_MAX); - - dm->foreachMappedVert(dm, vpaint_proj_dm_map_cosnos_update__map_cb, &vp_update, DM_FOREACH_USE_NORMAL); - } - - dm->release(dm); + copy_vn_fl(vp_handle->dists_sq, me->totvert, FLT_MAX); + BKE_mesh_foreach_mapped_vert(me_eval, vpaint_proj_dm_map_cosnos_update__map_cb, &vp_update, MESH_FOREACH_USE_NORMAL); } 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 7d241835b62..126b3b42e8f 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -35,8 +35,8 @@ #include "IMB_imbuf_types.h" #include "IMB_colormanagement.h" -//#include "DNA_armature_types.h" #include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "DNA_particle_types.h" #include "DNA_brush_types.h" #include "DNA_object_types.h" @@ -46,11 +46,11 @@ #include "RNA_define.h" #include "RNA_enum_types.h" -#include "BKE_DerivedMesh.h" #include "BKE_brush.h" #include "BKE_context.h" #include "BKE_deform.h" #include "BKE_mesh.h" +#include "BKE_mesh_iterators.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_runtime.h" #include "BKE_modifier.h" @@ -785,31 +785,16 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) ED_view3d_init_mats_rv3d(ob, ar->regiondata); Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob, scene->customdata_mask | CD_MASK_ORIGINDEX); - int *mv_orig_indices = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX); - MVert *mv = me_eval->mvert; - /* NULL origindex is valid when wehave no generative modifiers... */ - BLI_assert(mv_orig_indices != NULL || me_eval->totvert == me->totvert); if (data.is_init) { data.vert_visit = BLI_BITMAP_NEW(me->totvert, __func__); - /* TODO add some similar helpers as DM's foreachMappedXXX callbacks, for evaluated mesh? */ - for (int mv_idx = 0; mv_idx < me_eval->totvert; mv_idx++, mv++) { - const int mv_orig_idx = mv_orig_indices != NULL ? mv_orig_indices[mv_idx] : mv_idx; - if (mv_orig_idx != ORIGINDEX_NONE) { - gradientVertInit__mapFunc(&data, mv_orig_idx, mv->co, NULL, NULL); - } - } + BKE_mesh_foreach_mapped_vert(me_eval, gradientVertInit__mapFunc, &data, MESH_FOREACH_NOP); MEM_freeN(data.vert_visit); data.vert_visit = NULL; } else { - for (int mv_idx = 0; mv_idx < me_eval->totvert; mv_idx++, mv++) { - const int mv_orig_idx = mv_orig_indices != NULL ? mv_orig_indices[mv_idx] : mv_idx; - if (mv_orig_idx != ORIGINDEX_NONE) { - gradientVertUpdate__mapFunc(&data, mv_orig_idx, mv->co, NULL, NULL); - } - } + BKE_mesh_foreach_mapped_vert(me_eval, gradientVertUpdate__mapFunc, &data, MESH_FOREACH_NOP); } DEG_id_tag_update(&ob->id, OB_RECALC_DATA); diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 2872ad4fb9c..bc22147b15d 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -561,7 +561,7 @@ static void sculpt_undo_restore_list(bContext *C, ListBase *lb) else { BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild); } - BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw, NULL); + BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw | PBVH_UpdateNormals, NULL); if (BKE_sculpt_multires_active(scene, ob)) { if (rebuild) diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 527e382ec1e..537f184c71c 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -47,6 +47,8 @@ #include "BKE_screen.h" #include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_types.h" @@ -102,6 +104,7 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene) saction->autosnap = SACTSNAP_FRAME; saction->mode = SACTCONT_DOPESHEET; + saction->mode_prev = SACTCONT_DOPESHEET; saction->ads.filterflag |= ADS_FILTER_SUMMARY; @@ -835,6 +838,37 @@ static void action_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, I } +/** + * \note Used for splitting out a subset of modes is more involved, + * The previous non-timeline mode is stored so switching back to the + * dope-sheet doesn't always reset the sub-mode. + */ +static int action_space_subtype_get(ScrArea *sa) +{ + SpaceAction *sact = sa->spacedata.first; + return sact->mode == SACTCONT_TIMELINE ? SACTCONT_TIMELINE : SACTCONT_DOPESHEET; +} + +static void action_space_subtype_set(ScrArea *sa, int value) +{ + SpaceAction *sact = sa->spacedata.first; + if (value == SACTCONT_TIMELINE) { + if (sact->mode != SACTCONT_TIMELINE) { + sact->mode_prev = sact->mode; + } + sact->mode = value; + } + else { + sact->mode = sact->mode_prev; + } +} + +static void action_space_subtype_item_extend( + bContext *UNUSED(C), EnumPropertyItem **item, int *totitem) +{ + RNA_enum_items_add(item, totitem, rna_enum_space_action_mode_items); +} + /* only called once, from space/spacetypes.c */ void ED_spacetype_action(void) { @@ -853,6 +887,9 @@ void ED_spacetype_action(void) st->listener = action_listener; st->refresh = action_refresh; st->id_remap = action_id_remap; + st->space_subtype_item_extend = action_space_subtype_item_extend; + st->space_subtype_get = action_space_subtype_get; + st->space_subtype_set = action_space_subtype_set; /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype action region"); diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 33ec7f771ba..2ee791e81d6 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -127,6 +127,8 @@ void ED_spacetypes_init(void) ED_operatortypes_view2d(); ED_operatortypes_ui(); + ED_screen_user_menu_register(); + /* manipulator types */ ED_manipulatortypes_button_2d(); ED_manipulatortypes_dial_3d(); diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 469d94fed3a..f2fe06874d7 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -387,7 +387,7 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P else tip = TIP_("Marker is enabled at current frame"); - bt = uiDefIconButBitI(block, UI_BTYPE_TOGGLE_N, MARKER_DISABLED, 0, ICON_RESTRICT_VIEW_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y, + bt = uiDefIconButBitI(block, UI_BTYPE_TOGGLE_N, MARKER_DISABLED, 0, ICON_HIDE_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y, &cb->marker_flag, 0, 0, 1, 0, tip); UI_but_funcN_set(bt, marker_update_cb, cb, NULL); } diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c index f55a5511e2d..e543111e662 100644 --- a/source/blender/editors/space_graph/graph_utils.c +++ b/source/blender/editors/space_graph/graph_utils.c @@ -44,17 +44,62 @@ #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_screen.h" #include "WM_api.h" #include "ED_anim_api.h" +#include "ED_screen.h" +#include "UI_interface.h" #include "graph_intern.h" // own include /* ************************************************************** */ +/* Set Up Drivers Editor */ + +/* Set up UI configuration for Drivers Editor */ +/* NOTE: Currently called from windowmanager (new drivers editor window) and RNA (mode switching) */ +void ED_drivers_editor_init(bContext *C, ScrArea *sa) +{ + SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first; + + /* Set mode */ + sipo->mode = SIPO_MODE_DRIVERS; + + /* Show Properties Region (or else the settings can't be edited) */ + ARegion *ar_props = BKE_area_find_region_type(sa, RGN_TYPE_UI); + if (ar_props) { + UI_panel_category_active_set(ar_props, "Drivers"); + + ar_props->flag &= ~RGN_FLAG_HIDDEN; + /* XXX: Adjust width of this too? */ + + ED_region_visibility_change_update(C, ar_props); + } + else { + printf("%s: Couldn't find properties region for Drivers Editor - %p\n", __func__, sa); + } + + /* Adjust framing in graph region */ + /* TODO: Have a way of not resetting this every time? + * (e.g. So that switching back and forth between editors doesn't keep jumping?) + */ + ARegion *ar_main = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + if (ar_main) { + /* XXX: Ideally we recenter based on the range instead... */ + ar_main->v2d.tot.xmin = -2.0f; + ar_main->v2d.tot.ymin = -2.0f; + ar_main->v2d.tot.xmax = 2.0f; + ar_main->v2d.tot.ymax = 2.0f; + + ar_main->v2d.cur = ar_main->v2d.tot; + } +} + +/* ************************************************************** */ /* Active F-Curve */ /* Find 'active' F-Curve. It must be editable, since that's the purpose of these buttons (subject to change). diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 59d7d7500ae..7c3105843c5 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -60,6 +60,8 @@ #include "WM_message.h" #include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -181,14 +183,14 @@ static void graph_free(SpaceLink *sl) /* spacetype; init callback */ -static void graph_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa) +static void graph_init(struct wmWindowManager *wm, ScrArea *sa) { SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first; /* init dopesheet data if non-existent (i.e. for old files) */ if (sipo->ads == NULL) { sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet"); - sipo->ads->source = (ID *)(G.main->scene.first); // FIXME: this is a really nasty hack here for now... + sipo->ads->source = (ID *)WM_window_get_active_scene(wm->winactive); } /* force immediate init of any invalid F-Curve colors */ @@ -799,6 +801,24 @@ static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID } } +static int graph_space_subtype_get(ScrArea *sa) +{ + SpaceIpo *sgraph = sa->spacedata.first; + return sgraph->mode; +} + +static void graph_space_subtype_set(ScrArea *sa, int value) +{ + SpaceIpo *sgraph = sa->spacedata.first; + sgraph->mode = value; +} + +static void graph_space_subtype_item_extend( + bContext *UNUSED(C), EnumPropertyItem **item, int *totitem) +{ + RNA_enum_items_add(item, totitem, rna_enum_space_graph_mode_items); +} + /* only called once, from space/spacetypes.c */ void ED_spacetype_ipo(void) { @@ -817,6 +837,9 @@ void ED_spacetype_ipo(void) st->listener = graph_listener; st->refresh = graph_refresh; st->id_remap = graph_id_remap; + st->space_subtype_item_extend = graph_space_subtype_item_extend; + st->space_subtype_get = graph_space_subtype_get; + st->space_subtype_set = graph_space_subtype_set; /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); @@ -867,4 +890,3 @@ void ED_spacetype_ipo(void) BKE_spacetype_register(st); } - diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 7236a99ad80..9475c159653 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -710,7 +710,7 @@ static void uiblock_layer_pass_buttons( if (render_slot) { char str[64]; RenderSlot *slot = BKE_image_get_renderslot(image, *render_slot); - if (slot->name[0] != '\0') { + if (slot && slot->name[0] != '\0') { BLI_strncpy(str, slot->name, sizeof(str)); } else { diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index e84b596530e..827c39b8033 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -301,7 +301,7 @@ static void image_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "IMAGE_OT_reload", RKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "IMAGE_OT_read_viewlayers", RKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "IMAGE_OT_save", SKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_add_item(keymap, "IMAGE_OT_save_as", F3KEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "IMAGE_OT_save_as", SKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "IMAGE_OT_properties", NKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "IMAGE_OT_toolshelf", TKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 481c9031a73..b0b0f6dee07 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -34,6 +34,7 @@ #include "DNA_curve_types.h" #include "DNA_group_types.h" #include "DNA_lattice_types.h" +#include "DNA_mesh_types.h" #include "DNA_meta_types.h" #include "DNA_scene_types.h" @@ -48,7 +49,6 @@ #include "BKE_blender_version.h" #include "BKE_curve.h" #include "BKE_displist.h" -#include "BKE_DerivedMesh.h" #include "BKE_key.h" #include "BKE_layer.h" #include "BKE_paint.h" @@ -92,15 +92,15 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats) switch (ob->type) { case OB_MESH: { - /* we assume derivedmesh is already built, this strictly does stats now. */ - DerivedMesh *dm = ob->derivedFinal; + /* we assume evaluated mesh is already built, this strictly does stats now. */ + Mesh *me_eval = ob->runtime.mesh_eval; int totvert, totedge, totface, totloop; - if (dm) { - totvert = dm->getNumVerts(dm); - totedge = dm->getNumEdges(dm); - totface = dm->getNumPolys(dm); - totloop = dm->getNumLoops(dm); + if (me_eval) { + totvert = me_eval->totvert; + totedge = me_eval->totedge; + totface = me_eval->totpoly; + totloop = me_eval->totloop; stats->totvert += totvert * totob; stats->totedge += totedge * totob; @@ -387,7 +387,7 @@ static void stats_update(ViewLayer *view_layer) else { /* Objects */ for (base = view_layer->object_bases.first; base; base = base->next) - if (base->flag & BASE_VISIBLED) { + if (base->flag & BASE_VISIBLE) { stats_dupli_object(base, base->object, &stats); } } diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index d782fe4d7ef..d3725704636 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -129,7 +129,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe Object *ob = base->object; AnimData *adt = ob->adt; - if (nlaedit_is_tweakmode_on(ac) == 0 && (base->flag & BASE_SELECTABLED)) { + if (nlaedit_is_tweakmode_on(ac) == 0 && (base->flag & BASE_SELECTABLE)) { /* set selection status */ if (selectmode == SELECT_INVERT) { /* swap select */ diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 639195c16ac..745cea37ea3 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -178,14 +178,14 @@ static void nla_free(SpaceLink *sl) /* spacetype; init callback */ -static void nla_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa) +static void nla_init(struct wmWindowManager *wm, ScrArea *sa) { SpaceNla *snla = (SpaceNla *)sa->spacedata.first; /* init dopesheet data if non-existent (i.e. for old files) */ if (snla->ads == NULL) { snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet"); - snla->ads->source = (ID *)G.main->scene.first; // XXX this is bad, but we need this to be set correct + snla->ads->source = (ID *)WM_window_get_active_scene(wm->winactive); } ED_area_tag_refresh(sa); diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 441ab03cb28..14ba9280a75 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -1045,4 +1045,3 @@ void ED_spacetype_node(void) BKE_spacetype_register(st); } - diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index a700f8e20e0..b97cc13d713 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -164,8 +164,10 @@ static int collection_new_exec(bContext *C, wmOperator *op) data.collection, NULL); - outliner_cleanup_tree(soops); + DEG_id_tag_update(&data.collection->id, DEG_TAG_COPY_ON_WRITE); DEG_relations_tag_update(bmain); + + outliner_cleanup_tree(soops); WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); return OPERATOR_FINISHED; } @@ -236,18 +238,19 @@ static int collection_delete_exec(bContext *C, wmOperator *op) /* Effectively delete the collections. */ GSetIterator collections_to_edit_iter; GSET_ITER(collections_to_edit_iter, data.collections_to_edit) { - /* TODO: what if collection was child and got deleted in the meantime? */ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter); - BKE_collection_delete(bmain, collection, hierarchy); + + /* Test in case collection got deleted as part of another one. */ + if (BLI_findindex(&bmain->collection, collection) != -1) { + BKE_collection_delete(bmain, collection, hierarchy); + } } BLI_gset_free(data.collections_to_edit, NULL); + DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE); DEG_relations_tag_update(bmain); - /* TODO(sergey): Use proper flag for tagging here. */ - DEG_id_tag_update(&scene->id, 0); - WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); return OPERATOR_FINISHED; @@ -462,11 +465,9 @@ static int collection_link_exec(bContext *C, wmOperator *UNUSED(op)) BLI_gset_free(data.collections_to_edit, NULL); + DEG_id_tag_update(&active_collection->id, DEG_TAG_COPY_ON_WRITE); DEG_relations_tag_update(bmain); - /* TODO(sergey): Use proper flag for tagging here. */ - DEG_id_tag_update(&scene->id, 0); - WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); return OPERATOR_FINISHED; @@ -527,9 +528,6 @@ static int collection_instance_exec(bContext *C, wmOperator *UNUSED(op)) DEG_relations_tag_update(bmain); - /* TODO(sergey): Use proper flag for tagging here. */ - DEG_id_tag_update(&scene->id, 0); - WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index e4f551b0004..e617bb40837 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -51,6 +51,7 @@ #include "BKE_deform.h" #include "BKE_fcurve.h" #include "BKE_global.h" +#include "BKE_idcode.h" #include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" @@ -278,6 +279,44 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void } } +static void hidebutton_base_flag_cb(bContext *C, void *poin, void *poin2) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = poin; + Base *base = poin2; + bool extend = (CTX_wm_window(C)->eventstate->ctrl == 0); + + /* Undo button toggle, let function do it. */ + base->flag ^= BASE_HIDDEN; + + BKE_base_set_visible(scene, view_layer, base, extend); + + if (!extend && (base->flag & BASE_VISIBLE)) { + /* Auto select solo-ed object. */ + ED_object_base_select(base, BA_SELECT); + view_layer->basact = base; + } + + DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); +} + +static void hidebutton_layer_collection_flag_cb(bContext *C, void *poin, void *poin2) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = poin; + LayerCollection *lc = poin2; + bool extend = (CTX_wm_window(C)->eventstate->ctrl == 0); + + /* Undo button toggle, let function do it. */ + lc->runtime_flag ^= LAYER_COLLECTION_HAS_VISIBLE_OBJECTS; + + BKE_layer_collection_set_visible(scene, view_layer, lc, extend); + + DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); +} + static void namebutton_cb(bContext *C, void *tsep, char *oldname) { Main *bmain = CTX_data_main(C); @@ -435,18 +474,25 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) } static void outliner_draw_restrictbuts( - uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, ListBase *lb) + uiBlock *block, Scene *scene, ViewLayer *view_layer, ARegion *ar, SpaceOops *soops, ListBase *lb) { uiBut *bt; /* get RNA properties (once for speed) */ - PropertyRNA *collection_prop_hide_viewport; - PropertyRNA *collection_prop_hide_select; - PropertyRNA *collection_prop_hide_render; + PropertyRNA *object_prop_hide_viewport, *object_prop_hide_select, *object_prop_hide_render; + PropertyRNA *collection_prop_hide_viewport, *collection_prop_hide_select, *collection_prop_hide_render; + + object_prop_hide_viewport = RNA_struct_type_find_property(&RNA_Object, "hide_viewport"); + object_prop_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select"); + object_prop_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render"); collection_prop_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select"); collection_prop_hide_viewport = RNA_struct_type_find_property(&RNA_Collection, "hide_viewport"); collection_prop_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render"); - BLI_assert(collection_prop_hide_viewport && + + BLI_assert(object_prop_hide_viewport && + object_prop_hide_select && + object_prop_hide_render && + collection_prop_hide_viewport && collection_prop_hide_select && collection_prop_hide_render); @@ -455,15 +501,51 @@ static void outliner_draw_restrictbuts( if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { if (tselem->type == TSE_R_LAYER && (soops->outlinevis == SO_SCENES)) { /* View layer render toggle. */ - ViewLayer *view_layer = te->directdata; + ViewLayer *layer = te->directdata; bt = uiDefIconButBitS( block, UI_BTYPE_ICON_TOGGLE_N, VIEW_LAYER_RENDER, 0, ICON_RESTRICT_RENDER_OFF, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &view_layer->flag, 0, 0, 0, 0, TIP_("Use view layer for rendering")); + UI_UNIT_Y, &layer->flag, 0, 0, 0, 0, TIP_("Use view layer for rendering")); UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); } + else if (tselem->type == 0 && te->idcode == ID_OB) { + Object *ob = (Object *)tselem->id; + Base *base = BKE_view_layer_base_find(view_layer, ob); + + if (base) { + bt = uiDefIconButBitS( + block, UI_BTYPE_ICON_TOGGLE, BASE_HIDDEN, 0, ICON_HIDE_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &base->flag, 0, 0, 0, 0, + TIP_("Hide object in viewport (Ctrl to isolate)")); + UI_but_func_set(bt, hidebutton_base_flag_cb, view_layer, base); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } + + PointerRNA ptr; + RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr); + + bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, + &ptr, object_prop_hide_viewport, -1, 0, 0, -1, -1, + TIP_("Restrict viewport visibility")); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + + bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y, + &ptr, object_prop_hide_select, -1, 0, 0, -1, -1, + TIP_("Restrict viewport selection")); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + + bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y, + &ptr, object_prop_hide_render, -1, 0, 0, -1, -1, + TIP_("Restrict render visibility")); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + + } else if (tselem->type == TSE_MODIFIER) { ModifierData *md = (ModifierData *)te->directdata; Object *ob = (Object *)tselem->id; @@ -489,7 +571,7 @@ static void outliner_draw_restrictbuts( Object *ob = (Object *)tselem->id; bt = uiDefIconButBitI( - block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF, + block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_P, 0, ICON_HIDE_OFF, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0, TIP_("Restrict/Allow visibility in the 3D View")); @@ -527,7 +609,7 @@ static void outliner_draw_restrictbuts( bGPDlayer *gpl = (bGPDlayer *)te->directdata; bt = uiDefIconButBitS( - block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_HIDE, 0, ICON_RESTRICT_VIEW_OFF, + block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_HIDE, 0, ICON_HIDE_OFF, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0, TIP_("Restrict/Allow visibility in the 3D View")); @@ -551,6 +633,16 @@ static void outliner_draw_restrictbuts( if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) && !(collection->flag & COLLECTION_IS_MASTER)) { + if (lc && (lc->runtime_flag & LAYER_COLLECTION_HAS_ENABLED_OBJECTS)) { + bt = uiDefIconButBitS( + block, UI_BTYPE_ICON_TOGGLE_N, LAYER_COLLECTION_HAS_VISIBLE_OBJECTS, 0, ICON_HIDE_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &lc->runtime_flag, 0, 0, 0, 0, + TIP_("Hide collection in viewport (Ctrl to isolate)")); + UI_but_func_set(bt, hidebutton_layer_collection_flag_cb, view_layer, lc); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } + PointerRNA collection_ptr; RNA_id_pointer_create(&collection->id, &collection_ptr); @@ -576,7 +668,7 @@ static void outliner_draw_restrictbuts( } if (TSELEM_OPEN(tselem, soops)) { - outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree); + outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &te->subtree); } } } @@ -814,7 +906,7 @@ static void UNUSED_FUNCTION(tselem_draw_gp_icon_uibut)(struct DrawIconArg *arg, static void tselem_draw_icon( uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te, - float alpha) + float alpha, const bool is_clickable) { struct DrawIconArg arg; float aspect; @@ -835,6 +927,7 @@ static void tselem_draw_icon( arg.y = y; #define ICON_DRAW(_icon) UI_icon_draw_alpha(x, y, _icon, alpha) +#define ICON_CLICK_DRAW(_icon) if (!is_clickable) ICON_DRAW(_icon); else tselem_draw_icon_uibut(&arg, _icon) if (tselem->type) { switch (tselem->type) { @@ -1106,33 +1199,33 @@ static void tselem_draw_icon( Object *ob = (Object *)tselem->id; switch (ob->type) { case OB_LAMP: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_LAMP); break; case OB_MESH: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_MESH); break; case OB_CAMERA: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_CAMERA); break; case OB_CURVE: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_CURVE); break; case OB_MBALL: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_META); break; case OB_LATTICE: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_LATTICE); break; case OB_ARMATURE: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_ARMATURE); break; case OB_FONT: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_FONT); break; case OB_SURF: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_SURFACE); break; case OB_SPEAKER: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SPEAKER); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_SPEAKER); break; case OB_LIGHTPROBE: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LIGHTPROBE); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_LIGHTPROBE); break; case OB_EMPTY: if (ob->dup_group) { - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_GROUP_INSTANCE); + ICON_CLICK_DRAW(ICON_OUTLINER_OB_GROUP_INSTANCE); } else { - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); + ICON_CLICK_DRAW(ICON_OUTLINER_OB_EMPTY); } break; } @@ -1240,13 +1333,137 @@ static void tselem_draw_icon( #undef ICON_DRAW } +/** + * For icon-only children of a collapsed tree, + * Draw small number over the icon to show how many items of this type are displayed. + */ +static void outliner_draw_iconrow_number( + const uiFontStyle *fstyle, + int offsx, int ys, + const eOLDrawState active, + const int num_elements) +{ + float color[4] = {0.4f, 0.4f, 0.4f, 0.9f}; + copy_v3_fl(color, 0.2f); + if (active != OL_DRAWSEL_NONE) { + copy_v3_fl(color, 0.65f); + color[3] = 1.0f; + } + + float ufac = 0.25f * UI_UNIT_X; + float offset_x = (float) offsx + UI_UNIT_X * 0.35f; + + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_aa(true, + offset_x + ufac, + (float)ys - UI_UNIT_Y * 0.2f + ufac, + offset_x + UI_UNIT_X - ufac, + (float)ys - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac, + (float)UI_UNIT_Y / 2.0f - ufac, + color); + + /* Now the numbers. */ + unsigned char text_col[4]; + + UI_GetThemeColor4ubv(TH_TEXT_HI, text_col); + text_col[3] = 255; + + uiFontStyle fstyle_small = *fstyle; + fstyle_small.points *= 0.8f; + + /* We treat +99 as 4 digits to make sure the (eyeballed) alignment looks nice. */ + int num_digits = 4; + char number_text[4] = "+99\0"; + if (num_elements < 100) { + BLI_snprintf(number_text, sizeof(number_text), "%d", num_elements); + num_digits = num_elements < 10 ? 1 : 2; + } + UI_fontstyle_draw_simple(&fstyle_small, + (offset_x + ufac + UI_UNIT_X * (2 - num_digits) * 0.12f), + (float)ys - UI_UNIT_Y * 0.095f + ufac, + number_text, text_col); + UI_fontstyle_set(fstyle); + glEnable(GL_BLEND); /* Roundbox and text drawing disables. */ +} + +static void outliner_draw_iconrow_doit( + uiBlock *block, TreeElement *te, + const uiFontStyle *fstyle, + int xmax, int *offsx, int ys, float alpha_fac, + const eOLDrawState active, + const int num_elements) +{ + TreeStoreElem *tselem = TREESTORE(te); + + if (active != OL_DRAWSEL_NONE) { + float ufac = UI_UNIT_X / 20.0f; + float color[4] = {1.0f, 1.0f, 1.0f, 0.4f}; + + UI_draw_roundbox_corner_set(UI_CNR_ALL); + color[3] *= alpha_fac; + + UI_draw_roundbox_aa(true, + (float) *offsx + 1.0f * ufac, + (float)ys + 1.0f * ufac, + (float)*offsx + UI_UNIT_X - 1.0f * ufac, + (float)ys + UI_UNIT_Y - ufac, + (float)UI_UNIT_Y / 2.0f - ufac, + color); + glEnable(GL_BLEND); /* Roundbox disables. */ + } + + /* No inlined icon should be clickable. */ + tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f * alpha_fac, false); + te->xs = *offsx; + te->ys = ys; + te->xend = (short)*offsx + UI_UNIT_X; + + if (num_elements > 1) { + outliner_draw_iconrow_number(fstyle, *offsx, ys, active, num_elements); + } + (*offsx) += UI_UNIT_X; +} + +/** + * Return the index to use based on the TreeElement ID and object type + * + * We use a continuum of indeces until we get to the object datablocks + * and we then make room for the object types. + */ +static int tree_element_id_type_to_index(TreeElement *te) +{ + TreeStoreElem *tselem = TREESTORE(te); + + const int id_index = tselem->type == 0 ? BKE_idcode_to_index(te->idcode) : INDEX_ID_GR; + if (id_index < INDEX_ID_OB) { + return id_index; + } + else if (id_index == INDEX_ID_OB) { + const Object *ob = (Object *)tselem->id; + return INDEX_ID_OB + ob->type; + } + else { + return id_index + OB_TYPE_MAX; + } +} + static void outliner_draw_iconrow( - bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, SpaceOops *soops, + bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ViewLayer *view_layer, SpaceOops *soops, ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac) { eOLDrawState active; const Object *obact = OBACT(view_layer); + struct { + eOLDrawState active[INDEX_ID_MAX + OB_TYPE_MAX]; + int num_elements[INDEX_ID_MAX + OB_TYPE_MAX]; + TreeElement *tree_element[INDEX_ID_MAX + OB_TYPE_MAX]; + } data = { + .active = {0}, + .num_elements = {0}, + .tree_element = {NULL}, + }; + for (TreeElement *te = lb->first; te; te = te->next) { /* exit drawing early */ if ((*offsx) - UI_UNIT_X > xmax) @@ -1272,41 +1489,48 @@ static void outliner_draw_iconrow( active = tree_element_type_active(C, scene, view_layer, soops, te, tselem, OL_SETSEL_NONE, false); } - if (active != OL_DRAWSEL_NONE) { - float ufac = UI_UNIT_X / 20.0f; - float color[4] = {1.0f, 1.0f, 1.0f, 0.4f}; - - UI_draw_roundbox_corner_set(UI_CNR_ALL); - color[3] *= alpha_fac; - - UI_draw_roundbox_aa( - true, - (float) *offsx + 1.0f * ufac, - (float)ys + 1.0f * ufac, - (float)*offsx + UI_UNIT_X - 1.0f * ufac, - (float)ys + UI_UNIT_Y - ufac, - (float)UI_UNIT_Y / 2.0f - ufac, - color); - glEnable(GL_BLEND); /* roundbox disables */ + if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) { + outliner_draw_iconrow_doit(block, te, fstyle, xmax, offsx, ys, alpha_fac, active, 1); + } + else { + const int index = tree_element_id_type_to_index(te); + data.num_elements[index]++; + if ((data.tree_element[index] == NULL) || + (active > data.active[index])) + { + data.tree_element[index] = te; + } + data.active[index] = MAX2(active, data.active[index]); } - - tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f * alpha_fac); - te->xs = *offsx; - te->ys = ys; - te->xend = (short)*offsx + UI_UNIT_X; - te->flag |= TE_ICONROW; // for click - - (*offsx) += UI_UNIT_X; } /* this tree element always has same amount of branches, so don't draw */ if (tselem->type != TSE_R_LAYER) { outliner_draw_iconrow( - C, block, scene, view_layer, soops, + C, block, fstyle, scene, view_layer, soops, &te->subtree, level + 1, xmax, offsx, ys, alpha_fac); } } + for (int i = 0; i < INDEX_ID_MAX; i++) { + const int num_subtypes = (i == INDEX_ID_OB) ? OB_TYPE_MAX : 1; + /* See tree_element_id_type_to_index for the index logic. */ + int index_base = i; + if (i > INDEX_ID_OB) { + index_base += OB_TYPE_MAX; + } + for (int j = 0; j < num_subtypes; j++) { + const int index = index_base + j; + if (data.num_elements[index] != 0) { + outliner_draw_iconrow_doit(block, + data.tree_element[index], + fstyle, + xmax, offsx, ys, alpha_fac, + data.active[index], + data.num_elements[index]); + } + } + } } /* closed tree element */ @@ -1447,7 +1671,7 @@ static void outliner_draw_tree_element( /* datatype icon */ if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE))) { - tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac); + tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac, true); offsx += UI_UNIT_X + 2 * ufac; } else @@ -1531,7 +1755,7 @@ static void outliner_draw_tree_element( } outliner_draw_iconrow( - C, block, scene, view_layer, soops, &te->subtree, 0, xmax, &tempx, + C, block, fstyle, scene, view_layer, soops, &te->subtree, 0, xmax, &tempx, *starty, alpha_fac); glDisable(GL_BLEND); @@ -1736,7 +1960,6 @@ static void outliner_draw_highlights_recursive( const bool is_searching = ( SEARCHING_OUTLINER(soops) || (soops->outlinevis == SO_DATA_API && - (soops->filter & SO_FILTER_SEARCH) && soops->search_string[0] != 0)); for (TreeElement *te = lb->first; te; te = te->next) { @@ -1893,7 +2116,10 @@ static void outliner_draw_restrictcols(ARegion *ar) unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); immUniformThemeColorShadeAlpha(TH_BACK, -15, -200); - immBegin(GWN_PRIM_LINES, 6); + immBegin(GWN_PRIM_LINES, 8); + + immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), (int)ar->v2d.cur.ymax); + immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), (int)ar->v2d.cur.ymin); immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymax); immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymin); @@ -1999,16 +2225,16 @@ void draw_outliner(const bContext *C) /* draw restriction columns */ outliner_draw_restrictcols(ar); - outliner_draw_restrictbuts(block, scene, ar, soops, &soops->tree); + outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &soops->tree); } + UI_block_emboss_set(block, UI_EMBOSS); + /* draw edit buttons if nessecery */ if (te_edit) { outliner_buttons(C, block, ar, te_edit); } - UI_block_emboss_set(block, UI_EMBOSS); - UI_block_end(C, block); UI_block_draw(C, block); } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index c6288dc05ef..990d50ae42a 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -253,6 +253,55 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot) RNA_def_boolean(ot->srna, "all", 1, "All", "Close or open all items"); } +/* -------------------------------------------------------------------- */ +/** \name Object Mode Enter/Exit + * \{ */ + +static void item_object_mode_enter_exit( + bContext *C, ReportList *reports, Object *ob, + bool enter) +{ + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obact = OBACT(view_layer); + + if ((ob->type != obact->type) || ID_IS_LINKED(ob->data)) { + return; + } + if (((ob->mode & obact->mode) != 0) == enter) { + return; + } + + if (ob == obact) { + BKE_report(reports, RPT_WARNING, "Active object mode not changed"); + return; + } + + Base *base = BKE_view_layer_base_find(view_layer, ob); + if (base == NULL) { + return; + } + Scene *scene = CTX_data_scene(C); + outliner_object_mode_toggle(C, scene, view_layer, base); +} + +void item_object_mode_enter_cb( + bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) +{ + Object *ob = (Object *)tselem->id; + item_object_mode_enter_exit(C, reports, ob, true); +} + +void item_object_mode_exit_cb( + bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) +{ + Object *ob = (Object *)tselem->id; + item_object_mode_enter_exit(C, reports, ob, false); +} + +/** \} */ + /* Rename --------------------------------------------------- */ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, @@ -493,7 +542,7 @@ static int outliner_id_remap_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); /* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */ - GPU_materials_free(); + GPU_materials_free(bmain); WM_event_add_notifier(C, NC_WINDOW, NULL); @@ -2317,6 +2366,7 @@ static int collection_drop_invoke(bContext *C, wmOperator *op, const wmEvent *ev Object *ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname); BKE_collection_object_add(bmain, collection, ob); + DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE); DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 8ac09648d60..0ab22208841 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -151,11 +151,12 @@ typedef enum { /* size constants */ #define OL_Y_OFFSET 2 +#define OL_TOG_HIDEX (UI_UNIT_X * 4.0f) #define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 3.0f) #define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f) #define OL_TOG_RESTRICT_RENDERX UI_UNIT_X -#define OL_TOGW OL_TOG_RESTRICT_SELECTX +#define OL_TOGW OL_TOG_HIDEX #define OL_RNA_COLX (UI_UNIT_X * 15) #define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f) @@ -181,7 +182,7 @@ typedef enum { * - not searching into RNA items helps but isn't the complete solution */ -#define SEARCHING_OUTLINER(sov) ((sov->search_flags & SO_SEARCH_RECURSIVE) && (sov->filter & SO_FILTER_SEARCH)) +#define SEARCHING_OUTLINER(sov) (sov->search_flags & SO_SEARCH_RECURSIVE) /* is the currrent element open? if so we also show children */ #define TSELEM_OPEN(telm, sv) ( (telm->flag & TSE_CLOSED) == 0 || (SEARCHING_OUTLINER(sv) && (telm->flag & TSE_CHILDSEARCH)) ) @@ -226,6 +227,10 @@ void outliner_item_select( struct SpaceOops *soops, const struct TreeElement *te, const bool extend, const bool toggle); +void outliner_object_mode_toggle( + struct bContext *C, Scene *scene, ViewLayer *view_layer, + Base *base); + /* outliner_edit.c ---------------------------------------------- */ typedef void (*outliner_operation_cb)( struct bContext *C, struct ReportList *, struct Scene *scene, @@ -271,6 +276,13 @@ void id_remap_cb( struct bContext *C, struct ReportList *reports, struct Scene *scene, struct TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data); +void item_object_mode_enter_cb( + struct bContext *C, struct ReportList *reports, struct Scene *scene, + TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data); +void item_object_mode_exit_cb( + struct bContext *C, struct ReportList *reports, struct Scene *scene, + TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data); + TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const bool children); void outliner_set_coordinates(struct ARegion *ar, struct SpaceOops *soops); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index ecfd12618e5..316caf0e239 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -560,6 +560,13 @@ void outliner_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "OBJECT_OT_move_to_collection", MKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "OBJECT_OT_link_to_collection", MKEY, KM_PRESS, KM_SHIFT, 0); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0); + RNA_boolean_set(kmi->ptr, "select", false); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "unselected", false); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "unselected", true); + outliner_item_drag_drop_modal_keymap(keyconf); } diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 6a6a392e4a6..9b430b0af99 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -155,6 +155,20 @@ static void do_outliner_activate_pose(bContext *C, ViewLayer *view_layer, Base * } } +/* For draw callback to run mode switching */ +void outliner_object_mode_toggle( + bContext *C, Scene *scene, ViewLayer *view_layer, + Base *base) +{ + Object *obact = OBACT(view_layer); + if (obact->mode & OB_MODE_EDIT) { + do_outliner_activate_obdata(C, scene, view_layer, base); + } + else if (obact->mode & OB_MODE_POSE) { + do_outliner_activate_pose(C, view_layer, base); + } +} + /* ****************************************************** */ /* Outliner Element Selection/Activation on Click */ @@ -192,7 +206,7 @@ static void do_outliner_object_select_recursive(ViewLayer *view_layer, Object *o for (base = FIRSTBASE(view_layer); base; base = base->next) { Object *ob = base->object; - if ((((base->flag & BASE_VISIBLED) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) { + if ((((base->flag & BASE_VISIBLE) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) { ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); } } @@ -986,7 +1000,7 @@ static void do_outliner_item_activate_tree_element( Object *ob = (Object *)outliner_search_back(soops, te, ID_OB); if ((ob != NULL) && (ob->data == tselem->id)) { Base *base = BKE_view_layer_base_find(view_layer, ob); - if ((base != NULL) && (base->flag & BASE_VISIBLED)) { + if ((base != NULL) && (base->flag & BASE_VISIBLE)) { do_outliner_activate_obdata(C, scene, view_layer, base); } } diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index f8d9877be6e..e2eb617278b 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -229,18 +229,22 @@ static void unlink_collection_cb( if (GS(tsep->id->name) == ID_OB) { Object *ob = (Object *)tsep->id; ob->dup_group = NULL; + DEG_id_tag_update(&ob->id, OB_RECALC_OB); DEG_relations_tag_update(bmain); } else if (GS(tsep->id->name) == ID_GR) { Collection *parent = (Collection *)tsep->id; id_fake_user_set(&collection->id); BKE_collection_child_remove(bmain, parent, collection); + DEG_id_tag_update(&parent->id, DEG_TAG_COPY_ON_WRITE); DEG_relations_tag_update(bmain); } else if (GS(tsep->id->name) == ID_SCE) { - Collection *parent = BKE_collection_master((Scene *)tsep->id); + Scene *scene = (Scene *)tsep->id; + Collection *parent = BKE_collection_master(scene); id_fake_user_set(&collection->id); BKE_collection_child_remove(bmain, parent, collection); + DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE); DEG_relations_tag_update(bmain); } } @@ -257,11 +261,14 @@ static void unlink_object_cb( if (GS(tsep->id->name) == ID_GR) { Collection *parent = (Collection *)tsep->id; BKE_collection_object_remove(bmain, parent, ob, true); + DEG_id_tag_update(&parent->id, DEG_TAG_COPY_ON_WRITE); DEG_relations_tag_update(bmain); } else if (GS(tsep->id->name) == ID_SCE) { - Collection *parent = BKE_collection_master((Scene *)tsep->id); + Scene *scene = (Scene *)tsep->id; + Collection *parent = BKE_collection_master(scene); BKE_collection_object_remove(bmain, parent, ob, true); + DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE); DEG_relations_tag_update(bmain); } } @@ -394,7 +401,7 @@ static void object_select_cb( Object *ob = (Object *)tselem->id; Base *base = BKE_view_layer_base_find(view_layer, ob); - if (base && ((base->flag & BASE_VISIBLED) != 0)) { + if (base && ((base->flag & BASE_VISIBLE) != 0)) { base->flag |= BASE_SELECTED; } } @@ -911,6 +918,8 @@ enum { OL_OP_TOGSEL, OL_OP_TOGREN, OL_OP_RENAME, + OL_OP_OBJECT_MODE_ENTER, + OL_OP_OBJECT_MODE_EXIT, }; static const EnumPropertyItem prop_object_op_types[] = { @@ -922,6 +931,8 @@ static const EnumPropertyItem prop_object_op_types[] = { {OL_OP_REMAP, "REMAP", 0, "Remap Users", "Make all users of selected data-blocks to use instead a new chosen one"}, {OL_OP_RENAME, "RENAME", 0, "Rename", ""}, + {OL_OP_OBJECT_MODE_ENTER, "OBJECT_MODE_ENTER", 0, "Enter Mode", ""}, + {OL_OP_OBJECT_MODE_EXIT, "OBJECT_MODE_EXIT", 0, "Exit Mode", ""}, {0, NULL, 0, NULL, NULL} }; @@ -1005,6 +1016,14 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb); str = "Rename Object"; } + else if (event == OL_OP_OBJECT_MODE_ENTER) { + outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_object_mode_enter_cb); + str = "Enter Current Mode"; + } + else if (event == OL_OP_OBJECT_MODE_EXIT) { + outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_object_mode_exit_cb); + str = "Exit Current Mode"; + } else { BLI_assert(0); return OPERATOR_CANCELLED; @@ -1574,8 +1593,8 @@ void OUTLINER_OT_animdata_operation(wmOperatorType *ot) /* **************************************** */ static const EnumPropertyItem prop_constraint_op_types[] = { - {OL_CONSTRAINTOP_ENABLE, "ENABLE", ICON_RESTRICT_VIEW_OFF, "Enable", ""}, - {OL_CONSTRAINTOP_DISABLE, "DISABLE", ICON_RESTRICT_VIEW_ON, "Disable", ""}, + {OL_CONSTRAINTOP_ENABLE, "ENABLE", ICON_HIDE_OFF, "Enable", ""}, + {OL_CONSTRAINTOP_DISABLE, "DISABLE", ICON_HIDE_ON, "Disable", ""}, {OL_CONSTRAINTOP_DELETE, "DELETE", ICON_X, "Delete", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index d155457a208..9f6c944c914 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1469,6 +1469,10 @@ static void outliner_add_layer_collection_objects( Base *base = BKE_view_layer_base_find(layer, cob->ob); TreeElement *te_object = outliner_add_element(soops, tree, base->object, ten, 0, 0); te_object->directdata = base; + + if (!(base->flag & BASE_VISIBLE)) { + te_object->flag |= TE_DISABLED; + } } } @@ -1487,7 +1491,10 @@ static void outliner_add_layer_collections_recursive( ten->reinsert_poll = outliner_collections_reorder_poll; const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0; - if (exclude) { + if (exclude || + ((layer->runtime_flag & VIEW_LAYER_HAS_HIDE) && + !(lc->runtime_flag & LAYER_COLLECTION_HAS_VISIBLE_OBJECTS))) + { ten->flag |= TE_DISABLED; } @@ -1885,10 +1892,11 @@ static int outliner_exclude_filter_get(SpaceOops *soops) { int exclude_filter = soops->filter & ~SO_FILTER_OB_STATE; - if (soops->filter & SO_FILTER_SEARCH) { - if (soops->search_string[0] == 0) { - exclude_filter &= ~SO_FILTER_SEARCH; - } + if (soops->search_string[0] != 0) { + exclude_filter |= SO_FILTER_SEARCH; + } + else { + exclude_filter &= ~SO_FILTER_SEARCH; } /* Let's have this for the collection options at first. */ @@ -1976,7 +1984,7 @@ static bool outliner_element_visible_get(ViewLayer *view_layer, TreeElement *te, } if (exclude_filter & SO_FILTER_OB_STATE_VISIBLE) { - if ((base->flag & BASE_VISIBLED) == 0) { + if ((base->flag & BASE_VISIBLE) == 0) { return false; } } @@ -2262,5 +2270,3 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa BKE_main_id_clear_newpoins(mainvar); } - - diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 2d51a4b4554..6b95df7c917 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -335,6 +335,9 @@ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene) v3d->overlay.flag = V3D_OVERLAY_LOOK_DEV; v3d->overlay.wireframe_threshold = 0.5f; v3d->overlay.bone_selection_alpha = 0.5f; + v3d->overlay.texture_paint_mode_opacity = 0.8; + v3d->overlay.weight_paint_mode_opacity = 0.8; + v3d->overlay.vertex_paint_mode_opacity = 0.8; v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR; @@ -1410,7 +1413,7 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes if (view_layer->basact) { Object *ob = view_layer->basact->object; /* if hidden but in edit mode, we still display, can happen with animation */ - if ((view_layer->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) { + if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT)) { CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact); } } @@ -1422,7 +1425,7 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes if (view_layer->basact) { Object *ob = view_layer->basact->object; /* if hidden but in edit mode, we still display, can happen with animation */ - if ((view_layer->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) { + if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT) != 0) { CTX_data_id_pointer_set(result, &ob->id); } } @@ -1541,11 +1544,6 @@ void ED_spacetype_view3d(void) art->draw = view3d_tools_region_draw; BLI_addhead(&st->regiontypes, art); -#if 0 - /* unfinished still */ - view3d_toolshelf_register(art); -#endif - /* regions: header */ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region"); art->regionid = RGN_TYPE_HEADER; diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 300b6fafd7a..6ebed88728e 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -69,6 +69,7 @@ #include "RNA_access.h" #include "ED_armature.h" +#include "ED_object.h" #include "ED_mesh.h" #include "ED_screen.h" @@ -1163,6 +1164,11 @@ static void view3d_panel_transform(const bContext *C, Panel *pa) } } +static void hide_collections_menu_draw(const bContext *C, Menu *menu) +{ + ED_hide_collections_menu_draw(C, menu->layout); +} + void view3d_buttons_register(ARegionType *art) { PanelType *pt; @@ -1182,6 +1188,15 @@ void view3d_buttons_register(ARegionType *art) pt->draw = view3d_panel_vgroup; pt->poll = view3d_panel_vgroup_poll; BLI_addtail(&art->paneltypes, pt); + + MenuType *mt; + + mt = MEM_callocN(sizeof(MenuType), "spacetype view3d menu collections"); + strcpy(mt->idname, "VIEW3D_MT_collection"); + strcpy(mt->label, N_("Collection")); + strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + mt->draw = hide_collections_menu_draw; + WM_menutype_add(mt); } static int view3d_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index fd2f604651b..74554e8d62b 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -44,6 +44,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_key.h" +#include "BKE_main.h" #include "BKE_scene.h" #include "BKE_object.h" #include "BKE_paint.h" @@ -1182,7 +1183,7 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) /** * Information drawn on top of the solid plates and composed data */ -void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset) +void view3d_draw_region_info(const bContext *C, ARegion *ar, const int UNUSED(offset)) { RegionView3D *rv3d = ar->regiondata; View3D *v3d = CTX_wm_view3d(C); @@ -1196,8 +1197,6 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset) rcti rect; ED_region_visible_rect(ar, &rect); - /* Leave room for previously drawn info. */ - rect.ymax -= offset; view3d_draw_border(C, ar); view3d_draw_grease_pencil(C); @@ -1271,11 +1270,12 @@ RenderEngineType *ED_view3d_engine_type(Scene *scene, int drawtype) void view3d_main_region_draw(const bContext *C, ARegion *ar) { + Main *bmain = CTX_data_main(C); View3D *v3d = CTX_wm_view3d(C); view3d_draw_view(C, ar); - GPU_free_images_old(); + GPU_free_images_old(bmain); GPU_pass_cache_garbage_collect(); /* XXX This is in order to draw UI batches with the DRW @@ -1348,7 +1348,7 @@ void ED_view3d_draw_offscreen( if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* free images which can have changed on frame-change * warning! can be slow so only free animated images - campbell */ - GPU_free_images_anim(); + GPU_free_images_anim(G.main); /* XXX :((( */ } gpuPushProjectionMatrix(); diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index 3a89c910ea8..b19001ab834 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -263,7 +263,7 @@ static void backdrawview3d( G.f |= G_BACKBUFSEL; - if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLED) != 0)) { + if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { draw_object_backbufsel(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode); } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index bae186097a8..88c7eabc62f 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -4553,7 +4553,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() */ -void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2]) +void ED_view3d_cursor3d_position(bContext *C, const int mval[2], bool use_depth, float cursor_co[3]) { ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); @@ -4566,32 +4566,35 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2]) if (rv3d == NULL) return; - ED_view3d_calc_zfac(rv3d, fp, &flip); + ED_view3d_calc_zfac(rv3d, cursor_co, &flip); /* reset the depth based on the view offset (we _know_ the offset is infront of us) */ if (flip) { - negate_v3_v3(fp, rv3d->ofs); + negate_v3_v3(cursor_co, rv3d->ofs); /* re initialize, no need to check flip again */ - ED_view3d_calc_zfac(rv3d, fp, NULL /* &flip */ ); + ED_view3d_calc_zfac(rv3d, cursor_co, NULL /* &flip */ ); } - if (U.uiflag & USER_DEPTH_CURSOR) { /* maybe this should be accessed some other way */ + if (use_depth) { /* maybe this should be accessed some other way */ struct Depsgraph *depsgraph = CTX_data_depsgraph(C); view3d_operator_needs_opengl(C); - if (ED_view3d_autodist(depsgraph, ar, v3d, mval, fp, true, NULL)) { + if (ED_view3d_autodist(depsgraph, ar, v3d, mval, cursor_co, true, NULL)) { depth_used = true; } } if (depth_used == false) { float depth_pt[3]; - copy_v3_v3(depth_pt, fp); - ED_view3d_win_to_3d_int(v3d, ar, depth_pt, mval, fp); + copy_v3_v3(depth_pt, cursor_co); + ED_view3d_win_to_3d_int(v3d, ar, depth_pt, mval, cursor_co); } } -void ED_view3d_cursor3d_update(bContext *C, const int mval[2]) +void ED_view3d_cursor3d_position_rotation( + bContext *C, const int mval[2], + const bool use_depth, enum eV3DCursorOrient orientation, + float cursor_co[3], float cursor_quat[4]) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -4599,16 +4602,26 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2]) ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = ar->regiondata; - View3DCursor *cursor_curr = ED_view3d_cursor3d_get(scene, v3d); - View3DCursor cursor_prev = *cursor_curr; + /* XXX, caller should check. */ + if (rv3d == NULL) + return; - ED_view3d_cursor3d_position(C, cursor_curr->location, mval); - copy_qt_qt(cursor_curr->rotation, rv3d->viewquat); - cursor_curr->rotation[0] *= -1.0f; + ED_view3d_cursor3d_position(C, mval, use_depth, cursor_co); + + if (orientation == V3D_CURSOR_ORIENT_NONE) { + /* pass */ + } + else if (orientation == V3D_CURSOR_ORIENT_VIEW) { + copy_qt_qt(cursor_quat, rv3d->viewquat); + cursor_quat[0] *= -1.0f; + } + else if (orientation == V3D_CURSOR_ORIENT_GEOM) { + copy_qt_qt(cursor_quat, rv3d->viewquat); + cursor_quat[0] *= -1.0f; - { const float mval_fl[2] = {UNPACK2(mval)}; float ray_no[3]; + float ray_co[3]; struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( bmain, scene, CTX_data_depsgraph(C), 0, ar, v3d); @@ -4624,16 +4637,21 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2]) .use_object_edit_cage = false, }, mval_fl, &dist_px, - cursor_curr->location, ray_no, NULL, + ray_co, ray_no, NULL, &ob_dummy, obmat)) { + if (use_depth) { + copy_v3_v3(cursor_co, ray_co); + } + float tquat[4]; + /* Math normal (Z). */ { float z_src[3] = {0, 0, 1}; - mul_qt_v3(cursor_curr->rotation, z_src); + mul_qt_v3(cursor_quat, z_src); rotation_between_vecs_to_quat(tquat, z_src, ray_no); - mul_qt_qtqt(cursor_curr->rotation, tquat, cursor_curr->rotation); + mul_qt_qtqt(cursor_quat, tquat, cursor_quat); } /* Match object matrix (X). */ @@ -4646,27 +4664,47 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2]) const int ortho_axis = axis_dominant_v3_ortho_single(ortho_axis_dot); float x_src[3] = {1, 0, 0}; float x_dst[3]; - mul_qt_v3(cursor_curr->rotation, x_src); + mul_qt_v3(cursor_quat, x_src); project_plane_v3_v3v3(x_dst, obmat[ortho_axis], ray_no); normalize_v3(x_dst); rotation_between_vecs_to_quat(tquat, x_src, x_dst); - mul_qt_qtqt(cursor_curr->rotation, tquat, cursor_curr->rotation); + mul_qt_qtqt(cursor_quat, tquat, cursor_quat); } } ED_transform_snap_object_context_destroy(snap_context); } +} + +void ED_view3d_cursor3d_update( + bContext *C, const int mval[2], + const bool use_depth, enum eV3DCursorOrient orientation) +{ + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + + View3DCursor *cursor_curr = ED_view3d_cursor3d_get(scene, v3d); + View3DCursor cursor_prev = *cursor_curr; + + ED_view3d_cursor3d_position_rotation( + C, mval, + use_depth, orientation, + cursor_curr->location, cursor_curr->rotation); /* offset the cursor lock to avoid jumping to new offset */ if (v3d->ob_centre_cursor) { if (U.uiflag & USER_LOCK_CURSOR_ADJUST) { - float co_curr[2], co_prev[2]; + float co_2d_curr[2], co_2d_prev[2]; - if ((ED_view3d_project_float_global(ar, cursor_prev.location, co_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && - (ED_view3d_project_float_global(ar, cursor_curr->location, co_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) + if ((ED_view3d_project_float_global( + ar, cursor_prev.location, co_2d_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && + (ED_view3d_project_float_global( + ar, cursor_curr->location, co_2d_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) { - rv3d->ofs_lock[0] += (co_curr[0] - co_prev[0]) / (ar->winx * 0.5f); - rv3d->ofs_lock[1] += (co_curr[1] - co_prev[1]) / (ar->winy * 0.5f); + rv3d->ofs_lock[0] += (co_2d_curr[0] - co_2d_prev[0]) / (ar->winx * 0.5f); + rv3d->ofs_lock[1] += (co_2d_curr[1] - co_2d_prev[1]) / (ar->winy * 0.5f); } } else { @@ -4689,9 +4727,20 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2]) DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE); } -static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +static int view3d_cursor3d_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ED_view3d_cursor3d_update(C, event->mval); + bool use_depth = (U.uiflag & USER_DEPTH_CURSOR); + { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_depth"); + if (RNA_property_is_set(op->ptr, prop)) { + use_depth = RNA_property_boolean_get(op->ptr, prop); + } + else { + RNA_property_boolean_set(op->ptr, prop, use_depth); + } + } + const enum eV3DCursorOrient orientation = RNA_enum_get(op->ptr, "orientation"); + ED_view3d_cursor3d_update(C, event->mval, use_depth, orientation); return OPERATOR_FINISHED; } @@ -4711,6 +4760,24 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot) /* flags */ // ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + + PropertyRNA *prop; + static const EnumPropertyItem orientation_items[] = { + {V3D_CURSOR_ORIENT_NONE, "NONE", 0, "None", "Leave orientation unchanged"}, + {V3D_CURSOR_ORIENT_VIEW, "VIEW", 0, "View", "Orient to the viewport"}, + {V3D_CURSOR_ORIENT_GEOM, "GEOM", 0, "Geometry", "Match the surface normal"}, + {0, NULL, 0, NULL, NULL} + }; + + prop = RNA_def_boolean( + ot->srna, "use_depth", true, "Surface Project", + "Project onto the surface"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_enum( + ot->srna, "orientation", orientation_items, V3D_CURSOR_ORIENT_VIEW, + "Orientation", "Preset viewpoint to use"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 017b31a0bf2..4eb2a016b94 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -235,7 +235,6 @@ struct Object *ED_view3d_cameracontrol_object_get( /* view3d_toolbar.c */ void VIEW3D_OT_toolshelf(struct wmOperatorType *ot); -void view3d_toolshelf_register(struct ARegionType *art); /* view3d_snap.c */ bool ED_view3d_minmax_verts(struct Object *obedit, float min[3], float max[3]); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index b3211ed1108..267712b3339 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -302,7 +302,7 @@ void view3d_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", CKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "center", true); - WM_keymap_add_menu_pie(keymap, "VIEW3D_PIE_view", ACCENTGRAVEKEY, KM_CLICK_DRAG, 0, 0); + WM_keymap_add_menu_pie(keymap, "VIEW3D_MT_view_pie", ACCENTGRAVEKEY, KM_CLICK_DRAG, 0, 0); /* numpad view hotkeys*/ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD0, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_CAMERA); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index b4f3be178aa..c0a133032ea 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1326,7 +1326,7 @@ static Base *mouse_select_eval_buffer( while (base) { /* skip objects with select restriction, to prevent prematurely ending this loop * with an un-selectable choice */ - if ((base->flag & BASE_SELECTABLED) == 0) { + if ((base->flag & BASE_SELECTABLE) == 0) { base = base->next; if (base == NULL) base = FIRSTBASE(view_layer); if (base == startbase) break; diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index acceb40beaa..707e0e7a394 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -28,153 +28,24 @@ * \ingroup spview3d */ - #include <string.h> #include <stdio.h> #include <math.h> #include <float.h> -#include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BLI_ghash.h" - -#include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_screen.h" - #include "WM_api.h" #include "WM_types.h" -#include "RNA_access.h" - #include "ED_screen.h" -#include "ED_undo.h" - -#include "UI_interface.h" -#include "UI_resources.h" #include "view3d_intern.h" /* own include */ -/* ******************* */ - -typedef struct CustomTool { - struct CustomTool *next, *prev; - char opname[OP_MAX_TYPENAME]; - char context[OP_MAX_TYPENAME]; -} CustomTool; - -static void operator_call_cb(struct bContext *C, void *arg_listbase, void *arg2) -{ - wmOperatorType *ot = arg2; - - if (ot) { - CustomTool *ct = MEM_callocN(sizeof(CustomTool), "CustomTool"); - - BLI_addtail(arg_listbase, ct); - BLI_strncpy(ct->opname, ot->idname, OP_MAX_TYPENAME); - BLI_strncpy(ct->context, CTX_data_mode_string(C), OP_MAX_TYPENAME); - } - -} - -static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items) -{ - GHashIterator iter; - - for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { - wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); - - if (BLI_strcasestr(ot->name, str)) { - if (WM_operator_poll((bContext *)C, ot)) { - - if (false == UI_search_item_add(items, ot->name, ot, 0)) - break; - } - } - } -} - - -/* ID Search browse menu, open */ -static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase) -{ - static char search[OP_MAX_TYPENAME]; - wmEvent event; - wmWindow *win = CTX_wm_window(C); - uiBlock *block; - uiBut *but; - - /* clear initial search string, then all items show */ - search[0] = 0; - - block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); - UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU); - - /* fake button, it holds space for search items */ - uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL); - - but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, 19, 0, 0, ""); - UI_but_func_search_set(but, NULL, operator_search_cb, arg_listbase, operator_call_cb, NULL); - - UI_block_bounds_set_normal(block, 6); - UI_block_direction_set(block, UI_DIR_DOWN); - UI_block_end(C, block); - - wm_event_init_from_window(win, &event); - event.type = EVT_BUT_OPEN; - event.val = KM_PRESS; - event.customdata = but; - event.customdatafree = false; - wm_event_add(win, &event); - - return block; -} - - -static void view3d_panel_tool_shelf(const bContext *C, Panel *pa) -{ - SpaceLink *sl = CTX_wm_space_data(C); - SpaceType *st = NULL; - uiLayout *col; - const char *context = CTX_data_mode_string(C); - - if (sl) - st = BKE_spacetype_from_id(sl->spacetype); - - if (st && st->toolshelf.first) { - CustomTool *ct; - - for (ct = st->toolshelf.first; ct; ct = ct->next) { - if (STREQLEN(context, ct->context, OP_MAX_TYPENAME)) { - col = uiLayoutColumn(pa->layout, true); - uiItemFullO(col, ct->opname, NULL, ICON_NONE, NULL, WM_OP_INVOKE_REGION_WIN, 0, NULL); - } - } - } - col = uiLayoutColumn(pa->layout, true); - uiDefBlockBut(uiLayoutGetBlock(pa->layout), tool_search_menu, &st->toolshelf, "Add Tool", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Add Tool in shelf, gets saved in files"); -} - - -void view3d_toolshelf_register(ARegionType *art) -{ - PanelType *pt; - - pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel tools"); - strcpy(pt->idname, "VIEW3D_PT_tool_shelf"); - strcpy(pt->label, N_("Tool Shelf")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = view3d_panel_tool_shelf; - BLI_addtail(&art->paneltypes, pt); -} - /* ********** operator to open/close toolshelf region */ static int view3d_toolshelf_toggle_exec(bContext *C, wmOperator *UNUSED(op)) @@ -200,4 +71,3 @@ void VIEW3D_OT_toolshelf(wmOperatorType *ot) /* flags */ ot->flag = 0; } - diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index abb8c688e05..8b9ad387065 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -509,7 +509,6 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) { Depsgraph *depsgraph = CTX_data_depsgraph(C); Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); /* can be NULL */ Object *camera_ob = v3d ? v3d->camera : scene->camera; Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob); @@ -523,7 +522,7 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) } /* this function does all the important stuff */ - if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, view_layer, camera_ob_eval, r_co, &r_scale)) { + if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, camera_ob_eval, r_co, &r_scale)) { ObjectTfmProtectedChannels obtfm; float obmat_new[4][4]; diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 3c70eaae2d3..93e644b9706 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -559,7 +559,7 @@ static void applyObjectConstraintRot( /* on setup call, use first object */ if (td == NULL) { - td = tc->data; + td = TRANS_DATA_CONTAINER_FIRST_OK(t)->data; } if (t->flag & T_EDIT) { diff --git a/source/blender/editors/transform/transform_manipulator_3d.c b/source/blender/editors/transform/transform_manipulator_3d.c index 75da0fc2d23..ccf6cc8c7ce 100644 --- a/source/blender/editors/transform/transform_manipulator_3d.c +++ b/source/blender/editors/transform/transform_manipulator_3d.c @@ -159,18 +159,15 @@ enum { MAN_AXES_SCALE, }; -/* naming from old blender we may combine. */ -enum { - V3D_MANIP_TRANSLATE = 1, - V3D_MANIP_ROTATE = 2, - V3D_MANIP_SCALE = 4, -}; - - typedef struct ManipulatorGroup { bool all_hidden; int twtype; + /* Users may change the twtype, detect changes to re-setup manipulator options. */ + int twtype_init; + int twtype_prev; + int use_twtype_refresh; + struct wmManipulator *manipulators[MAN_AXIS_LAST]; } ManipulatorGroup; @@ -269,9 +266,9 @@ static bool manipulator_is_axis_visible( } } - if ((axis_type == MAN_AXES_TRANSLATE && !(twtype & V3D_MANIP_TRANSLATE)) || - (axis_type == MAN_AXES_ROTATE && !(twtype & V3D_MANIP_ROTATE)) || - (axis_type == MAN_AXES_SCALE && !(twtype & V3D_MANIP_SCALE))) + if ((axis_type == MAN_AXES_TRANSLATE && !(twtype & SCE_MANIP_TRANSLATE)) || + (axis_type == MAN_AXES_ROTATE && !(twtype & SCE_MANIP_ROTATE)) || + (axis_type == MAN_AXES_SCALE && !(twtype & SCE_MANIP_SCALE))) { return false; } @@ -301,34 +298,34 @@ static bool manipulator_is_axis_visible( case MAN_AXIS_SCALE_Z: return (rv3d->twdrawflag & MAN_SCALE_Z); case MAN_AXIS_SCALE_C: - return (rv3d->twdrawflag & MAN_SCALE_C && (twtype & V3D_MANIP_TRANSLATE) == 0); + return (rv3d->twdrawflag & MAN_SCALE_C && (twtype & SCE_MANIP_TRANSLATE) == 0); case MAN_AXIS_TRANS_XY: return (rv3d->twdrawflag & MAN_TRANS_X && rv3d->twdrawflag & MAN_TRANS_Y && - (twtype & V3D_MANIP_ROTATE) == 0); + (twtype & SCE_MANIP_ROTATE) == 0); case MAN_AXIS_TRANS_YZ: return (rv3d->twdrawflag & MAN_TRANS_Y && rv3d->twdrawflag & MAN_TRANS_Z && - (twtype & V3D_MANIP_ROTATE) == 0); + (twtype & SCE_MANIP_ROTATE) == 0); case MAN_AXIS_TRANS_ZX: return (rv3d->twdrawflag & MAN_TRANS_Z && rv3d->twdrawflag & MAN_TRANS_X && - (twtype & V3D_MANIP_ROTATE) == 0); + (twtype & SCE_MANIP_ROTATE) == 0); case MAN_AXIS_SCALE_XY: return (rv3d->twdrawflag & MAN_SCALE_X && rv3d->twdrawflag & MAN_SCALE_Y && - (twtype & V3D_MANIP_TRANSLATE) == 0 && - (twtype & V3D_MANIP_ROTATE) == 0); + (twtype & SCE_MANIP_TRANSLATE) == 0 && + (twtype & SCE_MANIP_ROTATE) == 0); case MAN_AXIS_SCALE_YZ: return (rv3d->twdrawflag & MAN_SCALE_Y && rv3d->twdrawflag & MAN_SCALE_Z && - (twtype & V3D_MANIP_TRANSLATE) == 0 && - (twtype & V3D_MANIP_ROTATE) == 0); + (twtype & SCE_MANIP_TRANSLATE) == 0 && + (twtype & SCE_MANIP_ROTATE) == 0); case MAN_AXIS_SCALE_ZX: return (rv3d->twdrawflag & MAN_SCALE_Z && rv3d->twdrawflag & MAN_SCALE_X && - (twtype & V3D_MANIP_TRANSLATE) == 0 && - (twtype & V3D_MANIP_ROTATE) == 0); + (twtype & SCE_MANIP_TRANSLATE) == 0 && + (twtype & SCE_MANIP_ROTATE) == 0); } return false; } @@ -1122,15 +1119,15 @@ static void manipulator_line_range(const int twtype, const short axis_type, floa switch (axis_type) { case MAN_AXES_TRANSLATE: - if (twtype & V3D_MANIP_SCALE) { + if (twtype & SCE_MANIP_SCALE) { *r_start = *r_len - ofs + 0.075f; } - if (twtype & V3D_MANIP_ROTATE) { + if (twtype & SCE_MANIP_ROTATE) { *r_len += ofs; } break; case MAN_AXES_SCALE: - if (twtype & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE)) { + if (twtype & (SCE_MANIP_TRANSLATE | SCE_MANIP_ROTATE)) { *r_len -= ofs + 0.025f; } break; @@ -1172,8 +1169,10 @@ static void manipulator_xform_message_subscribe( if (type_fn == TRANSFORM_WGT_manipulator) { extern PropertyRNA rna_ToolSettings_transform_pivot_point; + extern PropertyRNA rna_ToolSettings_use_manipulator_mode; const PropertyRNA *props[] = { - &rna_ToolSettings_transform_pivot_point + &rna_ToolSettings_transform_pivot_point, + &rna_ToolSettings_use_manipulator_mode, }; for (int i = 0; i < ARRAY_SIZE(props); i++) { WM_msg_subscribe_rna(mbus, &toolsettings_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__); @@ -1285,41 +1284,12 @@ static int manipulator_modal( return OPERATOR_RUNNING_MODAL; } -static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup *mgroup) +static void manipulatorgroup_init_properties_from_twtype(wmManipulatorGroup *mgroup) { - ManipulatorGroup *man = manipulatorgroup_init(mgroup); struct { wmOperatorType *translate, *rotate, *trackball, *resize; } ot_store = {NULL}; - - mgroup->customdata = man; - - { - /* TODO: support mixing modes again? - it's supported but tool system makes it unobvious. */ - man->twtype = 0; - ScrArea *sa = CTX_wm_area(C); - bToolRef_Runtime *tref_rt = sa->runtime.tool ? sa->runtime.tool->runtime : NULL; - wmKeyMap *km = tref_rt ? WM_keymap_find_all(C, tref_rt->keymap, sa->spacetype, RGN_TYPE_WINDOW) : NULL; - /* Weak, check first event */ - wmKeyMapItem *kmi = km ? km->items.first : NULL; - - if (kmi == NULL) { - man->twtype |= V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE | V3D_MANIP_SCALE; - } - else if (STREQ(kmi->idname, "TRANSFORM_OT_translate")) { - man->twtype |= V3D_MANIP_TRANSLATE; - } - else if (STREQ(kmi->idname, "TRANSFORM_OT_rotate")) { - man->twtype |= V3D_MANIP_ROTATE; - } - else if (STREQ(kmi->idname, "TRANSFORM_OT_resize")) { - man->twtype |= V3D_MANIP_SCALE; - } - BLI_assert(man->twtype != 0); - } - - /* *** set properties for axes *** */ - + ManipulatorGroup *man = mgroup->customdata; MAN_ITER_AXES_BEGIN(axis, axis_idx) { const short axis_type = manipulator_get_axis_type(axis_idx); @@ -1340,7 +1310,7 @@ static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup case MAN_AXIS_SCALE_Z: if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) { int draw_options = 0; - if ((man->twtype & (V3D_MANIP_ROTATE | V3D_MANIP_SCALE)) == 0) { + if ((man->twtype & (SCE_MANIP_ROTATE | SCE_MANIP_SCALE)) == 0) { draw_options |= ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM; } RNA_enum_set(axis->ptr, "draw_options", draw_options); @@ -1434,6 +1404,42 @@ static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup MAN_ITER_AXES_END; } +static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup *mgroup) +{ + ManipulatorGroup *man = manipulatorgroup_init(mgroup); + + mgroup->customdata = man; + + { + man->twtype = 0; + ScrArea *sa = CTX_wm_area(C); + bToolRef_Runtime *tref_rt = sa->runtime.tool ? sa->runtime.tool->runtime : NULL; + wmKeyMap *km = tref_rt ? WM_keymap_find_all(C, tref_rt->keymap, sa->spacetype, RGN_TYPE_WINDOW) : NULL; + /* Weak, check first event */ + wmKeyMapItem *kmi = km ? km->items.first : NULL; + + if (kmi == NULL) { + /* Setup all manipulators, they can be toggled via 'ToolSettings.manipulator_flag' */ + man->twtype = SCE_MANIP_TRANSLATE | SCE_MANIP_ROTATE | SCE_MANIP_SCALE; + man->use_twtype_refresh = true; + } + else if (STREQ(kmi->idname, "TRANSFORM_OT_translate")) { + man->twtype |= SCE_MANIP_TRANSLATE; + } + else if (STREQ(kmi->idname, "TRANSFORM_OT_rotate")) { + man->twtype |= SCE_MANIP_ROTATE; + } + else if (STREQ(kmi->idname, "TRANSFORM_OT_resize")) { + man->twtype |= SCE_MANIP_SCALE; + } + BLI_assert(man->twtype != 0); + man->twtype_init = man->twtype; + } + + /* *** set properties for axes *** */ + manipulatorgroup_init_properties_from_twtype(mgroup); +} + static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGroup *mgroup) { ManipulatorGroup *man = mgroup->customdata; @@ -1443,6 +1449,15 @@ static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGrou RegionView3D *rv3d = ar->regiondata; struct TransformBounds tbounds; + if (man->use_twtype_refresh) { + Scene *scene = CTX_data_scene(C); + man->twtype = scene->toolsettings->manipulator_flag & man->twtype_init; + if (man->twtype != man->twtype_prev) { + man->twtype_prev = man->twtype; + manipulatorgroup_init_properties_from_twtype(mgroup); + } + } + /* skip, we don't draw anything anyway */ if ((man->all_hidden = (ED_transform_calc_manipulator_stats( @@ -1481,7 +1496,7 @@ static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGrou RNA_float_set(axis->ptr, "length", len); if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) { - if (man->twtype & V3D_MANIP_ROTATE) { + if (man->twtype & SCE_MANIP_ROTATE) { /* Avoid rotate and translate arrows overlap. */ start_co[2] += 0.215f; } diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 704582deaca..02855e0a809 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -51,7 +51,6 @@ #include "GPU_immediate.h" -#include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_object.h" #include "BKE_anim.h" /* for duplis */ diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index c4bfe83ed4c..478e004743d 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -411,7 +411,7 @@ static const EnumPropertyItem *rna_undo_itemf(bContext *C, int *totitem) item_tmp.identifier = us->name; item_tmp.name = IFACE_(us->name); if (us == wm->undo_stack->step_active) { - item_tmp.icon = ICON_RESTRICT_VIEW_OFF; + item_tmp.icon = ICON_HIDE_OFF; } else { item_tmp.icon = ICON_NONE; diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 4473922841f..b3f3d188851 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -502,7 +502,7 @@ static void draw_uvs_other(ViewLayer *view_layer, Object *obedit, const Image *c for (Base *base = view_layer->object_bases.first; base; base = base->next) { if (((base->flag & BASE_SELECTED) != 0) && - ((base->flag & BASE_VISIBLED) != 0)) + ((base->flag & BASE_VISIBLE) != 0)) { Object *ob = base->object; if ((ob->type == OB_MESH) && (ob != obedit) && ((Mesh *)ob->data)->mloopuv) { diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 78b412579e6..5f60a5a714a 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -496,7 +496,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B smd.subdivType = smd_real->subdivType; initialDerived = CDDM_from_editbmesh(em, false, false); - derivedMesh = subsurf_make_derived_from_derived(initialDerived, &smd, + derivedMesh = subsurf_make_derived_from_derived(initialDerived, &smd, scene, NULL, SUBSURF_IN_EDIT_MODE); initialDerived->release(initialDerived); |