diff options
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 14 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_keymap.h | 5 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_types.h | 18 | ||||
-rw-r--r-- | source/blender/windowmanager/gizmo/WM_gizmo_types.h | 3 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm.c | 9 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_dragdrop.c | 17 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_draw.c | 3 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 25 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_files_link.c | 1244 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_keymap.c | 10 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 4 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_playanim.c | 3 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_event_system.h | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/xr/intern/wm_xr_operators.c | 16 |
14 files changed, 170 insertions, 1203 deletions
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index ef81addbb4d..c41c328c006 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -413,7 +413,7 @@ int WM_generic_select_invoke(struct bContext *C, const struct wmEvent *event); void WM_operator_view3d_unit_defaults(struct bContext *C, struct wmOperator *op); int WM_operator_smooth_viewtx_get(const struct wmOperator *op); -int WM_menu_invoke_ex(struct bContext *C, struct wmOperator *op, int opcontext); +int WM_menu_invoke_ex(struct bContext *C, struct wmOperator *op, wmOperatorCallContext opcontext); int WM_menu_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); void WM_menu_name_call(struct bContext *C, const char *menu_name, short context); int WM_enum_search_invoke_previews(struct bContext *C, @@ -451,7 +451,7 @@ int WM_operator_confirm_message_ex(struct bContext *C, const char *title, const int icon, const char *message, - const short opcontext); + const wmOperatorCallContext opcontext); int WM_operator_confirm_message(struct bContext *C, struct wmOperator *op, const char *message); /* operator api */ @@ -474,26 +474,26 @@ bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op bool WM_operator_name_poll(struct bContext *C, const char *opstring); int WM_operator_name_call_ptr(struct bContext *C, struct wmOperatorType *ot, - short context, + wmOperatorCallContext context, struct PointerRNA *properties); int WM_operator_name_call(struct bContext *C, const char *opstring, - short context, + wmOperatorCallContext context, struct PointerRNA *properties); int WM_operator_name_call_with_properties(struct bContext *C, const char *opstring, - short context, + wmOperatorCallContext context, struct IDProperty *properties); int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, - short context, + wmOperatorCallContext context, struct PointerRNA *properties, struct ReportList *reports, const bool is_undo); void WM_operator_name_call_ptr_with_depends_on_cursor(struct bContext *C, wmOperatorType *ot, - short opcontext, + wmOperatorCallContext opcontext, PointerRNA *properties, const char *drawstr); diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h index 564afe084b9..0633ffe55ea 100644 --- a/source/blender/windowmanager/WM_keymap.h +++ b/source/blender/windowmanager/WM_keymap.h @@ -26,6 +26,7 @@ /* dna-savable wmStructs here */ #include "BLI_utildefines.h" #include "DNA_windowmanager_types.h" +#include "WM_types.h" #ifdef __cplusplus extern "C" { @@ -169,14 +170,14 @@ int WM_keymap_item_raw_to_string(const short shift, const int result_len); wmKeyMapItem *WM_key_event_operator(const struct bContext *C, const char *opname, - int opcontext, + wmOperatorCallContext opcontext, struct IDProperty *properties, const short include_mask, const short exclude_mask, struct wmKeyMap **r_keymap); char *WM_key_event_operator_string(const struct bContext *C, const char *opname, - int opcontext, + wmOperatorCallContext opcontext, struct IDProperty *properties, const bool is_strict, char *result, diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 27c8aa532f2..b8fe3786bde 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -211,7 +211,7 @@ enum { * Context to call operator in for #WM_operator_name_call. * rna_ui.c contains EnumPropertyItem's of these, keep in sync. */ -enum { +typedef enum wmOperatorCallContext { /* if there's invoke, call it, otherwise exec */ WM_OP_INVOKE_DEFAULT, WM_OP_INVOKE_REGION_WIN, @@ -226,9 +226,11 @@ enum { WM_OP_EXEC_REGION_PREVIEW, WM_OP_EXEC_AREA, WM_OP_EXEC_SCREEN, -}; +} wmOperatorCallContext; -#define WM_OP_CONTEXT_HAS_AREA(type) (!ELEM(type, WM_OP_INVOKE_SCREEN, WM_OP_EXEC_SCREEN)) +#define WM_OP_CONTEXT_HAS_AREA(type) \ + (CHECK_TYPE_INLINE(type, wmOperatorCallContext), \ + !ELEM(type, WM_OP_INVOKE_SCREEN, WM_OP_EXEC_SCREEN)) #define WM_OP_CONTEXT_HAS_REGION(type) \ (WM_OP_CONTEXT_HAS_AREA(type) && !ELEM(type, WM_OP_INVOKE_AREA, WM_OP_EXEC_AREA)) @@ -923,7 +925,7 @@ typedef struct wmOperatorType { typedef struct wmOperatorCallParams { struct wmOperatorType *optype; struct PointerRNA *opptr; - short opcontext; + wmOperatorCallContext opcontext; } wmOperatorCallParams; #ifdef WITH_INPUT_IME @@ -1079,6 +1081,10 @@ typedef struct wmDrag { /** * Dropboxes are like keymaps, part of the screen/area/region definition. * Allocation and free is on startup and exit. + * + * The operator is polled and invoked with the current context (#WM_OP_INVOKE_DEFAULT), there is no + * way to override that (by design, since dropboxes should act on the exact mouse position). So the + * drop-boxes are supposed to check the required area and region context in their poll. */ typedef struct wmDropBox { struct wmDropBox *next, *prev; @@ -1120,10 +1126,6 @@ typedef struct wmDropBox { struct IDProperty *properties; /** RNA pointer to access properties. */ struct PointerRNA *ptr; - - /** Default invoke. */ - short opcontext; - } wmDropBox; /** diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h index ceaec94e70b..8bf82a41c91 100644 --- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h +++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h @@ -29,6 +29,7 @@ #pragma once #include "BLI_compiler_attrs.h" +#include "BLI_utildefines.h" struct wmGizmo; struct wmGizmoGroup; @@ -163,6 +164,8 @@ typedef enum eWM_GizmoFlagGroupTypeFlag { WM_GIZMOGROUPTYPE_VR_REDRAWS = (1 << 10), } eWM_GizmoFlagGroupTypeFlag; +ENUM_OPERATORS(eWM_GizmoFlagGroupTypeFlag, WM_GIZMOGROUPTYPE_VR_REDRAWS); + /** * #wmGizmoGroup.init_flag */ diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 4458b386ab6..47ee296823b 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -91,13 +91,18 @@ static void window_manager_foreach_id(ID *id, LibraryForeachIDData *data) /* This pointer can be NULL during old files reading, better be safe than sorry. */ if (win->workspace_hook != NULL) { ID *workspace = (ID *)BKE_workspace_active_get(win->workspace_hook); - BKE_LIB_FOREACHID_PROCESS_ID(data, workspace, IDWALK_CB_NOP); + BKE_lib_query_foreachid_process(data, &workspace, IDWALK_CB_USER); /* Allow callback to set a different workspace. */ BKE_workspace_active_set(win->workspace_hook, (WorkSpace *)workspace); + if (BKE_lib_query_foreachid_iter_stop(data)) { + return; + } } + if (BKE_lib_query_foreachid_process_flags_get(data) & IDWALK_INCLUDE_UI) { LISTBASE_FOREACH (ScrArea *, area, &win->global_areas.areabase) { - BKE_screen_foreach_id_screen_area(data, area); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, + BKE_screen_foreach_id_screen_area(data, area)); } } } diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index 49b84abf9a2..bc87347b2f3 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -122,7 +122,6 @@ wmDropBox *WM_dropbox_add(ListBase *lb, drop->cancel = cancel; drop->tooltip = tooltip; drop->ot = WM_operatortype_find(idname, 0); - drop->opcontext = WM_OP_INVOKE_DEFAULT; if (drop->ot == NULL) { MEM_freeN(drop); @@ -324,7 +323,8 @@ static wmDropBox *dropbox_active(bContext *C, continue; } - if (WM_operator_poll_context(C, drop->ot, drop->opcontext)) { + const wmOperatorCallContext opcontext = wm_drop_operator_context_get(drop); + if (WM_operator_poll_context(C, drop->ot, opcontext)) { return drop; } @@ -392,10 +392,11 @@ static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *even void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop) { + const wmOperatorCallContext opcontext = wm_drop_operator_context_get(drop); /* Optionally copy drag information to operator properties. Don't call it if the * operator fails anyway, it might do more than just set properties (e.g. * typically import an asset). */ - if (drop->copy && WM_operator_poll_context(C, drop->ot, drop->opcontext)) { + if (drop->copy && WM_operator_poll_context(C, drop->ot, opcontext)) { drop->copy(drag, drop); } @@ -423,6 +424,16 @@ void wm_drags_check_ops(bContext *C, const wmEvent *event) } } +/** + * The operator of a dropbox should always be executed in the context determined by the mouse + * coordinates. The dropbox poll should check the context area and region as needed. + * So this always returns #WM_OP_INVOKE_DEFAULT. + */ +wmOperatorCallContext wm_drop_operator_context_get(const wmDropBox *UNUSED(drop)) +{ + return WM_OP_INVOKE_DEFAULT; +} + /* ************** IDs ***************** */ void WM_drag_add_local_ID(wmDrag *drag, ID *id, ID *from_parent) diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 8acce240046..d8d57a9370c 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -108,6 +108,8 @@ static void wm_paintcursor_draw(bContext *C, ScrArea *area, ARegion *region) } if (pc->poll == NULL || pc->poll(C)) { + UI_SetTheme(area->spacetype, region->regiontype); + /* Prevent drawing outside region. */ GPU_scissor_test(true); GPU_scissor(region->winrct.xmin, @@ -839,6 +841,7 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view) } /* After area regions so we can do area 'overlay' drawing. */ + UI_SetTheme(0, 0); ED_screen_draw_edges(win); wm_draw_callbacks(win); wmWindowViewport(win); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index b780fef289a..474d900a53d 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -108,7 +108,7 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports, - const short context, + const wmOperatorCallContext context, const bool poll_only, wmEvent *event); @@ -1460,7 +1460,7 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports, - const short context, + const wmOperatorCallContext context, const bool poll_only, wmEvent *event) { @@ -1595,13 +1595,16 @@ static int wm_operator_call_internal(bContext *C, /* Invokes operator in context. */ int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, - short context, + wmOperatorCallContext context, PointerRNA *properties) { BLI_assert(ot == WM_operatortype_find(ot->idname, true)); return wm_operator_call_internal(C, ot, properties, NULL, context, false, NULL); } -int WM_operator_name_call(bContext *C, const char *opstring, short context, PointerRNA *properties) +int WM_operator_name_call(bContext *C, + const char *opstring, + wmOperatorCallContext context, + PointerRNA *properties) { wmOperatorType *ot = WM_operatortype_find(opstring, 0); if (ot) { @@ -1623,7 +1626,7 @@ bool WM_operator_name_poll(bContext *C, const char *opstring) int WM_operator_name_call_with_properties(struct bContext *C, const char *opstring, - short context, + wmOperatorCallContext context, struct IDProperty *properties) { PointerRNA props_ptr; @@ -1654,7 +1657,7 @@ void WM_menu_name_call(bContext *C, const char *menu_name, short context) */ int WM_operator_call_py(bContext *C, wmOperatorType *ot, - short context, + wmOperatorCallContext context, PointerRNA *properties, ReportList *reports, const bool is_undo) @@ -1778,8 +1781,11 @@ static int ui_handler_wait_for_input(bContext *C, const wmEvent *event, void *us return WM_UI_HANDLER_CONTINUE; } -void WM_operator_name_call_ptr_with_depends_on_cursor( - bContext *C, wmOperatorType *ot, short opcontext, PointerRNA *properties, const char *drawstr) +void WM_operator_name_call_ptr_with_depends_on_cursor(bContext *C, + wmOperatorType *ot, + wmOperatorCallContext opcontext, + PointerRNA *properties, + const char *drawstr) { int flag = ot->flag; @@ -3073,8 +3079,9 @@ static int wm_handlers_do_intern(bContext *C, wmWindow *win, wmEvent *event, Lis BLI_addtail(&single_lb, drag); event->customdata = &single_lb; + const wmOperatorCallContext opcontext = wm_drop_operator_context_get(drop); int op_retval = wm_operator_call_internal( - C, drop->ot, drop->ptr, NULL, drop->opcontext, false, event); + C, drop->ot, drop->ptr, NULL, opcontext, false, event); OPERATOR_RETVAL_CHECK(op_retval); if ((op_retval & OPERATOR_CANCELLED) && drop->cancel) { diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index b45cf765a75..00ac1c2ffe6 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -53,6 +53,7 @@ #include "BLO_readfile.h" #include "BKE_armature.h" +#include "BKE_blendfile_link_append.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_key.h" @@ -166,838 +167,6 @@ static int wm_link_append_flag(wmOperator *op) return flag; } -typedef struct WMLinkAppendDataItem { - char *name; - BLI_bitmap - *libraries; /* All libs (from WMLinkAppendData.libraries) to try to load this ID from. */ - short idcode; - - /** Type of action to do to append this item, and other append-specific information. */ - char append_action; - char append_tag; - - ID *new_id; - Library *source_library; - void *customdata; -} WMLinkAppendDataItem; - -typedef struct WMLinkAppendData { - LinkNodePair libraries; - LinkNodePair items; - int num_libraries; - int num_items; - /** - * Combines #eFileSel_Params_Flag from DNA_space_types.h & #eBLOLibLinkFlags from BLO_readfile.h - */ - int flag; - - /** Allows to easily find an existing items from an ID pointer. Used by append code. */ - GHash *new_id_to_item; - - /** Runtime info used by append code to manage re-use of already appended matching IDs. */ - GHash *library_weak_reference_mapping; - - /* Internal 'private' data */ - MemArena *memarena; -} WMLinkAppendData; - -typedef struct WMLinkAppendDataCallBack { - WMLinkAppendData *lapp_data; - WMLinkAppendDataItem *item; - ReportList *reports; - -} WMLinkAppendDataCallBack; - -enum { - WM_APPEND_ACT_UNSET = 0, - WM_APPEND_ACT_KEEP_LINKED, - WM_APPEND_ACT_REUSE_LOCAL, - WM_APPEND_ACT_MAKE_LOCAL, - WM_APPEND_ACT_COPY_LOCAL, -}; - -enum { - WM_APPEND_TAG_INDIRECT = 1 << 0, -}; - -static WMLinkAppendData *wm_link_append_data_new(const int flag) -{ - MemArena *ma = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - WMLinkAppendData *lapp_data = BLI_memarena_calloc(ma, sizeof(*lapp_data)); - - lapp_data->flag = flag; - lapp_data->memarena = ma; - - return lapp_data; -} - -static void wm_link_append_data_free(WMLinkAppendData *lapp_data) -{ - if (lapp_data->new_id_to_item != NULL) { - BLI_ghash_free(lapp_data->new_id_to_item, NULL, NULL); - } - - BLI_assert(lapp_data->library_weak_reference_mapping == NULL); - - BLI_memarena_free(lapp_data->memarena); -} - -/* WARNING! *Never* call wm_link_append_data_library_add() after having added some items! */ - -static void wm_link_append_data_library_add(WMLinkAppendData *lapp_data, const char *libname) -{ - size_t len = strlen(libname) + 1; - char *libpath = BLI_memarena_alloc(lapp_data->memarena, len); - - BLI_strncpy(libpath, libname, len); - BLI_linklist_append_arena(&lapp_data->libraries, libpath, lapp_data->memarena); - lapp_data->num_libraries++; -} - -static WMLinkAppendDataItem *wm_link_append_data_item_add(WMLinkAppendData *lapp_data, - const char *idname, - const short idcode, - void *customdata) -{ - WMLinkAppendDataItem *item = BLI_memarena_calloc(lapp_data->memarena, sizeof(*item)); - size_t len = strlen(idname) + 1; - - item->name = BLI_memarena_alloc(lapp_data->memarena, len); - BLI_strncpy(item->name, idname, len); - item->idcode = idcode; - item->libraries = BLI_BITMAP_NEW_MEMARENA(lapp_data->memarena, lapp_data->num_libraries); - - item->new_id = NULL; - item->append_action = WM_APPEND_ACT_UNSET; - item->customdata = customdata; - - BLI_linklist_append_arena(&lapp_data->items, item, lapp_data->memarena); - lapp_data->num_items++; - - return item; -} - -/* -------------------------------------------------------------------- */ -/** \name Library appending helper functions. - * - * FIXME: Deduplicate code with similar one in readfile.c - * \{ */ - -static bool object_in_any_scene(Main *bmain, Object *ob) -{ - LISTBASE_FOREACH (Scene *, sce, &bmain->scenes) { - if (BKE_scene_object_find(sce, ob)) { - return true; - } - } - - return false; -} - -static bool object_in_any_collection(Main *bmain, Object *ob) -{ - LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { - if (BKE_collection_has_object(collection, ob)) { - return true; - } - } - - LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { - if (scene->master_collection != NULL && - BKE_collection_has_object(scene->master_collection, ob)) { - return true; - } - } - - return false; -} - -static ID *wm_append_loose_data_instantiate_process_check(WMLinkAppendDataItem *item) -{ - /* We consider that if we either kept it linked, or re-used already local data, instantiation - * status of those should not be modified. */ - if (!ELEM(item->append_action, WM_APPEND_ACT_COPY_LOCAL, WM_APPEND_ACT_MAKE_LOCAL)) { - return NULL; - } - - ID *id = item->new_id; - if (id == NULL) { - return NULL; - } - - if (item->append_action == WM_APPEND_ACT_COPY_LOCAL) { - BLI_assert(ID_IS_LINKED(id)); - id = id->newid; - if (id == NULL) { - return NULL; - } - - BLI_assert(!ID_IS_LINKED(id)); - return id; - } - - BLI_assert(!ID_IS_LINKED(id)); - return id; -} - -static void wm_append_loose_data_instantiate_ensure_active_collection( - WMLinkAppendData *lapp_data, - Main *bmain, - Scene *scene, - ViewLayer *view_layer, - Collection **r_active_collection) -{ - /* Find or add collection as needed. */ - if (*r_active_collection == NULL) { - if (lapp_data->flag & FILE_ACTIVE_COLLECTION) { - LayerCollection *lc = BKE_layer_collection_get_active(view_layer); - *r_active_collection = lc->collection; - } - else { - *r_active_collection = BKE_collection_add(bmain, scene->master_collection, NULL); - } - } -} - -/* TODO: De-duplicate this code with the one in readfile.c, think we need some utils code for that - * in BKE. */ -static void wm_append_loose_data_instantiate(WMLinkAppendData *lapp_data, - Main *bmain, - Scene *scene, - ViewLayer *view_layer, - const View3D *v3d) -{ - if (scene == NULL) { - /* In some cases, like the asset drag&drop e.g., the caller code manages instantiation itself. - */ - return; - } - - LinkNode *itemlink; - Collection *active_collection = NULL; - const bool do_obdata = (lapp_data->flag & BLO_LIBLINK_OBDATA_INSTANCE) != 0; - - /* Do NOT make base active here! screws up GUI stuff, - * if you want it do it at the editor level. */ - const bool object_set_active = false; - - /* First pass on obdata to enable their instantiation by default, then do a second pass on - * objects to clear it for any obdata already in use. */ - if (do_obdata) { - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *id = wm_append_loose_data_instantiate_process_check(item); - if (id == NULL) { - continue; - } - const ID_Type idcode = GS(id->name); - if (!OB_DATA_SUPPORT_ID(idcode)) { - continue; - } - - id->tag |= LIB_TAG_DOIT; - } - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *id = item->new_id; - if (id == NULL || GS(id->name) != ID_OB) { - continue; - } - - Object *ob = (Object *)id; - Object *new_ob = (Object *)id->newid; - if (ob->data != NULL) { - ((ID *)(ob->data))->tag &= ~LIB_TAG_DOIT; - } - if (new_ob != NULL && new_ob->data != NULL) { - ((ID *)(new_ob->data))->tag &= ~LIB_TAG_DOIT; - } - } - } - - /* First do collections, then objects, then obdata. */ - - /* NOTE: For collections we only view_layer-instantiate duplicated collections that have - * non-instantiated objects in them. */ - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *id = wm_append_loose_data_instantiate_process_check(item); - if (id == NULL || GS(id->name) != ID_GR) { - continue; - } - - /* We do not want to force instantiation of indirectly appended collections. Users can now - * easily instantiate collections (and their objects) as needed by themselves. See T67032. */ - /* We need to check that objects in that collections are already instantiated in a scene. - * Otherwise, it's better to add the collection to the scene's active collection, than to - * instantiate its objects in active scene's collection directly. See T61141. - * - * NOTE: We only check object directly into that collection, not recursively into its - * children. - */ - Collection *collection = (Collection *)id; - /* We always add collections directly selected by the user. */ - bool do_add_collection = (item->append_tag & WM_APPEND_TAG_INDIRECT) == 0; - LISTBASE_FOREACH (CollectionObject *, coll_ob, &collection->gobject) { - Object *ob = coll_ob->ob; - if (!object_in_any_scene(bmain, ob)) { - do_add_collection = true; - break; - } - } - if (do_add_collection) { - wm_append_loose_data_instantiate_ensure_active_collection( - lapp_data, bmain, scene, view_layer, &active_collection); - - /* In case user requested instantiation of collections as empties, we do so for the one they - * explicitly selected (originally directly linked IDs). */ - if ((lapp_data->flag & BLO_LIBLINK_COLLECTION_INSTANCE) != 0 && - (item->append_tag & WM_APPEND_TAG_INDIRECT) == 0) { - /* BKE_object_add(...) messes with the selection. */ - Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2); - ob->type = OB_EMPTY; - ob->empty_drawsize = U.collection_instance_empty_size; - - const bool set_selected = (lapp_data->flag & FILE_AUTOSELECT) != 0; - /* TODO: why is it OK to make this active here but not in other situations? - * See other callers of #object_base_instance_init */ - const bool set_active = set_selected; - BLO_object_instantiate_object_base_instance_init( - bmain, active_collection, ob, view_layer, v3d, lapp_data->flag, set_active); - - /* Assign the collection. */ - ob->instance_collection = collection; - id_us_plus(&collection->id); - ob->transflag |= OB_DUPLICOLLECTION; - copy_v3_v3(ob->loc, scene->cursor.location); - } - else { - /* Add collection as child of active collection. */ - BKE_collection_child_add(bmain, active_collection, collection); - - if ((lapp_data->flag & FILE_AUTOSELECT) != 0) { - LISTBASE_FOREACH (CollectionObject *, coll_ob, &collection->gobject) { - Object *ob = coll_ob->ob; - Base *base = BKE_view_layer_base_find(view_layer, ob); - if (base) { - base->flag |= BASE_SELECTED; - BKE_scene_object_base_flag_sync_from_base(base); - } - } - } - } - } - } - - /* NOTE: For objects we only view_layer-instantiate duplicated objects that are not yet used - * anywhere. */ - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *id = wm_append_loose_data_instantiate_process_check(item); - if (id == NULL || GS(id->name) != ID_OB) { - continue; - } - - Object *ob = (Object *)id; - - if (object_in_any_collection(bmain, ob)) { - continue; - } - - wm_append_loose_data_instantiate_ensure_active_collection( - lapp_data, bmain, scene, view_layer, &active_collection); - - CLAMP_MIN(ob->id.us, 0); - ob->mode = OB_MODE_OBJECT; - - BLO_object_instantiate_object_base_instance_init( - bmain, active_collection, ob, view_layer, v3d, lapp_data->flag, object_set_active); - } - - if (!do_obdata) { - return; - } - - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *id = wm_append_loose_data_instantiate_process_check(item); - if (id == NULL) { - continue; - } - const ID_Type idcode = GS(id->name); - if (!OB_DATA_SUPPORT_ID(idcode)) { - continue; - } - if ((id->tag & LIB_TAG_DOIT) == 0) { - continue; - } - - wm_append_loose_data_instantiate_ensure_active_collection( - lapp_data, bmain, scene, view_layer, &active_collection); - - const int type = BKE_object_obdata_to_type(id); - BLI_assert(type != -1); - Object *ob = BKE_object_add_only_object(bmain, type, id->name + 2); - ob->data = id; - id_us_plus(id); - BKE_object_materials_test(bmain, ob, ob->data); - - BLO_object_instantiate_object_base_instance_init( - bmain, active_collection, ob, view_layer, v3d, lapp_data->flag, object_set_active); - - copy_v3_v3(ob->loc, scene->cursor.location); - - id->tag &= ~LIB_TAG_DOIT; - } - - /* Finally, add rigid body objects and constraints to current RB world(s). */ - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *id = wm_append_loose_data_instantiate_process_check(item); - if (id == NULL || GS(id->name) != ID_OB) { - continue; - } - BKE_rigidbody_ensure_local_object(bmain, (Object *)id); - } -} - -/** \} */ - -static int foreach_libblock_append_callback(LibraryIDLinkCallbackData *cb_data) -{ - /* NOTE: It is important to also skip liboverride references here, as those should never be made - * local. */ - if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_INTERNAL | IDWALK_CB_LOOPBACK | - IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) { - return IDWALK_RET_NOP; - } - - WMLinkAppendDataCallBack *data = cb_data->user_data; - ID *id = *cb_data->id_pointer; - - if (id == NULL) { - return IDWALK_RET_NOP; - } - - if (!BKE_idtype_idcode_is_linkable(GS(id->name))) { - /* While we do not want to add non-linkable ID (shape keys...) to the list of linked items, - * unfortunately they can use fully linkable valid IDs too, like actions. Those need to be - * processed, so we need to recursively deal with them here. */ - /* NOTE: Since we are by-passing checks in `BKE_library_foreach_ID_link` by manually calling it - * recursively, we need to take care of potential recursion cases ourselves (e.g.animdata of - * shapekey referencing the shapekey itself). */ - if (id != cb_data->id_self) { - BKE_library_foreach_ID_link( - cb_data->bmain, id, foreach_libblock_append_callback, data, IDWALK_NOP); - } - return IDWALK_RET_NOP; - } - - const bool do_recursive = (data->lapp_data->flag & BLO_LIBLINK_APPEND_RECURSIVE) != 0; - if (!do_recursive && cb_data->id_owner->lib != id->lib) { - /* When `do_recursive` is false, we only make local IDs from same library(-ies) as the - * initially directly linked ones. */ - return IDWALK_RET_NOP; - } - - WMLinkAppendDataItem *item = BLI_ghash_lookup(data->lapp_data->new_id_to_item, id); - if (item == NULL) { - item = wm_link_append_data_item_add(data->lapp_data, id->name, GS(id->name), NULL); - item->new_id = id; - item->source_library = id->lib; - /* Since we did not have an item for that ID yet, we know user did not selected it explicitly, - * it was rather linked indirectly. This info is important for instantiation of collections. */ - item->append_tag |= WM_APPEND_TAG_INDIRECT; - BLI_ghash_insert(data->lapp_data->new_id_to_item, id, item); - } - - /* NOTE: currently there is no need to do anything else here, but in the future this would be - * the place to add specific per-usage decisions on how to append an ID. */ - - return IDWALK_RET_NOP; -} - -/* Perform append operation, using modern ID usage looper to detect which ID should be kept linked, - * made local, duplicated as local, re-used from local etc. - * - * TODO: Expose somehow this logic to the two other parts of code performing actual append - * (i.e. copy/paste and `bpy` link/append API). - * Then we can heavily simplify #BKE_library_make_local(). */ -static void wm_append_do(WMLinkAppendData *lapp_data, - ReportList *reports, - Main *bmain, - Scene *scene, - ViewLayer *view_layer, - const View3D *v3d) -{ - BLI_assert((lapp_data->flag & FILE_LINK) == 0); - - const bool set_fakeuser = (lapp_data->flag & BLO_LIBLINK_APPEND_SET_FAKEUSER) != 0; - const bool do_reuse_local_id = (lapp_data->flag & BLO_LIBLINK_APPEND_LOCAL_ID_REUSE) != 0; - - const int make_local_common_flags = LIB_ID_MAKELOCAL_FULL_LIBRARY | - ((lapp_data->flag & BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR) != - 0 ? - LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR : - 0); - - LinkNode *itemlink; - - /* Generate a mapping between newly linked IDs and their items, and tag linked IDs used as - * liboverride references as already existing. */ - lapp_data->new_id_to_item = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *id = item->new_id; - if (id == NULL) { - continue; - } - BLI_ghash_insert(lapp_data->new_id_to_item, id, item); - - /* This ensures that if a liboverride reference is also linked/used by some other appended - * data, it gets a local copy instead of being made directly local, so that the liboverride - * references remain valid (i.e. linked data). */ - if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) { - id->override_library->reference->tag |= LIB_TAG_PRE_EXISTING; - } - } - - lapp_data->library_weak_reference_mapping = BKE_main_library_weak_reference_create(bmain); - - /* NOTE: Since we append items for IDs not already listed (i.e. implicitly linked indirect - * dependencies), this list will grow and we will process those IDs later, leading to a flatten - * recursive processing of all the linked dependencies. */ - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *id = item->new_id; - if (id == NULL) { - continue; - } - BLI_assert(item->customdata == NULL); - - /* In Append case linked IDs should never be marked as needing post-processing (instantiation - * of loose objects etc.). */ - BLI_assert((id->tag & LIB_TAG_DOIT) == 0); - - ID *existing_local_id = BKE_idtype_idcode_append_is_reusable(GS(id->name)) ? - BKE_main_library_weak_reference_search_item( - lapp_data->library_weak_reference_mapping, - id->lib->filepath, - id->name) : - NULL; - - if (item->append_action != WM_APPEND_ACT_UNSET) { - /* Already set, pass. */ - } - if (GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) { - CLOG_INFO(&LOG, 3, "Appended ID '%s' is proxified, keeping it linked...", id->name); - item->append_action = WM_APPEND_ACT_KEEP_LINKED; - } - else if (do_reuse_local_id && existing_local_id != NULL) { - CLOG_INFO(&LOG, 3, "Appended ID '%s' as a matching local one, re-using it...", id->name); - item->append_action = WM_APPEND_ACT_REUSE_LOCAL; - item->customdata = existing_local_id; - } - else if (id->tag & LIB_TAG_PRE_EXISTING) { - CLOG_INFO(&LOG, 3, "Appended ID '%s' was already linked, need to copy it...", id->name); - item->append_action = WM_APPEND_ACT_COPY_LOCAL; - } - else { - CLOG_INFO(&LOG, 3, "Appended ID '%s' will be made local...", id->name); - item->append_action = WM_APPEND_ACT_MAKE_LOCAL; - } - - /* Only check dependencies if we are not keeping linked data, nor re-using existing local data. - */ - if (!ELEM(item->append_action, WM_APPEND_ACT_KEEP_LINKED, WM_APPEND_ACT_REUSE_LOCAL)) { - WMLinkAppendDataCallBack cb_data = { - .lapp_data = lapp_data, .item = item, .reports = reports}; - BKE_library_foreach_ID_link( - bmain, id, foreach_libblock_append_callback, &cb_data, IDWALK_NOP); - } - - /* If we found a matching existing local id but are not re-using it, we need to properly clear - * its weak reference to linked data. */ - if (existing_local_id != NULL && - !ELEM(item->append_action, WM_APPEND_ACT_KEEP_LINKED, WM_APPEND_ACT_REUSE_LOCAL)) { - BKE_main_library_weak_reference_remove_item(lapp_data->library_weak_reference_mapping, - id->lib->filepath, - id->name, - existing_local_id); - } - } - - /* Effectively perform required operation on every linked ID. */ - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *id = item->new_id; - if (id == NULL) { - continue; - } - - ID *local_appended_new_id = NULL; - char lib_filepath[FILE_MAX]; - BLI_strncpy(lib_filepath, id->lib->filepath, sizeof(lib_filepath)); - char lib_id_name[MAX_ID_NAME]; - BLI_strncpy(lib_id_name, id->name, sizeof(lib_id_name)); - - switch (item->append_action) { - case WM_APPEND_ACT_COPY_LOCAL: - BKE_lib_id_make_local(bmain, id, make_local_common_flags | LIB_ID_MAKELOCAL_FORCE_COPY); - local_appended_new_id = id->newid; - break; - case WM_APPEND_ACT_MAKE_LOCAL: - BKE_lib_id_make_local(bmain, - id, - make_local_common_flags | LIB_ID_MAKELOCAL_FORCE_LOCAL | - LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING); - BLI_assert(id->newid == NULL); - local_appended_new_id = id; - break; - case WM_APPEND_ACT_KEEP_LINKED: - /* Nothing to do here. */ - break; - case WM_APPEND_ACT_REUSE_LOCAL: - /* We only need to set `newid` to ID found in previous loop, for proper remapping. */ - ID_NEW_SET(id, item->customdata); - /* This is not a 'new' local appended id, do not set `local_appended_new_id` here. */ - break; - case WM_APPEND_ACT_UNSET: - CLOG_ERROR( - &LOG, "Unexpected unset append action for '%s' ID, assuming 'keep link'", id->name); - break; - default: - BLI_assert(0); - } - - if (local_appended_new_id != NULL) { - if (BKE_idtype_idcode_append_is_reusable(GS(local_appended_new_id->name))) { - BKE_main_library_weak_reference_add_item(lapp_data->library_weak_reference_mapping, - lib_filepath, - lib_id_name, - local_appended_new_id); - } - - if (set_fakeuser) { - if (!ELEM(GS(local_appended_new_id->name), ID_OB, ID_GR)) { - /* Do not set fake user on objects nor collections (instancing). */ - id_fake_user_set(local_appended_new_id); - } - } - } - } - - BKE_main_library_weak_reference_destroy(lapp_data->library_weak_reference_mapping); - lapp_data->library_weak_reference_mapping = NULL; - - /* Remap IDs as needed. */ - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - - if (item->append_action == WM_APPEND_ACT_KEEP_LINKED) { - continue; - } - - ID *id = item->new_id; - if (id == NULL) { - continue; - } - if (ELEM(item->append_action, WM_APPEND_ACT_COPY_LOCAL, WM_APPEND_ACT_REUSE_LOCAL)) { - BLI_assert(ID_IS_LINKED(id)); - id = id->newid; - if (id == NULL) { - continue; - } - } - - BLI_assert(!ID_IS_LINKED(id)); - - BKE_libblock_relink_to_newid_new(bmain, id); - } - - /* Remove linked IDs when a local existing data has been reused instead. */ - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - - if (item->append_action != WM_APPEND_ACT_REUSE_LOCAL) { - continue; - } - - ID *id = item->new_id; - if (id == NULL) { - continue; - } - BLI_assert(ID_IS_LINKED(id)); - BLI_assert(id->newid != NULL); - - id->tag |= LIB_TAG_DOIT; - item->new_id = id->newid; - } - BKE_id_multi_tagged_delete(bmain); - - /* Instantiate newly created (duplicated) IDs as needed. */ - wm_append_loose_data_instantiate(lapp_data, bmain, scene, view_layer, v3d); - - /* Attempt to deal with object proxies. - * - * NOTE: Copied from `BKE_library_make_local`, but this is not really working (as in, not - * producing any useful result in any known use case), neither here nor in - * `BKE_library_make_local` currently. - * Proxies are end of life anyway, so not worth spending time on this. */ - for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - - if (item->append_action != WM_APPEND_ACT_COPY_LOCAL) { - continue; - } - - ID *id = item->new_id; - if (id == NULL) { - continue; - } - BLI_assert(ID_IS_LINKED(id)); - - /* Attempt to re-link copied proxy objects. This allows appending of an entire scene - * from another blend file into this one, even when that blend file contains proxified - * armatures that have local references. Since the proxified object needs to be linked - * (not local), this will only work when the "Localize all" checkbox is disabled. - * TL;DR: this is a dirty hack on top of an already weak feature (proxies). */ - if (GS(id->name) == ID_OB && ((Object *)id)->proxy != NULL) { - Object *ob = (Object *)id; - Object *ob_new = (Object *)id->newid; - bool is_local = false, is_lib = false; - - /* Proxies only work when the proxified object is linked-in from a library. */ - if (!ID_IS_LINKED(ob->proxy)) { - CLOG_WARN(&LOG, - "Proxy object %s will lose its link to %s, because the " - "proxified object is local", - id->newid->name, - ob->proxy->id.name); - continue; - } - - BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib); - - /* We can only switch the proxy'ing to a made-local proxy if it is no longer - * referred to from a library. Not checking for local use; if new local proxy - * was not used locally would be a nasty bug! */ - if (is_local || is_lib) { - CLOG_WARN(&LOG, - "Made-local proxy object %s will lose its link to %s, " - "because the linked-in proxy is referenced (is_local=%i, is_lib=%i)", - id->newid->name, - ob->proxy->id.name, - is_local, - is_lib); - } - else { - /* we can switch the proxy'ing from the linked-in to the made-local proxy. - * BKE_object_make_proxy() shouldn't be used here, as it allocates memory that - * was already allocated by object_make_local() (which called BKE_object_copy). */ - ob_new->proxy = ob->proxy; - ob_new->proxy_group = ob->proxy_group; - ob_new->proxy_from = ob->proxy_from; - ob_new->proxy->proxy_from = ob_new; - ob->proxy = ob->proxy_from = ob->proxy_group = NULL; - } - } - } - - BKE_main_id_newptr_and_tag_clear(bmain); -} - -static void wm_link_do(WMLinkAppendData *lapp_data, - ReportList *reports, - Main *bmain, - Scene *scene, - ViewLayer *view_layer, - const View3D *v3d) -{ - Main *mainl; - BlendHandle *bh; - Library *lib; - - const int flag = lapp_data->flag; - const int id_tag_extra = 0; - - LinkNode *liblink, *itemlink; - int lib_idx, item_idx; - - BLI_assert(lapp_data->num_items && lapp_data->num_libraries); - - for (lib_idx = 0, liblink = lapp_data->libraries.list; liblink; - lib_idx++, liblink = liblink->next) { - char *libname = liblink->link; - BlendFileReadReport bf_reports = {.reports = reports}; - - if (STREQ(libname, BLO_EMBEDDED_STARTUP_BLEND)) { - bh = BLO_blendhandle_from_memory( - datatoc_startup_blend, datatoc_startup_blend_size, &bf_reports); - } - else { - bh = BLO_blendhandle_from_file(libname, &bf_reports); - } - - if (bh == NULL) { - /* Unlikely since we just browsed it, but possible - * Error reports will have been made by BLO_blendhandle_from_file() */ - continue; - } - - /* here appending/linking starts */ - struct LibraryLink_Params liblink_params; - BLO_library_link_params_init_with_context( - &liblink_params, bmain, flag, id_tag_extra, scene, view_layer, v3d); - /* In case of append, do not handle instantiation in linking process, but during append phase - * (see #wm_append_loose_data_instantiate ). */ - if ((flag & FILE_LINK) == 0) { - liblink_params.flag &= ~BLO_LIBLINK_NEEDS_ID_TAG_DOIT; - } - - mainl = BLO_library_link_begin(&bh, libname, &liblink_params); - lib = mainl->curlib; - BLI_assert(lib); - UNUSED_VARS_NDEBUG(lib); - - if (mainl->versionfile < 250) { - BKE_reportf(reports, - RPT_WARNING, - "Linking or appending from a very old .blend file format (%d.%d), no animation " - "conversion will " - "be done! You may want to re-save your lib file with current Blender", - mainl->versionfile, - mainl->subversionfile); - } - - /* For each lib file, we try to link all items belonging to that lib, - * and tag those successful to not try to load them again with the other libs. */ - for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; - item_idx++, itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *new_id; - - if (!BLI_BITMAP_TEST(item->libraries, lib_idx)) { - continue; - } - - new_id = BLO_library_link_named_part(mainl, &bh, item->idcode, item->name, &liblink_params); - - if (new_id) { - /* If the link is successful, clear item's libs 'todo' flags. - * This avoids trying to link same item with other libraries to come. */ - BLI_bitmap_set_all(item->libraries, false, lapp_data->num_libraries); - item->new_id = new_id; - item->source_library = new_id->lib; - } - } - - BLO_library_link_end(mainl, &bh, &liblink_params); - BLO_blendhandle_close(bh); - } -} - /** * Check if an item defined by \a name and \a group can be appended/linked. * @@ -1048,7 +217,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); PropertyRNA *prop; - WMLinkAppendData *lapp_data; + BlendfileLinkAppendContext *lapp_context; char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX_LIBEXTRA], relname[FILE_MAX]; char *group, *name; int totfiles = 0; @@ -1115,7 +284,14 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) /* We define our working data... * Note that here, each item 'uses' one library, and only one. */ - lapp_data = wm_link_append_data_new(flag); + LibraryLink_Params lapp_params; + BLO_library_link_params_init_with_context( + &lapp_params, bmain, flag, 0, scene, view_layer, CTX_wm_view3d(C)); + + lapp_context = BKE_blendfile_link_append_context_new(&lapp_params); + BKE_blendfile_link_append_context_embedded_blendfile_set( + lapp_context, datatoc_startup_blend, datatoc_startup_blend_size); + if (totfiles != 0) { GHash *libraries = BLI_ghash_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__); int lib_idx = 0; @@ -1133,7 +309,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) if (!BLI_ghash_haskey(libraries, libname)) { BLI_ghash_insert(libraries, BLI_strdup(libname), POINTER_FROM_INT(lib_idx)); lib_idx++; - wm_link_append_data_library_add(lapp_data, libname); + BKE_blendfile_link_append_context_library_add(lapp_context, libname, NULL); } } } @@ -1145,7 +321,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) BLI_join_dirfile(path, sizeof(path), root, relname); if (BLO_library_path_explode(path, libname, &group, &name)) { - WMLinkAppendDataItem *item; + BlendfileLinkAppendContextItem *item; if (!wm_link_append_item_poll(op->reports, path, group, name, do_append)) { continue; @@ -1153,9 +329,9 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) lib_idx = POINTER_AS_INT(BLI_ghash_lookup(libraries, libname)); - item = wm_link_append_data_item_add( - lapp_data, name, BKE_idtype_idcode_from_name(group), NULL); - BLI_BITMAP_ENABLE(item->libraries, lib_idx); + item = BKE_blendfile_link_append_context_item_add( + lapp_context, name, BKE_idtype_idcode_from_name(group), NULL); + BKE_blendfile_link_append_context_item_library_index_enable(lapp_context, item, lib_idx); } } RNA_END; @@ -1163,16 +339,17 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) BLI_ghash_free(libraries, MEM_freeN, NULL); } else { - WMLinkAppendDataItem *item; + BlendfileLinkAppendContextItem *item; - wm_link_append_data_library_add(lapp_data, libname); - item = wm_link_append_data_item_add(lapp_data, name, BKE_idtype_idcode_from_name(group), NULL); - BLI_BITMAP_ENABLE(item->libraries, 0); + BKE_blendfile_link_append_context_library_add(lapp_context, libname, NULL); + item = BKE_blendfile_link_append_context_item_add( + lapp_context, name, BKE_idtype_idcode_from_name(group), NULL); + BKE_blendfile_link_append_context_item_library_index_enable(lapp_context, item, 0); } - if (lapp_data->num_items == 0) { + if (BKE_blendfile_link_append_context_is_empty(lapp_context)) { /* Early out in case there is nothing to link. */ - wm_link_append_data_free(lapp_data); + BKE_blendfile_link_append_context_free(lapp_context); /* Clear pre existing tag. */ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); return OPERATOR_CANCELLED; @@ -1181,7 +358,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) /* XXX We'd need re-entrant locking on Main for this to work... */ // BKE_main_lock(bmain); - wm_link_do(lapp_data, op->reports, bmain, scene, view_layer, CTX_wm_view3d(C)); + BKE_blendfile_link(lapp_context, op->reports); // BKE_main_unlock(bmain); @@ -1191,10 +368,10 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) /* append, rather than linking */ if (do_append) { - wm_append_do(lapp_data, op->reports, bmain, scene, view_layer, CTX_wm_view3d(C)); + BKE_blendfile_append(lapp_context, op->reports); } - wm_link_append_data_free(lapp_data); + BKE_blendfile_link_append_context_free(lapp_context); /* important we unset, otherwise these object won't * link into other scenes from this blend file */ @@ -1346,23 +523,29 @@ static ID *wm_file_link_append_datablock_ex(Main *bmain, BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); /* Define working data, with just the one item we want to link. */ - WMLinkAppendData *lapp_data = wm_link_append_data_new(flag); + LibraryLink_Params lapp_params; + BLO_library_link_params_init_with_context(&lapp_params, bmain, flag, 0, scene, view_layer, v3d); + + BlendfileLinkAppendContext *lapp_context = BKE_blendfile_link_append_context_new(&lapp_params); + BKE_blendfile_link_append_context_embedded_blendfile_set( + lapp_context, datatoc_startup_blend, datatoc_startup_blend_size); - wm_link_append_data_library_add(lapp_data, filepath); - WMLinkAppendDataItem *item = wm_link_append_data_item_add(lapp_data, id_name, id_code, NULL); - BLI_BITMAP_ENABLE(item->libraries, 0); + BKE_blendfile_link_append_context_library_add(lapp_context, filepath, NULL); + BlendfileLinkAppendContextItem *item = BKE_blendfile_link_append_context_item_add( + lapp_context, id_name, id_code, NULL); + BKE_blendfile_link_append_context_item_library_index_enable(lapp_context, item, 0); /* Link datablock. */ - wm_link_do(lapp_data, NULL, bmain, scene, view_layer, v3d); + BKE_blendfile_link(lapp_context, NULL); if (do_append) { - wm_append_do(lapp_data, NULL, bmain, scene, view_layer, v3d); + BKE_blendfile_append(lapp_context, NULL); } /* Get linked datablock and free working data. */ - ID *id = item->new_id; + ID *id = BKE_blendfile_link_append_context_item_newid_get(lapp_context, item); - wm_link_append_data_free(lapp_data); + BKE_blendfile_link_append_context_free(lapp_context); BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); @@ -1439,291 +622,6 @@ static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UN return OPERATOR_CANCELLED; } -static void lib_relocate_do_remap(Main *bmain, - ID *old_id, - ID *new_id, - ReportList *reports, - const bool do_reload, - const short remap_flags) -{ - BLI_assert(old_id); - if (do_reload) { - /* Since we asked for placeholders in case of missing IDs, - * we expect to always get a valid one. */ - BLI_assert(new_id); - } - if (new_id) { - CLOG_INFO(&LOG, - 4, - "Before remap of %s, old_id users: %d, new_id users: %d", - old_id->name, - old_id->us, - new_id->us); - BKE_libblock_remap_locked(bmain, old_id, new_id, remap_flags); - - if (old_id->flag & LIB_FAKEUSER) { - id_fake_user_clear(old_id); - id_fake_user_set(new_id); - } - - CLOG_INFO(&LOG, - 4, - "After remap of %s, old_id users: %d, new_id users: %d", - old_id->name, - old_id->us, - new_id->us); - - /* In some cases, new_id might become direct link, remove parent of library in this case. */ - if (new_id->lib->parent && (new_id->tag & LIB_TAG_INDIRECT) == 0) { - if (do_reload) { - BLI_assert_unreachable(); /* Should not happen in 'pure' reload case... */ - } - new_id->lib->parent = NULL; - } - } - - if (old_id->us > 0 && new_id && old_id->lib == new_id->lib) { - /* Note that this *should* not happen - but better be safe than sorry in this area, - * at least until we are 100% sure this cannot ever happen. - * Also, we can safely assume names were unique so far, - * so just replacing '.' by '~' should work, - * but this does not totally rules out the possibility of name collision. */ - size_t len = strlen(old_id->name); - size_t dot_pos; - bool has_num = false; - - for (dot_pos = len; dot_pos--;) { - char c = old_id->name[dot_pos]; - if (c == '.') { - break; - } - if (c < '0' || c > '9') { - has_num = false; - break; - } - has_num = true; - } - - if (has_num) { - old_id->name[dot_pos] = '~'; - } - else { - len = MIN2(len, MAX_ID_NAME - 7); - BLI_strncpy(&old_id->name[len], "~000", 7); - } - - id_sort_by_name(which_libbase(bmain, GS(old_id->name)), old_id, NULL); - - BKE_reportf( - reports, - RPT_WARNING, - "Lib Reload: Replacing all references to old data-block '%s' by reloaded one failed, " - "old one (%d remaining users) had to be kept and was renamed to '%s'", - new_id->name, - old_id->us, - old_id->name); - } -} - -static void lib_relocate_do(bContext *C, - Library *library, - WMLinkAppendData *lapp_data, - ReportList *reports, - const bool do_reload) -{ - ListBase *lbarray[INDEX_ID_MAX]; - int lba_idx; - - LinkNode *itemlink; - int item_idx; - - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - - /* Remove all IDs to be reloaded from Main. */ - lba_idx = set_listbasepointers(bmain, lbarray); - while (lba_idx--) { - ID *id = lbarray[lba_idx]->first; - const short idcode = id ? GS(id->name) : 0; - - if (!id || !BKE_idtype_idcode_is_linkable(idcode)) { - /* No need to reload non-linkable datatypes, - * those will get relinked with their 'users ID'. */ - continue; - } - - for (; id; id = id->next) { - if (id->lib == library) { - WMLinkAppendDataItem *item; - - /* We remove it from current Main, and add it to items to link... */ - /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitly linked here... */ - BLI_remlink(lbarray[lba_idx], id); - /* Usual special code for ShapeKeys snowflakes... */ - Key *old_key = BKE_key_from_id(id); - if (old_key != NULL) { - BLI_remlink(which_libbase(bmain, GS(old_key->id.name)), &old_key->id); - } - - item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, id); - BLI_bitmap_set_all(item->libraries, true, lapp_data->num_libraries); - - CLOG_INFO(&LOG, 4, "Datablock to seek for: %s", id->name); - } - } - } - - if (lapp_data->num_items == 0) { - /* Early out in case there is nothing to do. */ - return; - } - - BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); - - /* We do not want any instantiation here! */ - wm_link_do(lapp_data, reports, bmain, NULL, NULL, NULL); - - BKE_main_lock(bmain); - - /* We add back old id to bmain. - * We need to do this in a first, separated loop, otherwise some of those may not be handled by - * ID remapping, which means they would still reference old data to be deleted... */ - for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; - item_idx++, itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *old_id = item->customdata; - - BLI_assert(old_id); - BLI_addtail(which_libbase(bmain, GS(old_id->name)), old_id); - - /* Usual special code for ShapeKeys snowflakes... */ - Key *old_key = BKE_key_from_id(old_id); - if (old_key != NULL) { - BLI_addtail(which_libbase(bmain, GS(old_key->id.name)), &old_key->id); - } - } - - /* Since our (old) reloaded IDs were removed from main, the user count done for them in linking - * code is wrong, we need to redo it here after adding them back to main. */ - BKE_main_id_refcount_recompute(bmain, false); - - /* Note that in reload case, we also want to replace indirect usages. */ - const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | - ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE | - (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE); - for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; - item_idx++, itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *old_id = item->customdata; - ID *new_id = item->new_id; - - lib_relocate_do_remap(bmain, old_id, new_id, reports, do_reload, remap_flags); - if (new_id == NULL) { - continue; - } - /* Usual special code for ShapeKeys snowflakes... */ - Key **old_key_p = BKE_key_from_id_p(old_id); - if (old_key_p == NULL) { - continue; - } - Key *old_key = *old_key_p; - Key *new_key = BKE_key_from_id(new_id); - if (old_key != NULL) { - *old_key_p = NULL; - id_us_min(&old_key->id); - lib_relocate_do_remap(bmain, &old_key->id, &new_key->id, reports, do_reload, remap_flags); - *old_key_p = old_key; - id_us_plus_no_lib(&old_key->id); - } - } - - BKE_main_unlock(bmain); - - for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; - item_idx++, itemlink = itemlink->next) { - WMLinkAppendDataItem *item = itemlink->link; - ID *old_id = item->customdata; - - if (old_id->us == 0) { - BKE_id_free(bmain, old_id); - } - } - - /* Some datablocks can get reloaded/replaced 'silently' because they are not linkable - * (shape keys e.g.), so we need another loop here to clear old ones if possible. */ - lba_idx = set_listbasepointers(bmain, lbarray); - while (lba_idx--) { - ID *id, *id_next; - for (id = lbarray[lba_idx]->first; id; id = id_next) { - id_next = id->next; - /* XXX That check may be a bit to generic/permissive? */ - if (id->lib && (id->flag & LIB_TAG_PRE_EXISTING) && id->us == 0) { - BKE_id_free(bmain, id); - } - } - } - - /* Get rid of no more used libraries... */ - BKE_main_id_tag_idcode(bmain, ID_LI, LIB_TAG_DOIT, true); - lba_idx = set_listbasepointers(bmain, lbarray); - while (lba_idx--) { - ID *id; - for (id = lbarray[lba_idx]->first; id; id = id->next) { - if (id->lib) { - id->lib->id.tag &= ~LIB_TAG_DOIT; - } - } - } - Library *lib, *lib_next; - for (lib = which_libbase(bmain, ID_LI)->first; lib; lib = lib_next) { - lib_next = lib->id.next; - if (lib->id.tag & LIB_TAG_DOIT) { - id_us_clear_real(&lib->id); - if (lib->id.us == 0) { - BKE_id_free(bmain, (ID *)lib); - } - } - } - - /* Update overrides of reloaded linked data-blocks. */ - ID *id; - FOREACH_MAIN_ID_BEGIN (bmain, id) { - if (ID_IS_LINKED(id) || !ID_IS_OVERRIDE_LIBRARY_REAL(id) || - (id->tag & LIB_TAG_PRE_EXISTING) == 0) { - continue; - } - if ((id->override_library->reference->tag & LIB_TAG_PRE_EXISTING) == 0) { - BKE_lib_override_library_update(bmain, id); - } - } - FOREACH_MAIN_ID_END; - - /* Resync overrides if needed. */ - if (!USER_EXPERIMENTAL_TEST(&U, no_override_auto_resync)) { - BKE_lib_override_library_main_resync(bmain, - scene, - view_layer, - &(struct BlendFileReadReport){ - .reports = reports, - }); - /* We need to rebuild some of the deleted override rules (for UI feedback purpose). */ - BKE_lib_override_library_main_operations_create(bmain, true); - } - - BKE_main_collection_sync(bmain); - - BKE_main_lib_objects_recalc_all(bmain); - IMB_colormanagement_check_file_config(bmain); - - /* important we unset, otherwise these object won't - * link into other scenes from this blend file */ - BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); - - /* recreate dependency graph to include new objects */ - DEG_relations_tag_update(bmain); -} - void WM_lib_reload(Library *lib, bContext *C, ReportList *reports) { if (!BLO_has_bfile_extension(lib->filepath_abs)) { @@ -1740,14 +638,34 @@ void WM_lib_reload(Library *lib, bContext *C, ReportList *reports) return; } - WMLinkAppendData *lapp_data = wm_link_append_data_new(BLO_LIBLINK_USE_PLACEHOLDERS | - BLO_LIBLINK_FORCE_INDIRECT); + Main *bmain = CTX_data_main(C); + LibraryLink_Params lapp_params; + BLO_library_link_params_init_with_context(&lapp_params, + bmain, + BLO_LIBLINK_USE_PLACEHOLDERS | + BLO_LIBLINK_FORCE_INDIRECT, + 0, + CTX_data_scene(C), + CTX_data_view_layer(C), + NULL); + + BlendfileLinkAppendContext *lapp_context = BKE_blendfile_link_append_context_new(&lapp_params); - wm_link_append_data_library_add(lapp_data, lib->filepath_abs); + BKE_blendfile_link_append_context_library_add(lapp_context, lib->filepath_abs, NULL); - lib_relocate_do(C, lib, lapp_data, reports, true); + BKE_blendfile_library_relocate(lapp_context, reports, lib, true); - wm_link_append_data_free(lapp_data); + BKE_blendfile_link_append_context_free(lapp_context); + + BKE_main_lib_objects_recalc_all(bmain); + IMB_colormanagement_check_file_config(bmain); + + /* Important we unset, otherwise these object won't link into other scenes from this blend file. + */ + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); + + /* Recreate dependency graph to include new IDs. */ + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_WINDOW, NULL); } @@ -1763,7 +681,7 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload) if (lib) { Main *bmain = CTX_data_main(C); PropertyRNA *prop; - WMLinkAppendData *lapp_data; + BlendfileLinkAppendContext *lapp_context; char path[FILE_MAX], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX]; short flag = 0; @@ -1808,13 +726,17 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload) return OPERATOR_CANCELLED; } + LibraryLink_Params lapp_params; + BLO_library_link_params_init_with_context( + &lapp_params, bmain, flag, 0, CTX_data_scene(C), CTX_data_view_layer(C), NULL); + if (BLI_path_cmp(lib->filepath_abs, path) == 0) { CLOG_INFO(&LOG, 4, "We are supposed to reload '%s' lib (%d)", lib->filepath, lib->id.us); do_reload = true; - lapp_data = wm_link_append_data_new(flag); - wm_link_append_data_library_add(lapp_data, path); + lapp_context = BKE_blendfile_link_append_context_new(&lapp_params); + BKE_blendfile_link_append_context_library_add(lapp_context, path, NULL); } else { int totfiles = 0; @@ -1834,7 +756,7 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload) } } - lapp_data = wm_link_append_data_new(flag); + lapp_context = BKE_blendfile_link_append_context_new(&lapp_params); if (totfiles) { RNA_BEGIN (op->ptr, itemptr, "files") { @@ -1847,27 +769,39 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload) } CLOG_INFO(&LOG, 4, "\tCandidate new lib to reload datablocks from: %s", path); - wm_link_append_data_library_add(lapp_data, path); + BKE_blendfile_link_append_context_library_add(lapp_context, path, NULL); } RNA_END; } else { CLOG_INFO(&LOG, 4, "\tCandidate new lib to reload datablocks from: %s", path); - wm_link_append_data_library_add(lapp_data, path); + BKE_blendfile_link_append_context_library_add(lapp_context, path, NULL); } } if (do_reload) { - lapp_data->flag |= BLO_LIBLINK_USE_PLACEHOLDERS | BLO_LIBLINK_FORCE_INDIRECT; + BKE_blendfile_link_append_context_flag_set( + lapp_context, BLO_LIBLINK_USE_PLACEHOLDERS | BLO_LIBLINK_FORCE_INDIRECT, true); } - lib_relocate_do(C, lib, lapp_data, op->reports, do_reload); + BKE_blendfile_library_relocate(lapp_context, op->reports, lib, do_reload); - wm_link_append_data_free(lapp_data); + BKE_blendfile_link_append_context_free(lapp_context); /* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */ BLI_strncpy(G.lib, root, FILE_MAX); + BKE_main_lib_objects_recalc_all(bmain); + IMB_colormanagement_check_file_config(bmain); + + /* Important we unset, otherwise these object won't link into other scenes from this blend + * file. + */ + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); + + /* Recreate dependency graph to include new IDs. */ + DEG_relations_tag_update(bmain); + WM_event_add_notifier(C, NC_WINDOW, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 658424b84a6..35f6ce40dba 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -1394,7 +1394,7 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(const bContext *C, wmWindow *win, ListBase *handlers, const char *opname, - int UNUSED(opcontext), + wmOperatorCallContext UNUSED(opcontext), IDProperty *properties, const bool is_strict, const struct wmKeyMapItemFind_Params *params, @@ -1430,7 +1430,7 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(const bContext *C, static wmKeyMapItem *wm_keymap_item_find_props(const bContext *C, const char *opname, - int opcontext, + wmOperatorCallContext opcontext, IDProperty *properties, const bool is_strict, const struct wmKeyMapItemFind_Params *params, @@ -1543,7 +1543,7 @@ static wmKeyMapItem *wm_keymap_item_find_props(const bContext *C, static wmKeyMapItem *wm_keymap_item_find(const bContext *C, const char *opname, - int opcontext, + wmOperatorCallContext opcontext, IDProperty *properties, bool is_strict, const struct wmKeyMapItemFind_Params *params, @@ -1642,7 +1642,7 @@ static bool kmi_filter_is_visible(const wmKeyMap *UNUSED(km), char *WM_key_event_operator_string(const bContext *C, const char *opname, - int opcontext, + wmOperatorCallContext opcontext, IDProperty *properties, const bool is_strict, char *result, @@ -1682,7 +1682,7 @@ static bool kmi_filter_is_visible_type_mask(const wmKeyMap *km, */ wmKeyMapItem *WM_key_event_operator(const bContext *C, const char *opname, - int opcontext, + wmOperatorCallContext opcontext, IDProperty *properties, const short include_mask, const short exclude_mask, diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 1130ad9a558..ffdc99152b1 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1064,7 +1064,7 @@ int WM_operator_smooth_viewtx_get(const wmOperator *op) } /* invoke callback, uses enum property named "type" */ -int WM_menu_invoke_ex(bContext *C, wmOperator *op, int opcontext) +int WM_menu_invoke_ex(bContext *C, wmOperator *op, wmOperatorCallContext opcontext) { PropertyRNA *prop = op->type->prop; @@ -1216,7 +1216,7 @@ int WM_operator_confirm_message_ex(bContext *C, const char *title, const int icon, const char *message, - const short opcontext) + const wmOperatorCallContext opcontext) { IDProperty *properties = op->ptr->data; diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index fa21dbcb4bb..640fef82085 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -1570,7 +1570,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv) /* initialize the font */ BLF_init(); ps.fontid = BLF_load_mono_default(false); - BLF_size(ps.fontid, 11, 72); + BLF_size(ps.fontid, 11.0f, 72); ps.ibufx = ibuf->x; ps.ibufy = ibuf->y; @@ -1845,7 +1845,6 @@ static char *wm_main_playanim_intern(int argc, const char **argv) } IMB_exit(); - BKE_images_exit(); DEG_free_node_types(); totblock = MEM_get_memory_blocks_in_use(); diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index 40e4d905fcd..9b0f128d071 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -32,6 +32,7 @@ struct ARegion; struct GHOST_TabletData; struct ScrArea; +enum wmOperatorCallContext; #ifdef WITH_XR_OPENXR struct wmXrActionData; @@ -175,6 +176,7 @@ void wm_dropbox_free(void); void wm_drags_exit(wmWindowManager *wm, wmWindow *win); void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop); void wm_drags_check_ops(bContext *C, const wmEvent *event); +wmOperatorCallContext wm_drop_operator_context_get(const wmDropBox *drop); void wm_drags_draw(bContext *C, wmWindow *win); #ifdef __cplusplus diff --git a/source/blender/windowmanager/xr/intern/wm_xr_operators.c b/source/blender/windowmanager/xr/intern/wm_xr_operators.c index 112312bab7b..f3470edf2f7 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_operators.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_operators.c @@ -432,10 +432,10 @@ static bool wm_xr_navigation_grab_can_do_bimanual(const wmXrActionData *actionda const XrGrabData *data) { /* Returns true if: 1) Bimanual interaction is currently occurring (i.e. inputs on both - controllers are pressed) and 2) bimanual interaction occurred on the last update. This second - part is needed to avoid "jumpy" navigation changes when transitioning from one-handed to - two-handed interaction (see #wm_xr_grab_compute/compute_bimanual() for how navigation deltas - are calculated). */ + * controllers are pressed) and 2) bimanual interaction occurred on the last update. This second + * part is needed to avoid "jumpy" navigation changes when transitioning from one-handed to + * two-handed interaction (see #wm_xr_grab_compute/compute_bimanual() for how navigation deltas + * are calculated). */ return (actiondata->bimanual && data->bimanual_prev); } @@ -545,7 +545,7 @@ static int wm_xr_navigation_grab_modal(bContext *C, wmOperator *op, const wmEven /* Check if navigation is locked. */ if (!wm_xr_navigation_grab_is_locked(data, do_bimanual)) { /* Prevent unwanted snapping (i.e. "jumpy" navigation changes when transitioning from - two-handed to one-handed interaction) at the end of a bimanual interaction. */ + * two-handed to one-handed interaction) at the end of a bimanual interaction. */ if (!wm_xr_navigation_grab_is_bimanual_ending(actiondata, data)) { wm_xr_navigation_grab_apply(xr, actiondata, data, do_bimanual); } @@ -554,9 +554,9 @@ static int wm_xr_navigation_grab_modal(bContext *C, wmOperator *op, const wmEven wm_xr_navigation_grab_bimanual_state_update(actiondata, data); /* Note: KM_PRESS and KM_RELEASE are the only two values supported by XR events during event - dispatching (see #wm_xr_session_action_states_interpret()). For modal XR operators, modal - handling starts when an input is "pressed" (action state exceeds the action threshold) and - ends when the input is "released" (state falls below the threshold). */ + * dispatching (see #wm_xr_session_action_states_interpret()). For modal XR operators, modal + * handling starts when an input is "pressed" (action state exceeds the action threshold) and + * ends when the input is "released" (state falls below the threshold). */ switch (event->val) { case KM_PRESS: return OPERATOR_RUNNING_MODAL; |