Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r--source/blender/windowmanager/WM_api.h613
-rw-r--r--source/blender/windowmanager/WM_keymap.h32
-rw-r--r--source/blender/windowmanager/WM_toolsystem.h21
-rw-r--r--source/blender/windowmanager/WM_types.h6
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_api.h121
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo.c45
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c30
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c6
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h20
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c35
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c7
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_type.c5
-rw-r--r--source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h42
-rw-r--r--source/blender/windowmanager/intern/wm.c17
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c8
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c43
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c1
-rw-r--r--source/blender/windowmanager/intern/wm_event_query.c24
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c102
-rw-r--r--source/blender/windowmanager/intern/wm_files.c166
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c1262
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c3
-rw-r--r--source/blender/windowmanager/intern/wm_gesture_ops.c23
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c25
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c18
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c13
-rw-r--r--source/blender/windowmanager/intern/wm_keymap_utils.c5
-rw-r--r--source/blender/windowmanager/intern/wm_menu_type.c1
-rw-r--r--source/blender/windowmanager/intern/wm_operator_props.c53
-rw-r--r--source/blender/windowmanager/intern/wm_operator_type.c33
-rw-r--r--source/blender/windowmanager/intern/wm_operator_utils.c7
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c73
-rw-r--r--source/blender/windowmanager/intern/wm_panel_type.c1
-rw-r--r--source/blender/windowmanager/intern/wm_stereo.c4
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c1
-rw-r--r--source/blender/windowmanager/intern/wm_surface.c18
-rw-r--r--source/blender/windowmanager/intern/wm_toolsystem.c19
-rw-r--r--source/blender/windowmanager/intern/wm_uilist_type.c16
-rw-r--r--source/blender/windowmanager/intern/wm_window.c100
-rw-r--r--source/blender/windowmanager/message_bus/intern/wm_message_bus.c13
-rw-r--r--source/blender/windowmanager/message_bus/intern/wm_message_bus_intern.h3
-rw-r--r--source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c10
-rw-r--r--source/blender/windowmanager/message_bus/wm_message_bus.h12
-rw-r--r--source/blender/windowmanager/wm.h53
-rw-r--r--source/blender/windowmanager/wm_event_system.h41
-rw-r--r--source/blender/windowmanager/wm_event_types.h2
-rw-r--r--source/blender/windowmanager/wm_files.h23
-rw-r--r--source/blender/windowmanager/wm_surface.h5
-rw-r--r--source/blender/windowmanager/wm_window.h63
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_actionmap.c45
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_draw.c6
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_intern.h12
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_operators.c2
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_session.c47
54 files changed, 1312 insertions, 2044 deletions
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 8d25ece3753..4ffd31a9923 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -84,11 +84,24 @@ typedef struct wmGizmoMap wmGizmoMap;
typedef struct wmGizmoMapType wmGizmoMapType;
typedef struct wmJob wmJob;
-/* general API */
+/* General API. */
+
+/**
+ * Used for setting app-template from the command line:
+ * - non-empty string: overrides.
+ * - empty string: override, using no app template.
+ * - NULL: clears override.
+ */
void WM_init_state_app_template_set(const char *app_template);
const char *WM_init_state_app_template_get(void);
+/**
+ * Called when no ghost system was initialized.
+ */
void WM_init_state_size_set(int stax, int stay, int sizx, int sizy);
+/**
+ * For border-less and border windows set from command-line.
+ */
void WM_init_state_fullscreen_set(void);
void WM_init_state_normal_set(void);
void WM_init_state_maximized_set(void);
@@ -97,9 +110,21 @@ void WM_init_window_focus_set(bool do_it);
void WM_init_native_pixels(bool do_it);
void WM_init_tablet_api(void);
+/**
+ * Initialize Blender and load the startup file & preferences
+ * (only called once).
+ */
void WM_init(struct bContext *C, int argc, const char **argv);
+/**
+ * \note doesn't run exit() call #WM_exit() for that.
+ */
void WM_exit_ex(struct bContext *C, const bool do_python);
+/**
+ * \brief Main exit function to close Blender ordinarily.
+ * \note Use #wm_exit_schedule_delayed() to close Blender from an operator.
+ * Might leak memory otherwise.
+ */
void WM_exit(struct bContext *C) ATTR_NORETURN;
void WM_main(struct bContext *C) ATTR_NORETURN;
@@ -111,6 +136,10 @@ void WM_init_opengl(void);
void WM_check(struct bContext *C);
void WM_reinit_gizmomap_all(struct Main *bmain);
+/**
+ * Needed for cases when operators are re-registered
+ * (when operator type pointers are stored).
+ */
void WM_script_tag_reload(void);
wmWindow *WM_window_find_under_cursor(const wmWindowManager *wm,
@@ -125,13 +154,30 @@ void WM_window_pixel_sample_read(const wmWindowManager *wm,
uint *WM_window_pixels_read(struct wmWindowManager *wm, struct wmWindow *win, int r_size[2]);
+/**
+ * Support for native pixel size
+ *
+ * \note macOS retina opens window in size X, but it has up to 2 x more pixels.
+ */
int WM_window_pixels_x(const struct wmWindow *win);
int WM_window_pixels_y(const struct wmWindow *win);
+/**
+ * Get boundaries usable by all window contents, including global areas.
+ */
void WM_window_rect_calc(const struct wmWindow *win, struct rcti *r_rect);
+/**
+ * Get boundaries usable by screen-layouts, excluding global areas.
+ * \note Depends on #U.dpi_fac. Should that be outdated, call #WM_window_set_dpi first.
+ */
void WM_window_screen_rect_calc(const struct wmWindow *win, struct rcti *r_rect);
bool WM_window_is_fullscreen(const struct wmWindow *win);
bool WM_window_is_maximized(const struct wmWindow *win);
+/**
+ * Some editor data may need to be synced with scene data (3D View camera and layers).
+ * This function ensures data is synced for editors
+ * in visible work-spaces and their visible layouts.
+ */
void WM_windows_scene_data_sync(const ListBase *win_lb, struct Scene *scene) ATTR_NONNULL();
struct Scene *WM_windows_scene_get_from_screen(const struct wmWindowManager *wm,
const struct bScreen *screen)
@@ -145,6 +191,9 @@ struct WorkSpace *WM_windows_workspace_get_from_screen(const wmWindowManager *wm
struct Scene *WM_window_get_active_scene(const struct wmWindow *win)
ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+/**
+ * \warning Only call outside of area/region loops.
+ */
void WM_window_set_active_scene(struct Main *bmain,
struct bContext *C,
struct wmWindow *win,
@@ -159,6 +208,9 @@ struct WorkSpaceLayout *WM_window_get_active_layout(const struct wmWindow *win)
void WM_window_set_active_layout(struct wmWindow *win,
struct WorkSpace *workspace,
struct WorkSpaceLayout *layout) ATTR_NONNULL(1);
+/**
+ * Get the active screen of the active workspace in \a win.
+ */
struct bScreen *WM_window_get_active_screen(const struct wmWindow *win)
ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
void WM_window_set_active_screen(struct wmWindow *win,
@@ -185,6 +237,14 @@ typedef enum eWindowAlignment {
WIN_ALIGN_PARENT_CENTER,
} eWindowAlignment;
+/**
+ * \param space_type: SPACE_VIEW3D, SPACE_INFO, ... (eSpace_Type)
+ * \param toplevel: Not a child owned by other windows. A peer of main window.
+ * \param dialog: whether this should be made as a dialog-style window
+ * \param temp: whether this is considered a short-lived window
+ * \param alignment: how this window is positioned relative to its parent
+ * \return the window or NULL in case of failure.
+ */
struct wmWindow *WM_window_open(struct bContext *C,
const char *title,
int x,
@@ -208,6 +268,10 @@ void WM_autosave_init(struct wmWindowManager *wm);
bool WM_recover_last_session(struct bContext *C, struct ReportList *reports);
void WM_file_tag_modified(void);
+/**
+ * \note `scene` (and related `view_layer` and `v3d`) pointers may be NULL,
+ * in which case no instantiation of linked objects, collections etc. will be performed.
+ */
struct ID *WM_file_link_datablock(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
@@ -216,6 +280,10 @@ struct ID *WM_file_link_datablock(struct Main *bmain,
const short id_code,
const char *id_name,
int flag);
+/**
+ * \note `scene` (and related `view_layer` and `v3d`) pointers may be NULL,
+ * in which case no instantiation of appended objects, collections etc. will be performed.
+ */
struct ID *WM_file_append_datablock(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
@@ -226,14 +294,24 @@ struct ID *WM_file_append_datablock(struct Main *bmain,
int flag);
void WM_lib_reload(struct Library *lib, struct bContext *C, struct ReportList *reports);
-/* mouse cursors */
+/* Mouse cursors. */
+
void WM_cursor_set(struct wmWindow *win, int curs);
bool WM_cursor_set_from_tool(struct wmWindow *win, const ScrArea *area, const ARegion *region);
void WM_cursor_modal_set(struct wmWindow *win, int val);
void WM_cursor_modal_restore(struct wmWindow *win);
+/**
+ * To allow usage all over, we do entire WM.
+ */
void WM_cursor_wait(bool val);
+/**
+ * \param bounds: can be NULL
+ */
void WM_cursor_grab_enable(struct wmWindow *win, int wrap, bool hide, int bounds[4]);
void WM_cursor_grab_disable(struct wmWindow *win, const int mouse_ungrab_xy[2]);
+/**
+ * After this you can call restore too.
+ */
void WM_cursor_time(struct wmWindow *win, int nr);
struct wmPaintCursor *WM_paint_cursor_activate(
@@ -249,10 +327,16 @@ void WM_paint_cursor_remove_by_type(struct wmWindowManager *wm,
void (*free)(void *));
void WM_paint_cursor_tag_redraw(struct wmWindow *win, struct ARegion *region);
+/**
+ * This function requires access to the GHOST_SystemHandle (g_system).
+ */
void WM_cursor_warp(struct wmWindow *win, int x, int y);
+/**
+ * Set x, y to values we can actually position the cursor to.
+ */
void WM_cursor_compatible_xy(wmWindow *win, int *x, int *y);
-/* handlers */
+/* Handlers. */
typedef bool (*EventHandlerPoll)(const ARegion *region, const struct wmEvent *event);
struct wmEventHandler_Keymap *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap);
@@ -261,7 +345,9 @@ struct wmEventHandler_Keymap *WM_event_add_keymap_handler_poll(ListBase *handler
EventHandlerPoll poll);
struct wmEventHandler_Keymap *WM_event_add_keymap_handler_v2d_mask(ListBase *handlers,
wmKeyMap *keymap);
-/* priority not implemented, it adds in begin */
+/**
+ * \note Priorities not implemented yet, for time being just insert in begin of list.
+ */
struct wmEventHandler_Keymap *WM_event_add_keymap_handler_priority(ListBase *handlers,
wmKeyMap *keymap,
int priority);
@@ -319,6 +405,10 @@ struct wmEventHandler_UI *WM_event_add_ui_handler(const struct bContext *C,
wmUIHandlerRemoveFunc remove_fn,
void *user_data,
const char flag);
+/**
+ * \param postpone: Enable for `win->modalhandlers`,
+ * this is in a running for () loop in wm_handlers_do().
+ */
void WM_event_remove_ui_handler(ListBase *handlers,
wmUIHandlerFunc handle_fn,
wmUIHandlerRemoveFunc remove_fn,
@@ -331,13 +421,24 @@ void WM_event_free_ui_handler_all(struct bContext *C,
wmUIHandlerRemoveFunc remove_fn);
struct wmEventHandler_Op *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op);
+/**
+ * Modal handlers store a pointer to an area which might be freed while the handler runs.
+ * Use this function to NULL all handler pointers to \a old_area.
+ */
void WM_event_modal_handler_area_replace(wmWindow *win,
const struct ScrArea *old_area,
struct ScrArea *new_area);
+/**
+ * Modal handlers store a pointer to a region which might be freed while the handler runs.
+ * Use this function to NULL all handler pointers to \a old_region.
+ */
void WM_event_modal_handler_region_replace(wmWindow *win,
const struct ARegion *old_region,
struct ARegion *new_region);
+/**
+ * Called on exit or remove area, only here call cancel callback.
+ */
void WM_event_remove_handlers(struct bContext *C, ListBase *handlers);
/* handler flag */
@@ -366,11 +467,20 @@ void WM_event_add_notifier_ex(struct wmWindowManager *wm,
void *reference);
void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference);
void WM_main_add_notifier(unsigned int type, void *reference);
+/**
+ * Clear notifiers by reference, Used so listeners don't act on freed data.
+ */
void WM_main_remove_notifier_reference(const void *reference);
void WM_main_remap_editor_id_reference(struct ID *old_id, struct ID *new_id);
/* reports */
+/**
+ * Show the report in the info header.
+ */
void WM_report_banner_show(void);
+/**
+ * Hide all currently displayed banners and abort their timer.
+ */
void WM_report_banners_cancel(struct Main *bmain);
void WM_report(eReportType type, const char *message);
void WM_reportf(eReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(2, 3);
@@ -398,44 +508,87 @@ void WM_event_remove_timer(struct wmWindowManager *wm,
void WM_event_remove_timer_notifier(struct wmWindowManager *wm,
struct wmWindow *win,
struct wmTimer *timer);
+/**
+ * To (de)activate running timers temporary.
+ */
void WM_event_timer_sleep(struct wmWindowManager *wm,
struct wmWindow *win,
struct wmTimer *timer,
bool do_sleep);
-/* operator api, default callbacks */
-/* invoke callback, uses enum property named "type" */
+/* Operator API, default callbacks. */
+
+/**
+ * Helper to get select and tweak-transform to work conflict free and as desired. See
+ * #WM_operator_properties_generic_select() for details.
+ *
+ * To be used together with #WM_generic_select_invoke() and
+ * #WM_operator_properties_generic_select().
+ */
int WM_generic_select_modal(struct bContext *C,
struct wmOperator *op,
const struct wmEvent *event);
+/**
+ * Helper to get select and tweak-transform to work conflict free and as desired. See
+ * #WM_operator_properties_generic_select() for details.
+ *
+ * To be used together with #WM_generic_select_modal() and
+ * #WM_operator_properties_generic_select().
+ */
int WM_generic_select_invoke(struct bContext *C,
struct wmOperator *op,
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);
+/**
+ * Invoke callback, uses enum property named "type".
+ */
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);
+/**
+ * Call an existent menu. The menu can be created in C or Python.
+ */
void WM_menu_name_call(struct bContext *C, const char *menu_name, short context);
+/**
+ * Similar to #WM_enum_search_invoke, but draws previews. Also, this can't
+ * be used as invoke callback directly since it needs additional info.
+ */
int WM_enum_search_invoke_previews(struct bContext *C,
struct wmOperator *op,
short prv_cols,
short prv_rows);
int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
-/* invoke callback, confirm menu + exec */
+/**
+ * Invoke callback, confirm menu + exec.
+ */
int WM_operator_confirm(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int WM_operator_confirm_or_exec(struct bContext *C,
struct wmOperator *op,
const struct wmEvent *event);
-/* invoke callback, file selector "filepath" unset + exec */
+/**
+ * Invoke callback, file selector "filepath" unset + exec.
+ *
+ * #wmOperatorType.invoke, opens file-select if path property not set, otherwise executes.
+ */
int WM_operator_filesel(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op,
const struct ImageFormatData *im_format);
-/* poll callback, context checks */
+/** Callback for #wmOperatorType.poll */
bool WM_operator_winactive(struct bContext *C);
-/* invoke callback, exec + redo popup */
+/**
+ * Invoke callback, exec + redo popup.
+ *
+ * Same as #WM_operator_props_popup but don't use operator redo.
+ * just wraps #WM_operator_props_dialog_popup.
+ */
int WM_operator_props_popup_confirm(struct bContext *C,
struct wmOperator *op,
const struct wmEvent *event);
+/**
+ * Same as #WM_operator_props_popup but call the operator first,
+ * This way - the button values correspond to the result of the operator.
+ * Without this, first access to a button will make the result jump, see T32452.
+ */
int WM_operator_props_popup_call(struct bContext *C,
struct wmOperator *op,
const struct wmEvent *event);
@@ -446,6 +599,9 @@ int WM_operator_props_dialog_popup(struct bContext *C, struct wmOperator *op, in
int WM_operator_redo_popup(struct bContext *C, struct wmOperator *op);
int WM_operator_ui_popup(struct bContext *C, struct wmOperator *op, int width);
+/**
+ * Can't be used as an invoke directly, needs message arg (can be NULL).
+ */
int WM_operator_confirm_message_ex(struct bContext *C,
struct wmOperator *op,
const char *title,
@@ -454,22 +610,60 @@ int WM_operator_confirm_message_ex(struct bContext *C,
const wmOperatorCallContext opcontext);
int WM_operator_confirm_message(struct bContext *C, struct wmOperator *op, const char *message);
-/* operator api */
+/* Operator API. */
+
void WM_operator_free(struct wmOperator *op);
void WM_operator_free_all_after(wmWindowManager *wm, struct wmOperator *op);
+/**
+ * Use with extreme care!
+ * Properties, custom-data etc - must be compatible.
+ *
+ * \param op: Operator to assign the type to.
+ * \param ot: Operator type to assign.
+ */
void WM_operator_type_set(struct wmOperator *op, struct wmOperatorType *ot);
void WM_operator_stack_clear(struct wmWindowManager *wm);
+/**
+ * This function is needed in the case when an addon id disabled
+ * while a modal operator it defined is running.
+ */
void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot);
bool WM_operator_poll(struct bContext *C, struct wmOperatorType *ot);
bool WM_operator_poll_context(struct bContext *C, struct wmOperatorType *ot, short context);
+/**
+ * For running operators with frozen context (modal handlers, menus).
+ *
+ * \param store: Store settings for re-use.
+ *
+ * \warning do not use this within an operator to call its self! T29537.
+ */
int WM_operator_call_ex(struct bContext *C, struct wmOperator *op, const bool store);
int WM_operator_call(struct bContext *C, struct wmOperator *op);
+/**
+ * This is intended to be used when an invoke operator wants to call exec on its self
+ * and is basically like running op->type->exec() directly, no poll checks no freeing,
+ * since we assume whoever called invoke will take care of that
+ */
int WM_operator_call_notest(struct bContext *C, struct wmOperator *op);
+/**
+ * Execute this operator again, put here so it can share above code
+ */
int WM_operator_repeat(struct bContext *C, struct wmOperator *op);
int WM_operator_repeat_last(struct bContext *C, struct wmOperator *op);
+/**
+ * \return true if #WM_operator_repeat can run.
+ * Simple check for now but may become more involved.
+ * To be sure the operator can run call `WM_operator_poll(C, op->type)` also, since this call
+ * checks if #WM_operator_repeat() can run at all, not that it WILL run at any time.
+ */
bool WM_operator_repeat_check(const struct bContext *C, struct wmOperator *op);
bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op);
+
+bool WM_operator_name_poll(struct bContext *C, const char *opstring);
+/**
+ * Invokes operator in context.
+ */
int WM_operator_name_call_ptr(struct bContext *C,
struct wmOperatorType *ot,
wmOperatorCallContext context,
@@ -482,6 +676,13 @@ int WM_operator_name_call_with_properties(struct bContext *C,
const char *opstring,
wmOperatorCallContext context,
struct IDProperty *properties);
+/**
+ * Similar to #WM_operator_name_call called with #WM_OP_EXEC_DEFAULT context.
+ *
+ * - #wmOperatorType is used instead of operator name since python already has the operator type.
+ * - `poll()` must be called by python before this runs.
+ * - reports can be passed to this function (so python can report them as exceptions).
+ */
int WM_operator_call_py(struct bContext *C,
struct wmOperatorType *ot,
wmOperatorCallContext context,
@@ -495,15 +696,30 @@ void WM_operator_name_call_ptr_with_depends_on_cursor(struct bContext *C,
PointerRNA *properties,
const char *drawstr);
-/* Used for keymap and macro items. */
+/**
+ * Similar to the function above except its uses ID properties used for key-maps and macros.
+ */
void WM_operator_properties_alloc(struct PointerRNA **ptr,
struct IDProperty **properties,
const char *opstring);
-/* Make props context sensitive or not. */
+/**
+ * Make props context sensitive or not.
+ */
void WM_operator_properties_sanitize(struct PointerRNA *ptr, const bool no_context);
+/**
+ * Set all props to their default.
+ *
+ * \param do_update: Only update un-initialized props.
+ *
+ * \note There's nothing specific to operators here.
+ * This could be made a general function.
+ */
bool WM_operator_properties_default(struct PointerRNA *ptr, const bool do_update);
+/**
+ * Remove all props without #PROP_SKIP_SAVE.
+ */
void WM_operator_properties_reset(struct wmOperator *op);
void WM_operator_properties_create(struct PointerRNA *ptr, const char *opstring);
void WM_operator_properties_create_ptr(struct PointerRNA *ptr, struct wmOperatorType *ot);
@@ -511,18 +727,28 @@ void WM_operator_properties_clear(struct PointerRNA *ptr);
void WM_operator_properties_free(struct PointerRNA *ptr);
bool WM_operator_check_ui_empty(struct wmOperatorType *ot);
+/**
+ * Return false, if the UI should be disabled.
+ */
bool WM_operator_check_ui_enabled(const struct bContext *C, const char *idname);
IDProperty *WM_operator_last_properties_ensure_idprops(struct wmOperatorType *ot);
void WM_operator_last_properties_ensure(struct wmOperatorType *ot, struct PointerRNA *ptr);
wmOperator *WM_operator_last_redo(const struct bContext *C);
+/**
+ * Use for drag & drop a path or name with operators invoke() function.
+ */
ID *WM_operator_drop_load_path(struct bContext *C, struct wmOperator *op, const short idcode);
bool WM_operator_last_properties_init(struct wmOperator *op);
bool WM_operator_last_properties_store(struct wmOperator *op);
/* wm_operator_props.c */
+
void WM_operator_properties_confirm_or_exec(struct wmOperatorType *ot);
+/**
+ * Default properties for file-select.
+ */
void WM_operator_properties_filesel(struct wmOperatorType *ot,
int filter,
short type,
@@ -530,36 +756,91 @@ void WM_operator_properties_filesel(struct wmOperatorType *ot,
short flag,
short display,
short sort);
+/**
+ * Disable using cursor position,
+ * use when view operators are initialized from buttons.
+ */
void WM_operator_properties_use_cursor_init(struct wmOperatorType *ot);
void WM_operator_properties_border(struct wmOperatorType *ot);
void WM_operator_properties_border_to_rcti(struct wmOperator *op, struct rcti *rect);
void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect);
+/**
+ * Use with #WM_gesture_box_invoke
+ */
void WM_operator_properties_gesture_box_ex(struct wmOperatorType *ot, bool deselect, bool extend);
void WM_operator_properties_gesture_box(struct wmOperatorType *ot);
void WM_operator_properties_gesture_box_select(struct wmOperatorType *ot);
void WM_operator_properties_gesture_box_zoom(struct wmOperatorType *ot);
+/**
+ * Use with #WM_gesture_lasso_invoke
+ */
void WM_operator_properties_gesture_lasso(struct wmOperatorType *ot);
+/**
+ * Use with #WM_gesture_straightline_invoke
+ */
void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, int cursor);
+/**
+ * Use with #WM_gesture_circle_invoke
+ */
void WM_operator_properties_gesture_circle(struct wmOperatorType *ot);
void WM_operator_properties_mouse_select(struct wmOperatorType *ot);
void WM_operator_properties_select_all(struct wmOperatorType *ot);
void WM_operator_properties_select_action(struct wmOperatorType *ot,
int default_action,
bool hide_gui);
+/**
+ * Only #SELECT / #DESELECT.
+ */
void WM_operator_properties_select_action_simple(struct wmOperatorType *ot,
int default_action,
bool hide_gui);
+/**
+ * Use for all select random operators.
+ * Adds properties: percent, seed, action.
+ */
void WM_operator_properties_select_random(struct wmOperatorType *ot);
int WM_operator_properties_select_random_seed_increment_get(wmOperator *op);
void WM_operator_properties_select_operation(struct wmOperatorType *ot);
+/**
+ * \note Some tools don't support XOR/AND.
+ */
void WM_operator_properties_select_operation_simple(struct wmOperatorType *ot);
void WM_operator_properties_select_walk_direction(struct wmOperatorType *ot);
+/**
+ * Selecting and tweaking items are overlapping operations. Getting both to work without conflicts
+ * requires special care. See
+ * https://wiki.blender.org/wiki/Human_Interface_Guidelines/Selection#Select-tweaking for the
+ * desired behavior.
+ *
+ * For default click selection (with no modifier keys held), the select operators can do the
+ * following:
+ * - On a mouse press on an unselected item, change selection and finish immediately after.
+ * This sends an undo push and allows transform to take over should a tweak event be caught now.
+ * - On a mouse press on a selected item, don't change selection state, but start modal execution
+ * of the operator. Idea is that we wait with deselecting other items until we know that the
+ * intention wasn't to tweak (mouse press+drag) all selected items.
+ * - If a tweak is recognized before the release event happens, cancel the operator, so that
+ * transform can take over and no undo-push is sent.
+ * - If the release event occurs rather than a tweak one, deselect all items but the one under the
+ * cursor, and finish the modal operator.
+ *
+ * This utility, together with #WM_generic_select_invoke() and #WM_generic_select_modal() should
+ * help getting the wanted behavior to work. Most generic logic should be handled in these, so that
+ * the select operators only have to care for the case dependent handling.
+ *
+ * Every select operator has slightly different requirements, e.g. sequencer strip selection
+ * also needs to account for handle selection. This should be the baseline behavior though.
+ */
void WM_operator_properties_generic_select(struct wmOperatorType *ot);
+
struct CheckerIntervalParams {
int nth; /* bypass when set to zero */
int skip;
int offset;
};
+/**
+ * \param nth_can_disable: Enable if we want to be able to select no interval at all.
+ */
void WM_operator_properties_checker_interval(struct wmOperatorType *ot, bool nth_can_disable);
void WM_operator_properties_checker_interval_from_op(struct wmOperator *op,
struct CheckerIntervalParams *op_params);
@@ -576,7 +857,17 @@ bool WM_operator_properties_checker_interval_test(const struct CheckerIntervalPa
/* Show the properties sidebar by default. */
#define WM_FILESEL_SHOW_PROPS (1 << 5)
-/* operator as a python command (resultuing string must be freed) */
+/**
+ * Operator as a Python command (resulting string must be freed).
+ *
+ * Print a string representation of the operator,
+ * with the arguments that it runs so Python can run it again.
+ *
+ * When calling from an existing #wmOperator, better to use simple version:
+ * `WM_operator_pystring(C, op);`
+ *
+ * \note Both \a op and \a opptr may be `NULL` (\a op is only used for macro operators).
+ */
char *WM_operator_pystring_ex(struct bContext *C,
struct wmOperator *op,
const bool all_args,
@@ -587,16 +878,32 @@ char *WM_operator_pystring(struct bContext *C,
struct wmOperator *op,
const bool all_args,
const bool macro_args);
+/**
+ * \return true if the string was shortened.
+ */
bool WM_operator_pystring_abbreviate(char *str, int str_len_max);
char *WM_prop_pystring_assign(struct bContext *C,
struct PointerRNA *ptr,
struct PropertyRNA *prop,
int index);
+/**
+ * Convert: `some.op` -> `SOME_OT_op` or leave as-is.
+ */
void WM_operator_bl_idname(char *to, const char *from);
+/**
+ * Convert: `SOME_OT_op` -> `some.op` or leave as-is.
+ */
void WM_operator_py_idname(char *to, const char *from);
+/**
+ * Sanity check to ensure #WM_operator_bl_idname won't fail.
+ * \returns true when there are no problems with \a idname, otherwise report an error.
+ */
bool WM_operator_py_idname_ok_or_report(struct ReportList *reports,
const char *classname,
const char *idname);
+/**
+ * Calculate the path to `ptr` from context `C`, or return NULL if it can't be calculated.
+ */
char *WM_context_path_resolve_property_full(const struct bContext *C,
const PointerRNA *ptr,
PropertyRNA *prop,
@@ -604,16 +911,46 @@ char *WM_context_path_resolve_property_full(const struct bContext *C,
char *WM_context_path_resolve_full(struct bContext *C, const PointerRNA *ptr);
/* wm_operator_type.c */
+
struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet);
+/**
+ * \note Caller must free.
+ */
void WM_operatortype_iter(struct GHashIterator *ghi);
void WM_operatortype_append(void (*opfunc)(struct wmOperatorType *));
void WM_operatortype_append_ptr(void (*opfunc)(struct wmOperatorType *, void *), void *userdata);
void WM_operatortype_append_macro_ptr(void (*opfunc)(struct wmOperatorType *, void *),
void *userdata);
+/**
+ * Called on initialize WM_exit().
+ */
void WM_operatortype_remove_ptr(struct wmOperatorType *ot);
bool WM_operatortype_remove(const char *idname);
+/**
+ * Remove memory of all previously executed tools.
+ */
void WM_operatortype_last_properties_clear_all(void);
+/**
+ * Tag all operator-properties of \a ot defined after calling this, until
+ * the next #WM_operatortype_props_advanced_end call (if available), with
+ * #OP_PROP_TAG_ADVANCED. Previously defined ones properties not touched.
+ *
+ * Calling this multiple times without a call to #WM_operatortype_props_advanced_end,
+ * all calls after the first one are ignored. Meaning all proprieties defined after the
+ * first call are tagged as advanced.
+ *
+ * This doesn't do the actual tagging, #WM_operatortype_props_advanced_end does which is
+ * called for all operators during registration (see #wm_operatortype_append__end).
+ */
void WM_operatortype_props_advanced_begin(struct wmOperatorType *ot);
+/**
+ * Tags all operator-properties of \a ot defined since the first
+ * #WM_operatortype_props_advanced_begin call,
+ * or the last #WM_operatortype_props_advanced_end call, with #OP_PROP_TAG_ADVANCED.
+ *
+ * \note This is called for all operators during registration (see #wm_operatortype_append__end).
+ * So it does not need to be explicitly called in operator-type definition.
+ */
void WM_operatortype_props_advanced_end(struct wmOperatorType *ot);
#define WM_operatortype_prop_tag(property, tags) \
@@ -623,6 +960,9 @@ void WM_operatortype_props_advanced_end(struct wmOperatorType *ot);
} \
(void)0
+/**
+ * \note Names have to be static for now.
+ */
struct wmOperatorType *WM_operatortype_append_macro(const char *idname,
const char *name,
const char *description,
@@ -634,26 +974,57 @@ const char *WM_operatortype_name(struct wmOperatorType *ot, struct PointerRNA *p
char *WM_operatortype_description(struct bContext *C,
struct wmOperatorType *ot,
struct PointerRNA *properties);
+/**
+ * Use when we want a label, preferring the description.
+ */
char *WM_operatortype_description_or_name(struct bContext *C,
struct wmOperatorType *ot,
struct PointerRNA *properties);
/* wm_operator_utils.c */
+
+/**
+ * Allow an operator with only and execute function to run modally,
+ * re-doing the action, using vertex coordinate store/restore instead of operator undo.
+ */
void WM_operator_type_modal_from_exec_for_object_edit_coords(struct wmOperatorType *ot);
/* wm_uilist_type.c */
+
+/**
+ * Called on initialize #WM_init()
+ */
void WM_uilisttype_init(void);
struct uiListType *WM_uilisttype_find(const char *idname, bool quiet);
bool WM_uilisttype_add(struct uiListType *ult);
void WM_uilisttype_remove_ptr(struct Main *bmain, struct uiListType *ult);
void WM_uilisttype_free(void);
+/**
+ * The "full" list-ID is an internal name used for storing and identifying a list. It is built like
+ * this:
+ * "{uiListType.idname}_{list_id}", whereby "list_id" is an optional parameter passed to
+ * `UILayout.template_list()`. If it is not set, the full list-ID is just "{uiListType.idname}_".
+ *
+ * Note that whenever the Python API refers to the list-ID, it's the short, "non-full" one it
+ * passed to `UILayout.template_list()`. C code can query that through
+ * #WM_uilisttype_list_id_get().
+ */
void WM_uilisttype_to_full_list_id(const struct uiListType *ult,
const char *list_id,
char r_full_list_id[]);
+/**
+ * Get the "non-full" list-ID, see #WM_uilisttype_to_full_list_id() for details.
+ *
+ * \note Assumes `uiList.list_id` was set using #WM_uilisttype_to_full_list_id()!
+ */
const char *WM_uilisttype_list_id_get(const struct uiListType *ult, struct uiList *list);
/* wm_menu_type.c */
+
+/**
+ * \note Called on initialize #WM_init().
+ */
void WM_menutype_init(void);
struct MenuType *WM_menutype_find(const char *idname, bool quiet);
void WM_menutype_iter(struct GHashIterator *ghi);
@@ -663,6 +1034,10 @@ void WM_menutype_free(void);
bool WM_menutype_poll(struct bContext *C, struct MenuType *mt);
/* wm_panel_type.c */
+
+/**
+ * Called on initialize #WM_init().
+ */
void WM_paneltype_init(void);
void WM_paneltype_clear(void);
struct PanelType *WM_paneltype_find(const char *idname, bool quiet);
@@ -690,6 +1065,11 @@ int WM_gesture_lasso_invoke(struct bContext *C,
const struct wmEvent *event);
int WM_gesture_lasso_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
void WM_gesture_lasso_cancel(struct bContext *C, struct wmOperator *op);
+/**
+ * helper function, we may want to add options for conversion to view space
+ *
+ * caller must free.
+ */
const int (*WM_gesture_lasso_path_to_array(struct bContext *C,
struct wmOperator *op,
int *mcoords_len))[2];
@@ -697,18 +1077,38 @@ const int (*WM_gesture_lasso_path_to_array(struct bContext *C,
int WM_gesture_straightline_invoke(struct bContext *C,
struct wmOperator *op,
const struct wmEvent *event);
+/**
+ * This invoke callback starts the straight-line gesture with a viewport preview to the right side
+ * of the line.
+ */
int WM_gesture_straightline_active_side_invoke(struct bContext *C,
struct wmOperator *op,
const struct wmEvent *event);
+/**
+ * This modal callback calls exec once per mouse move event while the gesture is active with the
+ * updated line start and end values, so it can be used for tools that have a real time preview
+ * (like a gradient updating in real time over the mesh).
+ */
int WM_gesture_straightline_modal(struct bContext *C,
struct wmOperator *op,
const struct wmEvent *event);
+/**
+ * This modal one-shot callback only calls exec once after the gesture finishes without any updates
+ * during the gesture execution. Should be used for operations that are intended to be applied once
+ * without real time preview (like a trimming tool that only applies the bisect operation once
+ * after finishing the gesture as the bisect operation is too heavy to be computed in real time for
+ * a preview).
+ */
int WM_gesture_straightline_oneshot_modal(struct bContext *C,
struct wmOperator *op,
const struct wmEvent *event);
void WM_gesture_straightline_cancel(struct bContext *C, struct wmOperator *op);
/* Gesture manager API */
+
+/**
+ * Context checked on having screen, window and area.
+ */
struct wmGesture *WM_gesture_new(struct wmWindow *window,
const struct ARegion *region,
const struct wmEvent *event,
@@ -718,15 +1118,34 @@ void WM_gestures_remove(struct wmWindow *win);
void WM_gestures_free_all(struct wmWindow *win);
bool WM_gesture_is_modal_first(const struct wmGesture *gesture);
-/* fileselecting support */
+/* File-selecting support. */
+
+/**
+ * The idea here is to keep a handler alive on window queue, owning the operator.
+ * The file window can send event to make it execute, thus ensuring
+ * executing happens outside of lower level queues, with UI refreshed.
+ * Should also allow multi-window solutions.
+ */
void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op);
void WM_event_fileselect_event(struct wmWindowManager *wm, void *ophandle, int eventval);
+/**
+ * Sets the active region for this space from the context.
+ *
+ * \see #BKE_area_find_region_active_win
+ */
void WM_operator_region_active_win_set(struct bContext *C);
+/**
+ * Only finish + pass through for press events (allowing press-tweak).
+ */
int WM_operator_flag_only_pass_through_on_press(int retval, const struct wmEvent *event);
-/* drag and drop */
+/* Drag and drop. */
+
+/**
+ * Note that the pointer should be valid allocated and not on stack.
+ */
struct wmDrag *WM_event_start_drag(
struct bContext *C, int icon, int type, void *poin, double value, unsigned int flags);
void WM_event_drag_image(struct wmDrag *, struct ImBuf *, float scale, int sx, int sy);
@@ -748,30 +1167,61 @@ void WM_drag_draw_default_fn(struct bContext *C,
struct wmWindow *win,
struct wmDrag *drag,
const int xy[2]);
+/**
+ * `spaceid` / `regionid` are zero for window drop maps.
+ */
ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid);
/* ID drag and drop */
+
+/**
+ * \param flag_extra: Additional linking flags (from #eFileSel_Params_Flag).
+ */
ID *WM_drag_asset_id_import(wmDragAsset *asset_drag, int flag_extra);
bool WM_drag_asset_will_import_linked(const wmDrag *drag);
void WM_drag_add_local_ID(struct wmDrag *drag, struct ID *id, struct ID *from_parent);
struct ID *WM_drag_get_local_ID(const struct wmDrag *drag, short idcode);
struct ID *WM_drag_get_local_ID_from_event(const struct wmEvent *event, short idcode);
+/**
+ * Check if the drag data is either a local ID or an external ID asset of type \a idcode.
+ */
bool WM_drag_is_ID_type(const struct wmDrag *drag, int idcode);
+/**
+ * \note: Does not store \a asset in any way, so it's fine to pass a temporary.
+ */
wmDragAsset *WM_drag_create_asset_data(const struct AssetHandle *asset,
struct AssetMetaData *metadata,
const char *path,
int import_type);
struct wmDragAsset *WM_drag_get_asset_data(const struct wmDrag *drag, int idcode);
struct AssetMetaData *WM_drag_get_asset_meta_data(const struct wmDrag *drag, int idcode);
+/**
+ * When dragging a local ID, return that. Otherwise, if dragging an asset-handle, link or append
+ * that depending on what was chosen by the drag-box (currently append only in fact).
+ *
+ * Use #WM_drag_free_imported_drag_ID() as cancel callback of the drop-box, so that the asset
+ * import is rolled back if the drop operator fails.
+ */
struct ID *WM_drag_get_local_ID_or_import_from_asset(const struct wmDrag *drag, int idcode);
+/**
+ * \brief Free asset ID imported for canceled drop.
+ *
+ * If the asset was imported (linked/appended) using #WM_drag_get_local_ID_or_import_from_asset()`
+ * (typically via a #wmDropBox.copy() callback), we want the ID to be removed again if the drop
+ * operator cancels.
+ * This is for use as #wmDropBox.cancel() callback.
+ */
void WM_drag_free_imported_drag_ID(struct Main *bmain,
struct wmDrag *drag,
struct wmDropBox *drop);
struct wmDragAssetCatalog *WM_drag_get_asset_catalog_data(const struct wmDrag *drag);
+/**
+ * \note: Does not store \a asset in any way, so it's fine to pass a temporary.
+ */
void WM_drag_add_asset_list_item(wmDrag *drag,
const struct bContext *C,
const struct AssetLibraryReference *asset_library_ref,
@@ -788,6 +1238,10 @@ void wmWindowViewport(struct wmWindow *win);
/* OpenGL utilities with safety check */
void wmOrtho2(float x1, float x2, float y1, float y2);
/* use for conventions (avoid hard-coded offsets all over) */
+
+/**
+ * Default pixel alignment for regions.
+ */
void wmOrtho2_region_pixelspace(const struct ARegion *region);
void wmOrtho2_pixelspace(const float x, const float y);
void wmGetProjectionMatrix(float mat[4][4], const struct rcti *winrct);
@@ -834,6 +1288,12 @@ enum {
* if having hard coded values is a problem */
};
+/**
+ * \return current job or adds new job, but doesn't run it.
+ *
+ * \note every owner only gets a single job,
+ * adding a new one will stop running job and when stopped it starts the new one.
+ */
struct wmJob *WM_jobs_get(struct wmWindowManager *wm,
struct wmWindow *win,
const void *owner,
@@ -841,9 +1301,15 @@ struct wmJob *WM_jobs_get(struct wmWindowManager *wm,
int flag,
int job_type);
+/**
+ * Returns true if job runs, for UI (progress) indicators.
+ */
bool WM_jobs_test(const struct wmWindowManager *wm, const void *owner, int job_type);
float WM_jobs_progress(const struct wmWindowManager *wm, const void *owner);
const char *WM_jobs_name(const struct wmWindowManager *wm, const void *owner);
+/**
+ * Time that job started.
+ */
double WM_jobs_starttime(const struct wmWindowManager *wm, const void *owner);
void *WM_jobs_customdata(struct wmWindowManager *wm, const void *owner);
void *WM_jobs_customdata_from_type(struct wmWindowManager *wm, int job_type);
@@ -865,12 +1331,28 @@ void WM_jobs_callbacks(struct wmJob *,
void (*update)(void *),
void (*endjob)(void *));
+/**
+ * If job running, the same owner gave it a new job.
+ * if different owner starts existing startjob, it suspends itself
+ */
void WM_jobs_start(struct wmWindowManager *wm, struct wmJob *);
+/**
+ * Signal job(s) from this owner or callback to stop, timer is required to get handled.
+ */
void WM_jobs_stop(struct wmWindowManager *wm, const void *owner, void *startjob);
+/**
+ * Actually terminate thread and job timer.
+ */
void WM_jobs_kill(struct wmWindowManager *wm,
void *owner,
void (*)(void *, short int *, short int *, float *));
+/**
+ * Wait until every job ended.
+ */
void WM_jobs_kill_all(struct wmWindowManager *wm);
+/**
+ * Wait until every job ended, except for one owner (used in undo to keep screen job alive).
+ */
void WM_jobs_kill_all_except(struct wmWindowManager *wm, const void *owner);
void WM_jobs_kill_type(struct wmWindowManager *wm, const void *owner, int job_type);
@@ -879,16 +1361,27 @@ bool WM_jobs_has_running(const struct wmWindowManager *wm);
void WM_job_main_thread_lock_acquire(struct wmJob *job);
void WM_job_main_thread_lock_release(struct wmJob *job);
-/* clipboard */
+/* Clipboard. */
+
+/**
+ * Return text from the clipboard.
+ *
+ * \note Caller needs to check for valid utf8 if this is a requirement.
+ */
char *WM_clipboard_text_get(bool selection, int *r_len);
+/**
+ * Convenience function for pasting to areas of Blender which don't support newlines.
+ */
char *WM_clipboard_text_get_firstline(bool selection, int *r_len);
void WM_clipboard_text_set(const char *buf, bool selection);
/* progress */
+
void WM_progress_set(struct wmWindow *win, float progress);
void WM_progress_clear(struct wmWindow *win);
/* Draw (for screenshot) */
+
void *WM_draw_cb_activate(struct wmWindow *win,
void (*draw)(const struct wmWindow *, void *),
void *customdata);
@@ -900,21 +1393,29 @@ void WM_draw_region_viewport_bind(struct ARegion *region);
void WM_draw_region_viewport_unbind(struct ARegion *region);
/* Region drawing */
+
void WM_draw_region_free(struct ARegion *region, bool hide);
struct GPUViewport *WM_draw_region_get_viewport(struct ARegion *region);
struct GPUViewport *WM_draw_region_get_bound_viewport(struct ARegion *region);
void WM_main_playanim(int argc, const char **argv);
-/* debugging only, convenience function to write on crash */
+/**
+ * Debugging only, convenience function to write on crash.
+ * Convenient to save a blend file from a debugger.
+ */
bool write_crash_blend(void);
-/* Lock the interface for any communication */
+/**
+ * Lock the interface for any communication.
+ */
void WM_set_locked_interface(struct wmWindowManager *wm, bool lock);
void WM_event_tablet_data_default_set(struct wmTabletData *tablet_data);
-/* For testing only 'G_FLAG_EVENT_SIMULATE' */
+/**
+ * For testing only, see #G_FLAG_EVENT_SIMULATE.
+ */
struct wmEvent *WM_event_add_simulate(struct wmWindow *win, const struct wmEvent *event_to_add);
const char *WM_window_cursor_keymap_status_get(const struct wmWindow *win,
@@ -923,28 +1424,60 @@ const char *WM_window_cursor_keymap_status_get(const struct wmWindow *win,
void WM_window_cursor_keymap_status_refresh(struct bContext *C, struct wmWindow *win);
void WM_window_status_area_tag_redraw(struct wmWindow *win);
+/**
+ * Similar to #BKE_screen_area_map_find_area_xy and related functions,
+ * use here since the area is stored in the window manager.
+ */
struct ScrArea *WM_window_status_area_find(struct wmWindow *win, struct bScreen *screen);
bool WM_window_modal_keymap_status_draw(struct bContext *C,
struct wmWindow *win,
struct uiLayout *layout);
/* wm_event_query.c */
+
+/**
+ * For debugging only, getting inspecting events manually is tedious.
+ */
void WM_event_print(const struct wmEvent *event);
int WM_event_modifier_flag(const struct wmEvent *event);
+/**
+ * For modal callbacks, check configuration for how to interpret exit with tweaks.
+ */
bool WM_event_is_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
bool WM_event_is_last_mousemove(const struct wmEvent *event);
bool WM_event_is_mouse_drag(const struct wmEvent *event);
bool WM_event_is_mouse_drag_or_press(const wmEvent *event);
+/**
+ * Detect motion between selection (callers should only use this for selection picking),
+ * typically mouse press/click events.
+ *
+ * \param mval: Region relative coordinates, call with (-1, -1) resets the last cursor location.
+ * \returns True when there was motion since last called.
+ *
+ * NOTE(@campbellbarton): The logic used here isn't foolproof.
+ * It's possible that users move the cursor past #WM_EVENT_CURSOR_MOTION_THRESHOLD then back to
+ * a position within the threshold (between mouse clicks).
+ * In practice users never reported this since the threshold is very small (a few pixels).
+ * To prevent the unlikely case of values matching from another region,
+ * changing regions resets this value to (-1, -1).
+ */
bool WM_cursor_test_motion_and_update(const int mval[2]) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
int WM_event_drag_threshold(const struct wmEvent *event);
bool WM_event_drag_test(const struct wmEvent *event, const int prev_xy[2]);
bool WM_event_drag_test_with_delta(const struct wmEvent *event, const int delta[2]);
-/* event map */
+/**
+ * Event map that takes preferences into account.
+ */
int WM_userdef_event_map(int kmitype);
+/**
+ * Use so we can check if 'wmEvent.type' is released in modal operators.
+ *
+ * An alternative would be to add a 'wmEvent.type_nokeymap'... or similar.
+ */
int WM_userdef_event_type_from_keymap_type(int kmitype);
#ifdef WITH_INPUT_NDOF
@@ -961,6 +1494,10 @@ void WM_event_ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4]);
bool WM_event_is_xr(const struct wmEvent *event);
#endif
+/**
+ * If this is a tablet event, return tablet pressure and set `*pen_flip`
+ * to 1 if the eraser tool is being used, 0 otherwise.
+ */
float WM_event_tablet_data(const struct wmEvent *event, int *pen_flip, float tilt[2]);
bool WM_event_is_tablet(const struct wmEvent *event);
@@ -972,6 +1509,7 @@ bool WM_event_is_ime_switch(const struct wmEvent *event);
#endif
/* wm_tooltip.c */
+
typedef struct ARegion *(*wmTooltipInitFn)(struct bContext *C,
struct ARegion *region,
int *pass,
@@ -1001,6 +1539,7 @@ void WM_tooltip_refresh(struct bContext *C, struct wmWindow *win);
double WM_tooltip_time_closed(void);
/* wm_utils.c */
+
struct wmGenericCallback *WM_generic_callback_steal(struct wmGenericCallback *callback);
void WM_generic_callback_free(struct wmGenericCallback *callback);
@@ -1010,7 +1549,15 @@ bool WM_region_use_viewport(struct ScrArea *area, struct ARegion *region);
#ifdef WITH_XR_OPENXR
/* wm_xr_session.c */
+
+/**
+ * Check if the XR-Session was triggered.
+ * If an error happened while trying to start a session, this returns false too.
+ */
bool WM_xr_session_exists(const wmXrData *xr);
+/**
+ * Check if the session is running, according to the OpenXR definition.
+ */
bool WM_xr_session_is_ready(const wmXrData *xr);
struct wmXrSessionState *WM_xr_session_state_handle_get(const wmXrData *xr);
struct ScrArea *WM_xr_session_area_get(const wmXrData *xr);
@@ -1043,8 +1590,10 @@ void WM_xr_session_state_navigation_reset(struct wmXrSessionState *state);
struct ARegionType *WM_xr_surface_controller_region_type_get(void);
/* wm_xr_actions.c */
+
/* XR action functions to be called pre-XR session start.
* NOTE: The "destroy" functions can also be called post-session start. */
+
bool WM_xr_action_set_create(wmXrData *xr, const char *action_set_name);
void WM_xr_action_set_destroy(wmXrData *xr, const char *action_set_name);
bool WM_xr_action_create(wmXrData *xr,
@@ -1078,7 +1627,9 @@ void WM_xr_action_binding_destroy(wmXrData *xr,
const char *action_name,
const char *profile_path);
-/* If action_set_name is NULL, then all action sets will be treated as active. */
+/**
+ * If action_set_name is NULL, then all action sets will be treated as active.
+ */
bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name);
bool WM_xr_controller_pose_actions_set(wmXrData *xr,
@@ -1086,7 +1637,9 @@ bool WM_xr_controller_pose_actions_set(wmXrData *xr,
const char *grip_action_name,
const char *aim_action_name);
-/* XR action functions to be called post-XR session start. */
+/**
+ * XR action functions to be called post-XR session start.
+ */
bool WM_xr_action_state_get(const wmXrData *xr,
const char *action_set_name,
const char *action_name,
@@ -1105,9 +1658,13 @@ void WM_xr_haptic_action_stop(wmXrData *xr,
const char *subaction_path);
/* wm_xr_actionmap.c */
+
XrActionMap *WM_xr_actionmap_new(struct wmXrRuntimeData *runtime,
const char *name,
bool replace_existing);
+/**
+ * Ensure unique name among all action maps.
+ */
void WM_xr_actionmap_ensure_unique(struct wmXrRuntimeData *runtime, XrActionMap *actionmap);
XrActionMap *WM_xr_actionmap_add_copy(struct wmXrRuntimeData *runtime, XrActionMap *am_src);
bool WM_xr_actionmap_remove(struct wmXrRuntimeData *runtime, XrActionMap *actionmap);
@@ -1123,15 +1680,25 @@ void WM_xr_actionmap_selected_index_set(struct wmXrRuntimeData *runtime, short i
XrActionMapItem *WM_xr_actionmap_item_new(XrActionMap *actionmap,
const char *name,
bool replace_existing);
+/**
+ * Ensure unique name among all action map items.
+ */
void WM_xr_actionmap_item_ensure_unique(XrActionMap *actionmap, XrActionMapItem *ami);
XrActionMapItem *WM_xr_actionmap_item_add_copy(XrActionMap *actionmap, XrActionMapItem *ami_src);
bool WM_xr_actionmap_item_remove(XrActionMap *actionmap, XrActionMapItem *ami);
XrActionMapItem *WM_xr_actionmap_item_find(XrActionMap *actionmap, const char *name);
+/**
+ * Similar to #wm_xr_actionmap_item_properties_set()
+ * but checks for the #eXrActionType and #wmOperatorType having changed.
+ */
void WM_xr_actionmap_item_properties_update_ot(XrActionMapItem *ami);
XrActionMapBinding *WM_xr_actionmap_binding_new(XrActionMapItem *ami,
const char *name,
bool replace_existing);
+/**
+ * Ensure unique name among all action map bindings.
+ */
void WM_xr_actionmap_binding_ensure_unique(XrActionMapItem *ami, XrActionMapBinding *amb);
XrActionMapBinding *WM_xr_actionmap_binding_add_copy(XrActionMapItem *ami,
XrActionMapBinding *amb_src);
diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index 0633ffe55ea..4d1f2d979cb 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -55,6 +55,9 @@ void WM_keyconfig_update_operatortype(void);
void WM_keymap_clear(struct wmKeyMap *keymap);
+/**
+ * Always add item.
+ */
wmKeyMapItem *WM_keymap_add_item(
struct wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier);
wmKeyMapItem *WM_keymap_add_item_copy(struct wmKeyMap *keymap, wmKeyMapItem *kmi_src);
@@ -91,16 +94,30 @@ bool WM_keymap_item_compare(const struct wmKeyMapItem *k1, const struct wmKeyMap
/* keymap_utils.c */
-/** Wrappers for #WM_keymap_add_item */
+/* Wrappers for #WM_keymap_add_item */
+
+/**
+ * Menu wrapper for #WM_keymap_add_item.
+ */
wmKeyMapItem *WM_keymap_add_menu(
struct wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier);
+/**
+ * Pie-menu wrapper for #WM_keymap_add_item.
+ */
wmKeyMapItem *WM_keymap_add_menu_pie(
struct wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier);
+/**
+ * Panel (popover) wrapper for #WM_keymap_add_item.
+ */
wmKeyMapItem *WM_keymap_add_panel(
struct wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier);
+/**
+ * Tool wrapper for #WM_keymap_add_item.
+ */
wmKeyMapItem *WM_keymap_add_tool(
struct wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier);
+/** Useful for mapping numbers to an enum. */
void WM_keymap_add_context_enum_set_items(wmKeyMap *keymap,
const struct EnumPropertyItem *items,
const char *data_path,
@@ -110,6 +127,12 @@ void WM_keymap_add_context_enum_set_items(wmKeyMap *keymap,
int keymodifier);
wmKeyMap *WM_keymap_guess_from_context(const struct bContext *C);
+
+/**
+ * Guess an appropriate key-map from the operator name.
+ *
+ * \note Needs to be kept up to date with Key-map and Operator naming.
+ */
wmKeyMap *WM_keymap_guess_opname(const struct bContext *C, const char *opname);
bool WM_keymap_uses_event_modifier(const wmKeyMap *keymap, const int event_modifier);
@@ -149,6 +172,9 @@ void WM_modalkeymap_assign(struct wmKeyMap *km, const char *opname);
/* Keymap Editor */
void WM_keymap_restore_to_default(struct wmKeyMap *keymap, struct wmWindowManager *wm);
+/**
+ * Properties can be NULL, otherwise the arg passed is used and ownership is given to the `kmi`.
+ */
void WM_keymap_item_properties_reset(struct wmKeyMapItem *kmi, struct IDProperty *properties);
void WM_keymap_item_restore_to_default(wmWindowManager *wm,
struct wmKeyMap *keymap,
@@ -168,6 +194,10 @@ int WM_keymap_item_raw_to_string(const short shift,
const bool compact,
char *result,
const int result_len);
+/**
+ * \param include_mask, exclude_mask:
+ * Event types to include/exclude when looking up keys (#eEventType_Mask).
+ */
wmKeyMapItem *WM_key_event_operator(const struct bContext *C,
const char *opname,
wmOperatorCallContext opcontext,
diff --git a/source/blender/windowmanager/WM_toolsystem.h b/source/blender/windowmanager/WM_toolsystem.h
index eb89fca7b56..32b9cf1d7ba 100644
--- a/source/blender/windowmanager/WM_toolsystem.h
+++ b/source/blender/windowmanager/WM_toolsystem.h
@@ -69,6 +69,9 @@ void WM_toolsystem_unlink(struct bContext *C, struct WorkSpace *workspace, const
void WM_toolsystem_refresh(struct bContext *C, struct WorkSpace *workspace, const bToolKey *tkey);
void WM_toolsystem_reinit(struct bContext *C, struct WorkSpace *workspace, const bToolKey *tkey);
+/**
+ * Operate on all active tools.
+ */
void WM_toolsystem_unlink_all(struct bContext *C, struct WorkSpace *workspace);
void WM_toolsystem_refresh_all(struct bContext *C, struct WorkSpace *workspace);
void WM_toolsystem_reinit_all(struct bContext *C, struct wmWindow *win);
@@ -79,6 +82,12 @@ void WM_toolsystem_ref_set_from_runtime(struct bContext *C,
const struct bToolRef_Runtime *tref_rt,
const char *idname);
+/**
+ * Sync the internal active state of a tool back into the tool system,
+ * this is needed for active brushes where the real active state is not stored in the tool system.
+ *
+ * \see #toolsystem_ref_link
+ */
void WM_toolsystem_ref_sync_from_context(struct Main *bmain,
struct WorkSpace *workspace,
struct bToolRef *tref);
@@ -98,8 +107,12 @@ void WM_toolsystem_update_from_context(struct bContext *C,
struct ViewLayer *view_layer,
struct ScrArea *area);
+/**
+ * For paint modes to support non-brush tools.
+ */
bool WM_toolsystem_active_tool_is_brush(const struct bContext *C);
+/** Follow #wmMsgNotifyFn spec. */
void WM_toolsystem_do_msg_notify_tag_refresh(struct bContext *C,
struct wmMsgSubscribeKey *msg_key,
struct wmMsgSubscribeValue *msg_val);
@@ -129,6 +142,14 @@ void WM_toolsystem_ref_properties_init_for_keymap(struct bToolRef *tref,
struct PointerRNA *src_ptr,
struct wmOperatorType *ot);
+/**
+ * Use to update the active tool (shown in the top bar) in the least disruptive way.
+ *
+ * This is a little involved since there may be multiple valid active tools
+ * depending on the mode and space type.
+ *
+ * Used when undoing since the active mode may have changed.
+ */
void WM_toolsystem_refresh_active(struct bContext *C);
void WM_toolsystem_refresh_screen_area(struct WorkSpace *workspace,
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index b8fe3786bde..3d56303a424 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -972,10 +972,10 @@ typedef void (*wmPaintCursorDraw)(struct bContext *C, int, int, void *customdata
#define WM_DRAG_DATASTACK 8
#define WM_DRAG_ASSET_CATALOG 9
-typedef enum wmDragFlags {
+typedef enum eWM_DragFlags {
WM_DRAG_NOP = 0,
WM_DRAG_FREE_DATA = 1,
-} wmDragFlags;
+} eWM_DragFlags;
/* NOTE: structs need not exported? */
@@ -1070,7 +1070,7 @@ typedef struct wmDrag {
wmDragActiveDropState drop_state;
- unsigned int flags;
+ eWM_DragFlags flags;
/** List of wmDragIDs, all are guaranteed to have the same ID type. */
ListBase ids;
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_api.h b/source/blender/windowmanager/gizmo/WM_gizmo_api.h
index c7a4b064d0e..497e4f6e5fc 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_api.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_api.h
@@ -61,19 +61,42 @@ extern "C" {
struct wmGizmo *WM_gizmo_new_ptr(const struct wmGizmoType *gzt,
struct wmGizmoGroup *gzgroup,
struct PointerRNA *properties);
+/**
+ * \param idname: Must be a valid gizmo type name,
+ * if you need to check it exists use #WM_gizmo_new_ptr
+ * because callers of this function don't NULL check the return value.
+ */
struct wmGizmo *WM_gizmo_new(const char *idname,
struct wmGizmoGroup *gzgroup,
struct PointerRNA *properties);
+/**
+ * \warning this doesn't check #wmGizmoMap (highlight, selection etc).
+ * Typical use is when freeing the windowing data,
+ * where caller can manage clearing selection, highlight... etc.
+ */
void WM_gizmo_free(struct wmGizmo *gz);
+/**
+ * Free \a gizmo and unlink from \a gizmolist.
+ * \a gizmolist is allowed to be NULL.
+ */
void WM_gizmo_unlink(ListBase *gizmolist,
struct wmGizmoMap *gzmap,
struct wmGizmo *gz,
struct bContext *C);
+/**
+ * Remove from selection array without running callbacks.
+ */
bool WM_gizmo_select_unlink(struct wmGizmoMap *gzmap, struct wmGizmo *gz);
bool WM_gizmo_select_set(struct wmGizmoMap *gzmap, struct wmGizmo *gz, bool select);
bool WM_gizmo_highlight_set(struct wmGizmoMap *gzmap, struct wmGizmo *gz);
+/**
+ * Special function to run from setup so gizmos start out interactive.
+ *
+ * We could do this when linking them,
+ * but this complicates things since the window update code needs to run first.
+ */
void WM_gizmo_modal_set_from_setup(struct wmGizmoMap *gzmap,
struct bContext *C,
struct wmGizmo *gz,
@@ -87,17 +110,30 @@ struct PointerRNA *WM_gizmo_operator_set(struct wmGizmo *gz,
struct IDProperty *properties);
int WM_gizmo_operator_invoke(struct bContext *C, struct wmGizmo *gz, struct wmGizmoOpElem *gzop);
-/* callbacks */
+/* Callbacks. */
+
void WM_gizmo_set_fn_custom_modal(struct wmGizmo *gz, wmGizmoFnModal fn);
void WM_gizmo_set_matrix_location(struct wmGizmo *gz, const float origin[3]);
+/**
+ * #wmGizmo.matrix utility, set the orientation by it's Z axis.
+ */
void WM_gizmo_set_matrix_rotation_from_z_axis(struct wmGizmo *gz, const float z_axis[3]);
+/**
+ * #wmGizmo.matrix utility, set the orientation by it's Y/Z axis.
+ */
void WM_gizmo_set_matrix_rotation_from_yz_axis(struct wmGizmo *gz,
const float y_axis[3],
const float z_axis[3]);
void WM_gizmo_set_matrix_offset_location(struct wmGizmo *gz, const float offset[3]);
+/**
+ * #wmGizmo.matrix_offset utility, set the orientation by it's Z axis.
+ */
void WM_gizmo_set_matrix_offset_rotation_from_z_axis(struct wmGizmo *gz, const float z_axis[3]);
+/**
+ * #wmGizmo.matrix_offset utility, set the orientation by it's Y/Z axis.
+ */
void WM_gizmo_set_matrix_offset_rotation_from_yz_axis(struct wmGizmo *gz,
const float y_axis[3],
const float z_axis[3]);
@@ -128,14 +164,30 @@ void WM_gizmo_calc_matrix_final_no_offset(const struct wmGizmo *gz, float r_mat[
void WM_gizmo_calc_matrix_final(const struct wmGizmo *gz, float r_mat[4][4]);
-/* properties */
+/* Properties. */
+
void WM_gizmo_properties_create_ptr(struct PointerRNA *ptr, struct wmGizmoType *gzt);
void WM_gizmo_properties_create(struct PointerRNA *ptr, const char *gtstring);
+/**
+ * Similar to #WM_gizmo_properties_create
+ * except its uses ID properties used for key-maps and macros.
+ */
void WM_gizmo_properties_alloc(struct PointerRNA **ptr,
struct IDProperty **properties,
const char *gtstring);
void WM_gizmo_properties_sanitize(struct PointerRNA *ptr, const bool no_context);
+/**
+ * Set all props to their default.
+ *
+ * \param do_update: Only update un-initialized props.
+ *
+ * \note There's nothing specific to gizmos here.
+ * This could be made a general function.
+ */
bool WM_gizmo_properties_default(struct PointerRNA *ptr, const bool do_update);
+/**
+ * Remove all props without #PROP_SKIP_SAVE.
+ */
void WM_gizmo_properties_reset(struct wmGizmo *gz);
void WM_gizmo_properties_clear(struct PointerRNA *ptr);
void WM_gizmo_properties_free(struct PointerRNA *ptr);
@@ -146,7 +198,13 @@ void WM_gizmotype_append(void (*gtfunc)(struct wmGizmoType *));
void WM_gizmotype_append_ptr(void (*gtfunc)(struct wmGizmoType *, void *), void *userdata);
bool WM_gizmotype_remove(struct bContext *C, struct Main *bmain, const char *idname);
void WM_gizmotype_remove_ptr(struct bContext *C, struct Main *bmain, struct wmGizmoType *gzt);
+/**
+ * Free but don't remove from ghash.
+ */
void WM_gizmotype_free_ptr(struct wmGizmoType *gzt);
+/**
+ * Caller must free.
+ */
void WM_gizmotype_iter(struct GHashIterator *ghi);
/* wm_gizmo_group_type.c */
@@ -155,8 +213,15 @@ struct wmGizmoGroupType *WM_gizmogrouptype_append(void (*wtfunc)(struct wmGizmoG
struct wmGizmoGroupType *WM_gizmogrouptype_append_ptr(void (*wtfunc)(struct wmGizmoGroupType *,
void *),
void *userdata);
+/**
+ * Caller must free.
+ */
void WM_gizmogrouptype_iter(struct GHashIterator *ghi);
+/**
+ * Append and insert into a gizmo typemap.
+ * This is most common for C gizmos which are enabled by default.
+ */
struct wmGizmoGroupTypeRef *WM_gizmogrouptype_append_and_link(
struct wmGizmoMapType *gzmap_type, void (*wtfunc)(struct wmGizmoGroupType *));
@@ -167,6 +232,10 @@ void WM_gizmoconfig_update_tag_group_type_init(struct wmGizmoMapType *gzmap_type
struct wmGizmoGroupType *gzgt);
void WM_gizmoconfig_update_tag_group_type_remove(struct wmGizmoMapType *gzmap_type,
struct wmGizmoGroupType *gzgt);
+/**
+ * Run in case new types have been added (runs often, early exit where possible).
+ * Follows #WM_keyconfig_update conventions.
+ */
void WM_gizmoconfig_update(struct Main *bmain);
void WM_gizmoconfig_update_tag_group_remove(struct wmGizmoMap *gzmap);
@@ -222,7 +291,8 @@ bool WM_gizmo_target_property_float_range_get(const struct wmGizmo *gz,
int WM_gizmo_target_property_array_length(const struct wmGizmo *gz,
struct wmGizmoProperty *gz_prop);
-/* definitions */
+/* Definitions. */
+
const struct wmGizmoPropertyType *WM_gizmotype_target_property_find(const struct wmGizmoType *gzt,
const char *idname);
void WM_gizmotype_target_property_def(struct wmGizmoType *gzt,
@@ -230,14 +300,21 @@ void WM_gizmotype_target_property_def(struct wmGizmoType *gzt,
int data_type,
int array_length);
-/* utilities */
+/* Utilities. */
+
void WM_gizmo_do_msg_notify_tag_refresh(struct bContext *C,
struct wmMsgSubscribeKey *msg_key,
struct wmMsgSubscribeValue *msg_val);
+/**
+ * Runs on the "prepare draw" pass, drawing the region clears.
+ */
void WM_gizmo_target_property_subscribe_all(struct wmGizmo *gz,
struct wmMsgBus *mbus,
struct ARegion *region);
+/**
+ * Auto-key function if auto-key is enabled.
+ */
void WM_gizmo_target_property_anim_autokey(struct bContext *C,
const struct wmGizmo *gz,
struct wmGizmoProperty *gz_prop);
@@ -256,6 +333,7 @@ struct wmKeyMap *WM_gizmogroup_setup_keymap_generic_maybe_drag(const struct wmGi
struct wmKeyConfig *kc);
/* Utility functions (not callbacks). */
+
struct wmKeyMap *WM_gizmo_keymap_generic_with_keyconfig(struct wmKeyConfig *kc);
struct wmKeyMap *WM_gizmo_keymap_generic(struct wmWindowManager *wm);
@@ -268,19 +346,29 @@ struct wmKeyMap *WM_gizmo_keymap_generic_drag(struct wmWindowManager *wm);
struct wmKeyMap *WM_gizmo_keymap_generic_click_drag_with_keyconfig(struct wmKeyConfig *kc);
struct wmKeyMap *WM_gizmo_keymap_generic_click_drag(struct wmWindowManager *wm);
+/**
+ * Drag or press depending on preference.
+ */
struct wmKeyMap *WM_gizmo_keymap_generic_maybe_drag_with_keyconfig(struct wmKeyConfig *kc);
struct wmKeyMap *WM_gizmo_keymap_generic_maybe_drag(struct wmWindowManager *wm);
void WM_gizmogroup_ensure_init(const struct bContext *C, struct wmGizmoGroup *gzgroup);
/* Sort utilities for use with 'BLI_listbase_sort'. */
+
int WM_gizmo_cmp_temp_fl(const void *gz_a_ptr, const void *gz_b_ptr);
int WM_gizmo_cmp_temp_fl_reverse(const void *gz_a_ptr, const void *gz_b_ptr);
/* -------------------------------------------------------------------- */
/* wmGizmoMap */
+/**
+ * Creates a gizmo-map with all registered gizmos for that type
+ */
struct wmGizmoMap *WM_gizmomap_new_from_type(const struct wmGizmoMapType_Params *gzmap_params);
+/**
+ * Re-create the gizmos (use when changing theme settings).
+ */
void WM_gizmomap_reinit(struct wmGizmoMap *gzmap);
const struct ListBase *WM_gizmomap_group_list(struct wmGizmoMap *gzmap);
struct wmGizmoGroup *WM_gizmomap_group_find(struct wmGizmoMap *gzmap, const char *idname);
@@ -298,6 +386,12 @@ void WM_gizmomap_draw(struct wmGizmoMap *gzmap,
const struct bContext *C,
const eWM_GizmoFlagMapDrawStep drawstep);
void WM_gizmomap_add_handlers(struct ARegion *region, struct wmGizmoMap *gzmap);
+/**
+ * Select/Deselect all selectable gizmos in \a gzmap.
+ * \return if selection has changed.
+ *
+ * TODO: select all by type.
+ */
bool WM_gizmomap_select_all(struct bContext *C, struct wmGizmoMap *gzmap, const int action);
bool WM_gizmomap_cursor_set(const struct wmGizmoMap *gzmap, struct wmWindow *win);
void WM_gizmomap_message_subscribe(const struct bContext *C,
@@ -305,6 +399,9 @@ void WM_gizmomap_message_subscribe(const struct bContext *C,
struct ARegion *region,
struct wmMsgBus *mbus);
bool WM_gizmomap_is_any_selected(const struct wmGizmoMap *gzmap);
+/**
+ * \note We could use a callback to define bounds, for now just use matrix location.
+ */
bool WM_gizmomap_minmax(const struct wmGizmoMap *gzmap,
bool use_hidden,
bool use_select,
@@ -327,6 +424,10 @@ struct wmGizmoGroupTypeRef *WM_gizmomaptype_group_find(struct wmGizmoMapType *gz
const char *idname);
struct wmGizmoGroupTypeRef *WM_gizmomaptype_group_find_ptr(struct wmGizmoMapType *gzmap_type,
const struct wmGizmoGroupType *gzgt);
+/**
+ * Use this for registering gizmos on startup.
+ * For runtime, use #WM_gizmomaptype_group_link_runtime.
+ */
struct wmGizmoGroupTypeRef *WM_gizmomaptype_group_link(struct wmGizmoMapType *gzmap_type,
const char *idname);
struct wmGizmoGroupTypeRef *WM_gizmomaptype_group_link_ptr(struct wmGizmoMapType *gzmap_type,
@@ -345,6 +446,9 @@ void WM_gizmomaptype_group_unlink(struct bContext *C,
struct wmGizmoMapType *gzmap_type,
const struct wmGizmoGroupType *gzgt);
+/**
+ * Unlike #WM_gizmomaptype_group_unlink this doesn't maintain correct state, simply free.
+ */
void WM_gizmomaptype_group_free(struct wmGizmoGroupTypeRef *gzgt);
/* -------------------------------------------------------------------- */
@@ -362,6 +466,9 @@ bool WM_gizmo_group_type_ensure_ptr_ex(struct wmGizmoGroupType *gzgt,
bool WM_gizmo_group_type_ensure_ptr(struct wmGizmoGroupType *gzgt);
bool WM_gizmo_group_type_ensure(const char *idname);
+/**
+ * Call #WM_gizmo_group_type_free_ptr after to remove & free.
+ */
void WM_gizmo_group_type_remove_ptr_ex(struct Main *bmain,
struct wmGizmoGroupType *gzgt,
struct wmGizmoMapType *gzmap_type);
@@ -380,7 +487,9 @@ void WM_gizmo_group_unlink_delayed_ptr_from_space(struct wmGizmoGroupType *gzgt,
void WM_gizmo_group_type_free_ptr(wmGizmoGroupType *gzgt);
bool WM_gizmo_group_type_free(const char *idname);
-/* Has the result of unlinking and linking (re-initializes gizmo's). */
+/**
+ * Has the result of unlinking and linking (re-initializes gizmo's).
+ */
void WM_gizmo_group_type_reinit_ptr_ex(struct Main *bmain,
struct wmGizmoGroupType *gzgt,
struct wmGizmoMapType *gzmap_type);
@@ -388,6 +497,7 @@ void WM_gizmo_group_type_reinit_ptr(struct Main *bmain, struct wmGizmoGroupType
void WM_gizmo_group_type_reinit(struct Main *bmain, const char *idname);
/* Utilities */
+
bool WM_gizmo_context_check_drawstep(const struct bContext *C, eWM_GizmoFlagMapDrawStep step);
void WM_gizmo_group_remove_by_tool(struct bContext *C,
@@ -398,6 +508,7 @@ void WM_gizmo_group_remove_by_tool(struct bContext *C,
void WM_gizmo_group_tag_remove(struct wmGizmoGroup *gzgroup);
/* Wrap Group Type Callbacks. */
+
bool WM_gizmo_group_type_poll(const struct bContext *C, const struct wmGizmoGroupType *gzgt);
void WM_gizmo_group_refresh(const struct bContext *C, struct wmGizmoGroup *gzgroup);
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo.c
index cfedd67b2f0..d4f11c79d46 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo.c
@@ -106,11 +106,6 @@ wmGizmo *WM_gizmo_new_ptr(const wmGizmoType *gzt, wmGizmoGroup *gzgroup, Pointer
return gz;
}
-/**
- * \param idname: Must be a valid gizmo type name,
- * if you need to check it exists use #WM_gizmo_new_ptr
- * because callers of this function don't NULL check the return value.
- */
wmGizmo *WM_gizmo_new(const char *idname, wmGizmoGroup *gzgroup, PointerRNA *properties)
{
const wmGizmoType *gzt = WM_gizmotype_find(idname, false);
@@ -143,11 +138,6 @@ static void wm_gizmo_register(wmGizmoGroup *gzgroup, wmGizmo *gz)
wm_gizmogroup_gizmo_register(gzgroup, gz);
}
-/**
- * \warning this doesn't check #wmGizmoMap (highlight, selection etc).
- * Typical use is when freeing the windowing data,
- * where caller can manage clearing selection, highlight... etc.
- */
void WM_gizmo_free(wmGizmo *gz)
{
if (gz->type->free != NULL) {
@@ -187,10 +177,6 @@ void WM_gizmo_free(wmGizmo *gz)
MEM_freeN(gz);
}
-/**
- * Free \a gizmo and unlink from \a gizmolist.
- * \a gizmolist is allowed to be NULL.
- */
void WM_gizmo_unlink(ListBase *gizmolist, wmGizmoMap *gzmap, wmGizmo *gz, bContext *C)
{
if (gz->state & WM_GIZMO_STATE_HIGHLIGHT) {
@@ -300,9 +286,6 @@ static void wm_gizmo_set_matrix_rotation_from_yz_axis__internal(float matrix[4][
normalize_v3(matrix[0]);
}
-/**
- * wmGizmo.matrix utils.
- */
void WM_gizmo_set_matrix_rotation_from_z_axis(wmGizmo *gz, const float z_axis[3])
{
wm_gizmo_set_matrix_rotation_from_z_axis__internal(gz->matrix_basis, z_axis);
@@ -318,9 +301,6 @@ void WM_gizmo_set_matrix_location(wmGizmo *gz, const float origin[3])
copy_v3_v3(gz->matrix_basis[3], origin);
}
-/**
- * wmGizmo.matrix_offset utils.
- */
void WM_gizmo_set_matrix_offset_rotation_from_z_axis(wmGizmo *gz, const float z_axis[3])
{
wm_gizmo_set_matrix_rotation_from_z_axis__internal(gz->matrix_offset, z_axis);
@@ -388,12 +368,7 @@ void WM_gizmo_set_fn_custom_modal(struct wmGizmo *gz, wmGizmoFnModal fn)
/** \} */
/* -------------------------------------------------------------------- */
-/**
- * Add/Remove \a gizmo to selection.
- * Reallocates memory for selected gizmos so better not call for selecting multiple ones.
- *
- * \return if the selection has changed.
- */
+
bool wm_gizmo_select_set_ex(
wmGizmoMap *gzmap, wmGizmo *gz, bool select, bool use_array, bool use_callback)
{
@@ -429,7 +404,6 @@ bool wm_gizmo_select_set_ex(
return changed;
}
-/* Remove from selection array without running callbacks. */
bool WM_gizmo_select_unlink(wmGizmoMap *gzmap, wmGizmo *gz)
{
return wm_gizmo_select_set_ex(gzmap, gz, false, true, false);
@@ -454,12 +428,6 @@ bool wm_gizmo_select_and_highlight(bContext *C, wmGizmoMap *gzmap, wmGizmo *gz)
return false;
}
-/**
- * Special function to run from setup so gizmos start out interactive.
- *
- * We could do this when linking them,
- * but this complicates things since the window update code needs to run first.
- */
void WM_gizmo_modal_set_from_setup(struct wmGizmoMap *gzmap,
struct bContext *C,
struct wmGizmo *gz,
@@ -634,8 +602,6 @@ void WM_gizmo_properties_create(PointerRNA *ptr, const char *gtstring)
}
}
-/* similar to the function above except its uses ID properties
- * used for keymaps and macros */
void WM_gizmo_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *gtstring)
{
if (*properties == NULL) {
@@ -680,14 +646,6 @@ void WM_gizmo_properties_sanitize(PointerRNA *ptr, const bool no_context)
RNA_STRUCT_END;
}
-/**
- * Set all props to their default.
- *
- * \param do_update: Only update un-initialized props.
- *
- * \note There's nothing specific to gizmos here.
- * This could be made a general function.
- */
bool WM_gizmo_properties_default(PointerRNA *ptr, const bool do_update)
{
bool changed = false;
@@ -715,7 +673,6 @@ bool WM_gizmo_properties_default(PointerRNA *ptr, const bool do_update)
return changed;
}
-/* remove all props without PROP_SKIP_SAVE */
void WM_gizmo_properties_reset(wmGizmo *gz)
{
if (gz->ptr->data) {
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
index b6d759eb95f..6f10e4f3f0d 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
@@ -63,9 +63,6 @@
/** \name wmGizmoGroup
* \{ */
-/**
- * Create a new gizmo-group from \a gzgt.
- */
wmGizmoGroup *wm_gizmogroup_new_from_type(wmGizmoMap *gzmap, wmGizmoGroupType *gzgt)
{
wmGizmoGroup *gzgroup = MEM_callocN(sizeof(*gzgroup), "gizmo-group");
@@ -148,9 +145,6 @@ void WM_gizmo_group_tag_remove(wmGizmoGroup *gzgroup)
}
}
-/**
- * Add \a gizmo to \a gzgroup and make sure its name is unique within the group.
- */
void wm_gizmogroup_gizmo_register(wmGizmoGroup *gzgroup, wmGizmo *gz)
{
BLI_assert(BLI_findindex(&gzgroup->gizmos, gz) == -1);
@@ -234,10 +228,6 @@ wmGizmo *wm_gizmogroup_find_intersected_gizmo(wmWindowManager *wm,
return NULL;
}
-/**
- * Adds all gizmos of \a gzgroup that can be selected to the head of \a listbase.
- * Added items need freeing!
- */
void wm_gizmogroup_intersectable_gizmos_to_list(wmWindowManager *wm,
const wmGizmoGroup *gzgroup,
const int event_modifier,
@@ -345,10 +335,9 @@ bool wm_gizmogroup_is_any_selected(const wmGizmoGroup *gzgroup)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Gizmo operators
+/** \name Gizmo Operators
*
* Basic operators for gizmo interaction with user configurable keymaps.
- *
* \{ */
static int gizmo_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
@@ -641,8 +630,6 @@ void GIZMOGROUP_OT_gizmo_tweak(wmOperatorType *ot)
#endif
}
-/** \} */
-
wmKeyMap *wm_gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
@@ -774,11 +761,12 @@ wmKeyMap *WM_gizmogroup_setup_keymap_generic_select(const wmGizmoGroupType *UNUS
return WM_gizmogroup_keymap_template_select_ex(kc, "Generic Gizmo Select", &params);
}
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name wmGizmo (Key-map access)
*
* Key config version so these can be called from #wmGizmoGroupFnSetupKeymap.
- *
* \{ */
struct wmKeyMap *WM_gizmo_keymap_generic_with_keyconfig(wmKeyConfig *kc)
@@ -821,7 +809,6 @@ struct wmKeyMap *WM_gizmo_keymap_generic_click_drag(wmWindowManager *wm)
return WM_gizmo_keymap_generic_click_drag_with_keyconfig(wm->defaultconf);
}
-/** Drag or press depending on preference. */
struct wmKeyMap *WM_gizmo_keymap_generic_maybe_drag_with_keyconfig(wmKeyConfig *kc)
{
const char *idname = "Generic Gizmo Maybe Drag";
@@ -862,10 +849,6 @@ struct wmGizmoGroupTypeRef *WM_gizmomaptype_group_find(struct wmGizmoMapType *gz
return NULL;
}
-/**
- * Use this for registering gizmos on startup.
- * For runtime, use #WM_gizmomaptype_group_link_runtime.
- */
wmGizmoGroupTypeRef *WM_gizmomaptype_group_link(wmGizmoMapType *gzmap_type, const char *idname)
{
wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
@@ -939,9 +922,6 @@ wmGizmoGroup *WM_gizmomaptype_group_init_runtime_with_region(wmGizmoMapType *gzm
return gzgroup;
}
-/**
- * Unlike #WM_gizmomaptype_group_unlink this doesn't maintain correct state, simply free.
- */
void WM_gizmomaptype_group_free(wmGizmoGroupTypeRef *gzgt_ref)
{
MEM_freeN(gzgt_ref);
@@ -1017,7 +997,6 @@ void wm_gizmogrouptype_setup_keymap(wmGizmoGroupType *gzgt, wmKeyConfig *keyconf
* but for general purpose API this is too detailed & annoying.
*
* \note We may want to return a value if there is nothing to remove.
- *
* \{ */
void WM_gizmo_group_type_add_ptr_ex(wmGizmoGroupType *gzgt, wmGizmoMapType *gzmap_type)
@@ -1059,9 +1038,6 @@ bool WM_gizmo_group_type_ensure(const char *idname)
return WM_gizmo_group_type_ensure_ptr(gzgt);
}
-/**
- * Call #WM_gizmo_group_type_free_ptr after to remove & free.
- */
void WM_gizmo_group_type_remove_ptr_ex(struct Main *bmain,
wmGizmoGroupType *gzgt,
wmGizmoMapType *gzmap_type)
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c
index 6a793d52f74..0a36068bb21 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c
@@ -71,7 +71,6 @@ wmGizmoGroupType *WM_gizmogrouptype_find(const char *idname, bool quiet)
return NULL;
}
-/* caller must free */
void WM_gizmogrouptype_iter(GHashIterator *ghi)
{
BLI_ghashIterator_init(ghi, global_gizmogrouptype_hash);
@@ -127,10 +126,6 @@ wmGizmoGroupType *WM_gizmogrouptype_append_ptr(void (*wtfunc)(struct wmGizmoGrou
return gzgt;
}
-/**
- * Append and insert into a gizmo typemap.
- * This is most common for C gizmos which are enabled by default.
- */
wmGizmoGroupTypeRef *WM_gizmogrouptype_append_and_link(wmGizmoMapType *gzmap_type,
void (*wtfunc)(struct wmGizmoGroupType *))
{
@@ -190,7 +185,6 @@ void wm_gizmogrouptype_free(void)
global_gizmogrouptype_hash = NULL;
}
-/* called on initialize WM_init() */
void wm_gizmogrouptype_init(void)
{
/* reserve size is set based on blender default setup */
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
index dd2db209771..b6912d79076 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
@@ -29,6 +29,12 @@ struct wmKeyConfig;
/* -------------------------------------------------------------------- */
/* wmGizmo */
+/**
+ * Add/Remove \a gizmo to selection.
+ * Reallocates memory for selected gizmos so better not call for selecting multiple ones.
+ *
+ * \return if the selection has changed.
+ */
bool wm_gizmo_select_set_ex(
struct wmGizmoMap *gzmap, struct wmGizmo *gz, bool select, bool use_array, bool use_callback);
bool wm_gizmo_select_and_highlight(bContext *C, struct wmGizmoMap *gzmap, struct wmGizmo *gz);
@@ -54,9 +60,15 @@ enum {
TWEAK_MODAL_SNAP_OFF,
};
+/**
+ * Create a new gizmo-group from \a gzgt.
+ */
struct wmGizmoGroup *wm_gizmogroup_new_from_type(struct wmGizmoMap *gzmap,
struct wmGizmoGroupType *gzgt);
void wm_gizmogroup_free(bContext *C, struct wmGizmoGroup *gzgroup);
+/**
+ * Add \a gizmo to \a gzgroup and make sure its name is unique within the group.
+ */
void wm_gizmogroup_gizmo_register(struct wmGizmoGroup *gzgroup, struct wmGizmo *gz);
struct wmGizmoGroup *wm_gizmogroup_find_by_type(const struct wmGizmoMap *gzmap,
const struct wmGizmoGroupType *gzgt);
@@ -66,6 +78,10 @@ struct wmGizmo *wm_gizmogroup_find_intersected_gizmo(wmWindowManager *wm,
const int event_modifier,
const int mval[2],
int *r_part);
+/**
+ * Adds all gizmos of \a gzgroup that can be selected to the head of \a listbase.
+ * Added items need freeing!
+ */
void wm_gizmogroup_intersectable_gizmos_to_list(wmWindowManager *wm,
const struct wmGizmoGroup *gzgroup,
const int event_modifier,
@@ -137,6 +153,10 @@ struct wmGizmoMapType {
};
void wm_gizmomap_select_array_clear(struct wmGizmoMap *gzmap);
+/**
+ * Deselect all selected gizmos in \a gzmap.
+ * \return if selection has changed.
+ */
bool wm_gizmomap_deselect_all(struct wmGizmoMap *gzmap);
void wm_gizmomap_select_array_shrink(struct wmGizmoMap *gzmap, int len_subtract);
void wm_gizmomap_select_array_push_back(struct wmGizmoMap *gzmap, wmGizmo *gz);
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
index 6f952bc9526..d3e682f1490 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
@@ -176,9 +176,6 @@ static wmGizmoMap *wm_gizmomap_new_from_type_ex(struct wmGizmoMapType *gzmap_typ
return gzmap;
}
-/**
- * Creates a gizmo-map with all registered gizmos for that type
- */
wmGizmoMap *WM_gizmomap_new_from_type(const struct wmGizmoMapType_Params *gzmap_params)
{
wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(gzmap_params);
@@ -207,7 +204,6 @@ void wm_gizmomap_remove(wmGizmoMap *gzmap)
MEM_freeN(gzmap);
}
-/** Re-create the gizmos (use when changing theme settings). */
void WM_gizmomap_reinit(wmGizmoMap *gzmap)
{
wmGizmoMapType *gzmap_type = gzmap->type;
@@ -246,9 +242,6 @@ bool WM_gizmomap_is_any_selected(const wmGizmoMap *gzmap)
return gzmap->gzmap_context.select.len != 0;
}
-/**
- * \note We could use a callback to define bounds, for now just use matrix location.
- */
bool WM_gizmomap_minmax(const wmGizmoMap *gzmap,
bool UNUSED(use_hidden),
bool use_select,
@@ -713,10 +706,6 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C,
return result;
}
-/**
- * Try to find a gizmo under the mouse position. 2D intersections have priority over
- * 3D ones (could check for smallest screen-space distance but not needed right now).
- */
wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap,
bContext *C,
const wmEvent *event,
@@ -843,10 +832,6 @@ void wm_gizmomaps_handled_modal_update(bContext *C, wmEvent *event, wmEventHandl
CTX_wm_region_set(C, region);
}
-/**
- * Deselect all selected gizmos in \a gzmap.
- * \return if selection has changed.
- */
bool wm_gizmomap_deselect_all(wmGizmoMap *gzmap)
{
wmGizmoMapSelectState *msel = &gzmap->gzmap_context.select;
@@ -903,12 +888,6 @@ static bool wm_gizmomap_select_all_intern(bContext *C, wmGizmoMap *gzmap)
return changed;
}
-/**
- * Select/Deselect all selectable gizmos in \a gzmap.
- * \return if selection has changed.
- *
- * TODO: select all by type.
- */
bool WM_gizmomap_select_all(bContext *C, wmGizmoMap *gzmap, const int action)
{
bool changed = false;
@@ -932,10 +911,6 @@ bool WM_gizmomap_select_all(bContext *C, wmGizmoMap *gzmap, const int action)
return changed;
}
-/**
- * Prepare context for gizmo handling (but only if area/region is
- * part of screen). Version of #wm_handler_op_context for gizmos.
- */
void wm_gizmomap_handler_context_op(bContext *C, wmEventHandler_Op *handler)
{
bScreen *screen = CTX_wm_screen(C);
@@ -1037,9 +1012,6 @@ wmGizmo *wm_gizmomap_highlight_get(wmGizmoMap *gzmap)
return gzmap->gzmap_context.highlight;
}
-/**
- * Caller should call exit when (enable == False).
- */
void wm_gizmomap_modal_set(
wmGizmoMap *gzmap, bContext *C, wmGizmo *gz, const wmEvent *event, bool enable)
{
@@ -1247,9 +1219,6 @@ void wm_gizmomaptypes_free(void)
}
}
-/**
- * Initialize keymaps for all existing gizmo-groups
- */
void wm_gizmos_keymap(wmKeyConfig *keyconf)
{
LISTBASE_FOREACH (wmGizmoMapType *, gzmap_type, &gizmomaptypes) {
@@ -1293,10 +1262,6 @@ void WM_gizmoconfig_update_tag_group_remove(wmGizmoMap *gzmap)
wm_gzmap_type_update_flag |= WM_GIZMOTYPE_GLOBAL_UPDATE_REMOVE;
}
-/**
- * Run in case new types have been added (runs often, early exit where possible).
- * Follows #WM_keyconfig_update conventions.
- */
void WM_gizmoconfig_update(struct Main *bmain)
{
if (G.background) {
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c
index 63e833d73c3..57555fb5416 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c
@@ -319,10 +319,6 @@ void WM_gizmo_do_msg_notify_tag_refresh(bContext *UNUSED(C),
WM_gizmomap_tag_refresh(gzmap);
}
-/**
- * Runs on the "prepare draw" pass,
- * drawing the region clears.
- */
void WM_gizmo_target_property_subscribe_all(wmGizmo *gz, struct wmMsgBus *mbus, ARegion *region)
{
if (gz->type->target_property_defs_len) {
@@ -355,9 +351,6 @@ void WM_gizmo_target_property_subscribe_all(wmGizmo *gz, struct wmMsgBus *mbus,
}
}
-/**
- * Auto-key function if auto-key is enabled.
- */
void WM_gizmo_target_property_anim_autokey(bContext *C,
const wmGizmo *UNUSED(gz),
wmGizmoProperty *gz_prop)
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_type.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_type.c
index 1523246d08b..602100a624e 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_type.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_type.c
@@ -78,7 +78,6 @@ const wmGizmoType *WM_gizmotype_find(const char *idname, bool quiet)
return NULL;
}
-/* caller must free */
void WM_gizmotype_iter(GHashIterator *ghi)
{
BLI_ghashIterator_init(ghi, global_gizmotype_hash);
@@ -118,9 +117,6 @@ void WM_gizmotype_append_ptr(void (*gtfunc)(struct wmGizmoType *, void *), void
wm_gizmotype_append__end(mt);
}
-/**
- * Free but don't remove from ghash.
- */
void WM_gizmotype_free_ptr(wmGizmoType *gzt)
{
if (gzt->rna_ext.srna) { /* python gizmo, allocs own string */
@@ -195,7 +191,6 @@ void wm_gizmotype_free(void)
global_gizmotype_hash = NULL;
}
-/* called on initialize WM_init() */
void wm_gizmotype_init(void)
{
/* reserve size is set based on blender default setup */
diff --git a/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h b/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h
index 18b3f40aba6..0612ba97db0 100644
--- a/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h
+++ b/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h
@@ -40,37 +40,63 @@ extern "C" {
#endif
/* -------------------------------------------------------------------- */
-/* wmGizmo */
+/** \name #wmGizmo
+ * \{ */
/* wm_gizmo_type.c, for init/exit */
+
void wm_gizmotype_free(void);
+/**
+ * Called on initialize #WM_init().
+ */
void wm_gizmotype_init(void);
/* wm_gizmogroup_type.c, for init/exit */
+
void wm_gizmogrouptype_free(void);
+/**
+ * Called on initialize #WM_init().
+ */
void wm_gizmogrouptype_init(void);
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* wmGizmoGroup */
+/** \name #wmGizmoGroup
+ * \{ */
void GIZMOGROUP_OT_gizmo_select(struct wmOperatorType *ot);
void GIZMOGROUP_OT_gizmo_tweak(struct wmOperatorType *ot);
bool wm_gizmogroup_is_any_selected(const struct wmGizmoGroup *gzgroup);
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* wmGizmoMap */
+/** \name #wmGizmoMap
+ * \{ */
void wm_gizmomap_remove(struct wmGizmoMap *gzmap);
+/**
+ * Initialize key-maps for all existing gizmo-groups
+ */
void wm_gizmos_keymap(struct wmKeyConfig *keyconf);
void wm_gizmomaps_handled_modal_update(bContext *C,
struct wmEvent *event,
struct wmEventHandler_Op *handler);
+/**
+ * Prepare context for gizmo handling (but only if area/region is
+ * part of screen). Version of #wm_handler_op_context for gizmos.
+ */
void wm_gizmomap_handler_context_op(bContext *C, struct wmEventHandler_Op *handler);
void wm_gizmomap_handler_context_gizmo(bContext *C, struct wmEventHandler_Gizmo *handler);
+/**
+ * Try to find a gizmo under the mouse position. 2D intersections have priority over
+ * 3D ones (could check for smallest screen-space distance but not needed right now).
+ */
struct wmGizmo *wm_gizmomap_highlight_find(struct wmGizmoMap *gzmap,
bContext *C,
const struct wmEvent *event,
@@ -80,6 +106,9 @@ bool wm_gizmomap_highlight_set(struct wmGizmoMap *gzmap,
struct wmGizmo *gz,
int part);
struct wmGizmo *wm_gizmomap_highlight_get(struct wmGizmoMap *gzmap);
+/**
+ * Caller should call exit when (enable == False).
+ */
void wm_gizmomap_modal_set(struct wmGizmoMap *gzmap,
bContext *C,
struct wmGizmo *gz,
@@ -90,11 +119,16 @@ struct wmGizmo *wm_gizmomap_modal_get(struct wmGizmoMap *gzmap);
struct wmGizmo **wm_gizmomap_selected_get(wmGizmoMap *gzmap, int *r_selected_len);
struct ListBase *wm_gizmomap_groups_get(wmGizmoMap *gzmap);
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* wmGizmoMapType */
+/** \name #wmGizmoMapType
+ * \{ */
void wm_gizmomaptypes_free(void);
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 47ee296823b..40f8da63e11 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -272,6 +272,7 @@ IDTypeInfo IDType_ID_WM = {
.name_plural = "window_managers",
.translation_context = BLT_I18NCONTEXT_ID_WINDOWMANAGER,
.flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_LIBLINKING | IDTYPE_FLAGS_NO_ANIMDATA,
+ .asset_type_info = NULL,
.init_data = NULL,
.copy_data = NULL,
@@ -279,6 +280,7 @@ IDTypeInfo IDType_ID_WM = {
.make_local = NULL,
.foreach_id = window_manager_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = window_manager_blend_write,
@@ -339,13 +341,6 @@ void WM_operator_free_all_after(wmWindowManager *wm, struct wmOperator *op)
}
}
-/**
- * Use with extreme care!,
- * properties, custom-data etc - must be compatible.
- *
- * \param op: Operator to assign the type to.
- * \param ot: Operator type to assign.
- */
void WM_operator_type_set(wmOperator *op, wmOperatorType *ot)
{
/* Not supported for Python. */
@@ -375,8 +370,6 @@ static void wm_reports_free(wmWindowManager *wm)
WM_event_remove_timer(wm, NULL, wm->reports.reporttimer);
}
-/* All operations get registered in the windowmanager here. */
-/* Called on event handling by event_system.c. */
void wm_operator_register(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -413,10 +406,6 @@ void WM_operator_stack_clear(wmWindowManager *wm)
WM_main_add_notifier(NC_WM | ND_HISTORY, NULL);
}
-/**
- * This function is needed in the case when an addon id disabled
- * while a modal operator it defined is running.
- */
void WM_operator_handlers_clear(wmWindowManager *wm, wmOperatorType *ot)
{
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
@@ -549,7 +538,6 @@ void wm_clear_default_size(bContext *C)
}
}
-/* On startup, it adds all data, for matching. */
void wm_add_default(Main *bmain, bContext *C)
{
wmWindowManager *wm = BKE_libblock_alloc(bmain, ID_WM, "WinMan", 0);
@@ -571,7 +559,6 @@ void wm_add_default(Main *bmain, bContext *C)
wm_window_make_drawable(wm, win);
}
-/* Context is allowed to be NULL, do not free wm itself (lib_id.c). */
void wm_close_and_free(bContext *C, wmWindowManager *wm)
{
if (wm->autosavetimer) {
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 9c020b16234..74ec2bcd41f 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -222,7 +222,6 @@ void WM_cursor_modal_restore(wmWindow *win)
win->lastcursor = 0;
}
-/* to allow usage all over, we do entire WM */
void WM_cursor_wait(bool val)
{
if (!G.background) {
@@ -240,9 +239,6 @@ void WM_cursor_wait(bool val)
}
}
-/**
- * \param bounds: can be NULL
- */
void WM_cursor_grab_enable(wmWindow *win, int wrap, bool hide, int bounds[4])
{
/* Only grab cursor when not running debug.
@@ -307,9 +303,10 @@ static void wm_cursor_warp_relative(wmWindow *win, int x, int y)
WM_cursor_warp(win, cx + x, cy + y);
}
-/* give it a modal keymap one day? */
bool wm_cursor_arrow_move(wmWindow *win, const wmEvent *event)
{
+ /* TODO: give it a modal keymap? Hard coded for now */
+
if (win && event->val == KM_PRESS) {
/* Must move at least this much to avoid rounding in WM_cursor_warp. */
float fac = GHOST_GetNativePixelSize(win->ghostwin);
@@ -334,7 +331,6 @@ bool wm_cursor_arrow_move(wmWindow *win, const wmEvent *event)
return 0;
}
-/* after this you can call restore too */
void WM_cursor_time(wmWindow *win, int nr)
{
/* 10 8x8 digits */
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index bc87347b2f3..e1017c4236e 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -89,7 +89,6 @@ typedef struct wmDropBoxMap {
} wmDropBoxMap;
-/* spaceid/regionid is zero for window drop maps */
ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid)
{
LISTBASE_FOREACH (wmDropBoxMap *, dm, &dropboxes) {
@@ -153,7 +152,6 @@ void wm_dropbox_free(void)
/* *********************************** */
-/* note that the pointer should be valid allocated and not on stack */
wmDrag *WM_event_start_drag(
struct bContext *C, int icon, int type, void *poin, double value, unsigned int flags)
{
@@ -208,11 +206,6 @@ wmDrag *WM_event_start_drag(
return drag;
}
-/**
- * Additional work to cleanly end dragging. Additional because this doesn't actually remove the
- * drag items. Should be called whenever dragging is stopped (successful or not, also when
- * canceled).
- */
void wm_drags_exit(wmWindowManager *wm, wmWindow *win)
{
bool any_active = false;
@@ -403,7 +396,6 @@ void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop)
wm_drags_exit(CTX_wm_manager(C), CTX_wm_window(C));
}
-/* called in inner handler loop, region context */
void wm_drags_check_ops(bContext *C, const wmEvent *event)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -424,11 +416,6 @@ 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;
@@ -484,17 +471,11 @@ ID *WM_drag_get_local_ID_from_event(const wmEvent *event, short idcode)
return WM_drag_get_local_ID(lb->first, idcode);
}
-/**
- * Check if the drag data is either a local ID or an external ID asset of type \a idcode.
- */
bool WM_drag_is_ID_type(const wmDrag *drag, int idcode)
{
return WM_drag_get_local_ID(drag, idcode) || WM_drag_get_asset_data(drag, idcode);
}
-/**
- * \note: Does not store \a asset in any way, so it's fine to pass a temporary.
- */
wmDragAsset *WM_drag_create_asset_data(const AssetHandle *asset,
AssetMetaData *metadata,
const char *path,
@@ -542,9 +523,6 @@ struct AssetMetaData *WM_drag_get_asset_meta_data(const wmDrag *drag, int idcode
return NULL;
}
-/**
- * \param flag_extra: Additional linking flags (from #eFileSel_Params_Flag).
- */
ID *WM_drag_asset_id_import(wmDragAsset *asset_drag, const int flag_extra)
{
/* Only support passing in limited flags. */
@@ -603,15 +581,6 @@ bool WM_drag_asset_will_import_linked(const wmDrag *drag)
return asset_drag->import_type == FILE_ASSET_IMPORT_LINK;
}
-/**
- * When dragging a local ID, return that. Otherwise, if dragging an asset-handle, link or append
- * that depending on what was chosen by the drag-box (currently append only in fact).
- *
- * Use #WM_drag_free_imported_drag_ID() as cancel callback of the drop-box, so that the asset
- * import is rolled back if the drop operator fails.
- *
- * \param flag: #eFileSel_Params_Flag passed to linking code.
- */
ID *WM_drag_get_local_ID_or_import_from_asset(const wmDrag *drag, int idcode)
{
if (!ELEM(drag->type, WM_DRAG_ASSET, WM_DRAG_ID)) {
@@ -631,14 +600,6 @@ ID *WM_drag_get_local_ID_or_import_from_asset(const wmDrag *drag, int idcode)
return WM_drag_asset_id_import(asset_drag, 0);
}
-/**
- * \brief Free asset ID imported for canceled drop.
- *
- * If the asset was imported (linked/appended) using #WM_drag_get_local_ID_or_import_from_asset()`
- * (typically via a #wmDropBox.copy() callback), we want the ID to be removed again if the drop
- * operator cancels.
- * This is for use as #wmDropBox.cancel() callback.
- */
void WM_drag_free_imported_drag_ID(struct Main *bmain, wmDrag *drag, wmDropBox *drop)
{
if (drag->type != WM_DRAG_ASSET) {
@@ -673,9 +634,6 @@ wmDragAssetCatalog *WM_drag_get_asset_catalog_data(const wmDrag *drag)
return drag->poin;
}
-/**
- * \note: Does not store \a asset in any way, so it's fine to pass a temporary.
- */
void WM_drag_add_asset_list_item(
wmDrag *drag,
/* Context only needed for the hack in #ED_asset_handle_get_full_library_path(). */
@@ -912,7 +870,6 @@ void WM_drag_draw_default_fn(bContext *C, wmWindow *win, wmDrag *drag, const int
wm_drag_draw_default(C, win, drag, xy);
}
-/* Called in #wm_draw_window_onscreen. */
void wm_drags_draw(bContext *C, wmWindow *win)
{
int xy[2];
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index d8d57a9370c..ab9de6ce4d4 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -148,6 +148,7 @@ static void wm_region_draw_overlay(bContext *C, ScrArea *area, ARegion *region)
}
/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Internal Utilities
* \{ */
diff --git a/source/blender/windowmanager/intern/wm_event_query.c b/source/blender/windowmanager/intern/wm_event_query.c
index ef733837bf7..22cd68ddbd7 100644
--- a/source/blender/windowmanager/intern/wm_event_query.c
+++ b/source/blender/windowmanager/intern/wm_event_query.c
@@ -71,7 +71,6 @@ static void event_ids_from_type_and_value(const short type,
}
}
-/* for debugging only, getting inspecting events manually is tedious */
void WM_event_print(const wmEvent *event)
{
if (event) {
@@ -218,7 +217,6 @@ bool WM_event_type_mask_test(const int event_type, const enum eEventType_Mask ma
/** \name Event Motion Queries
* \{ */
-/* for modal callbacks, check configuration for how to interpret exit with tweaks. */
bool WM_event_is_modal_tweak_exit(const wmEvent *event, int tweak_event)
{
/* if the release-confirm userpref setting is enabled,
@@ -276,20 +274,6 @@ bool WM_event_is_mouse_drag_or_press(const wmEvent *event)
(ISMOUSE_BUTTON(event->type) && (event->val == KM_PRESS));
}
-/**
- * Detect motion between selection (callers should only use this for selection picking),
- * typically mouse press/click events.
- *
- * \param mval: Region relative coordinates, call with (-1, -1) resets the last cursor location.
- * \returns True when there was motion since last called.
- *
- * NOTE(@campbellbarton): The logic used here isn't foolproof.
- * It's possible that users move the cursor past #WM_EVENT_CURSOR_MOTION_THRESHOLD then back to
- * a position within the threshold (between mouse clicks).
- * In practice users never reported this since the threshold is very small (a few pixels).
- * To prevent the unlikely case of values matching from another region,
- * changing regions resets this value to (-1, -1).
- */
bool WM_cursor_test_motion_and_update(const int mval[2])
{
static int mval_prev[2] = {-1, -1};
@@ -360,11 +344,6 @@ int WM_userdef_event_map(int kmitype)
return kmitype;
}
-/**
- * Use so we can check if 'wmEvent.type' is released in modal operators.
- *
- * An alternative would be to add a 'wmEvent.type_nokeymap'... or similar.
- */
int WM_userdef_event_type_from_keymap_type(int kmitype)
{
switch (kmitype) {
@@ -447,7 +426,6 @@ bool WM_event_is_xr(const struct wmEvent *event)
/** \name Event Tablet Input Access
* \{ */
-/* applies the global tablet pressure correction curve */
float wm_pressure_curve(float pressure)
{
if (U.pressure_threshold_max != 0.0f) {
@@ -463,8 +441,6 @@ float wm_pressure_curve(float pressure)
return pressure;
}
-/* if this is a tablet event, return tablet pressure and set *pen_flip
- * to 1 if the eraser tool is being used, 0 otherwise */
float WM_event_tablet_data(const wmEvent *event, int *pen_flip, float tilt[2])
{
if (tilt) {
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index f51c8c48c48..1b6df9fb0db 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -64,6 +64,7 @@
#include "ED_asset.h"
#include "ED_fileselect.h"
#include "ED_info.h"
+#include "ED_render.h"
#include "ED_screen.h"
#include "ED_undo.h"
#include "ED_util.h"
@@ -83,6 +84,7 @@
#include "wm.h"
#include "wm_event_system.h"
#include "wm_event_types.h"
+#include "wm_surface.h"
#include "wm_window.h"
#include "DEG_depsgraph.h"
@@ -287,9 +289,6 @@ void WM_main_add_notifier(unsigned int type, void *reference)
note->reference = reference;
}
-/**
- * Clear notifiers by reference, Used so listeners don't act on freed data.
- */
void WM_main_remove_notifier_reference(const void *reference)
{
Main *bmain = G_MAIN;
@@ -384,13 +383,10 @@ void wm_event_do_depsgraph(bContext *C, bool is_after_open_file)
DEG_make_active(depsgraph);
BKE_scene_graph_update_tagged(depsgraph, bmain);
}
+
+ wm_surfaces_do_depsgraph(C);
}
-/**
- * Was part of #wm_event_do_notifiers,
- * split out so it can be called once before entering the #WM_main loop.
- * This ensures operators don't run before the UI and depsgraph are initialized.
- */
void wm_event_do_refresh_wm_and_depsgraph(bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -427,7 +423,6 @@ static void wm_event_execute_timers(bContext *C)
CTX_wm_window_set(C, NULL);
}
-/* Called in mainloop. */
void wm_event_do_notifiers(bContext *C)
{
/* Run the timer before assigning 'wm' in the unlikely case a timer loads a file, see T80028. */
@@ -457,6 +452,9 @@ void wm_event_do_notifiers(bContext *C)
else if (note->data == ND_DATACHANGED) {
wm_window_title(wm, win);
}
+ else if (note->data == ND_UNDO) {
+ ED_preview_restart_queue_work(C);
+ }
}
if (note->window == win) {
if (note->category == NC_SCREEN) {
@@ -752,9 +750,6 @@ static void wm_event_handler_ui_cancel(bContext *C)
* Access to #wmWindowManager.reports
* \{ */
-/**
- * Show the report in the info header.
- */
void WM_report_banner_show(void)
{
wmWindowManager *wm = G_MAIN->wm.first;
@@ -770,9 +765,6 @@ void WM_report_banner_show(void)
wm_reports->reporttimer->customdata = rti;
}
-/**
- * Hide all currently displayed banners and abort their timer.
- */
void WM_report_banners_cancel(Main *bmain)
{
wmWindowManager *wm = bmain->wm.first;
@@ -855,9 +847,9 @@ bool WM_operator_poll(bContext *C, wmOperatorType *ot)
return true;
}
-/* sets up the new context and calls 'wm_operator_invoke()' with poll_only */
bool WM_operator_poll_context(bContext *C, wmOperatorType *ot, short context)
{
+ /* Sets up the new context and calls #wm_operator_invoke() with poll_only. */
return wm_operator_call_internal(C, ot, NULL, NULL, context, true, NULL);
}
@@ -892,11 +884,6 @@ bool WM_operator_check_ui_empty(wmOperatorType *ot)
return true;
}
-/**
- * Sets the active region for this space from the context.
- *
- * \see #BKE_area_find_region_active_win
- */
void WM_operator_region_active_win_set(bContext *C)
{
ScrArea *area = CTX_wm_area(C);
@@ -1103,13 +1090,6 @@ static int wm_operator_exec_notest(bContext *C, wmOperator *op)
return retval;
}
-/**
- * For running operators with frozen context (modal handlers, menus).
- *
- * \param store: Store settings for re-use.
- *
- * \warning do not use this within an operator to call its self! T29537.
- */
int WM_operator_call_ex(bContext *C, wmOperator *op, const bool store)
{
return wm_operator_exec(C, op, false, store);
@@ -1120,19 +1100,11 @@ int WM_operator_call(bContext *C, wmOperator *op)
return WM_operator_call_ex(C, op, false);
}
-/**
- * This is intended to be used when an invoke operator wants to call exec on its self
- * and is basically like running op->type->exec() directly, no poll checks no freeing,
- * since we assume whoever called invoke will take care of that
- */
int WM_operator_call_notest(bContext *C, wmOperator *op)
{
return wm_operator_exec_notest(C, op);
}
-/**
- * Execute this operator again, put here so it can share above code
- */
int WM_operator_repeat(bContext *C, wmOperator *op)
{
const int op_flag = OP_IS_REPEAT;
@@ -1149,12 +1121,6 @@ int WM_operator_repeat_last(bContext *C, wmOperator *op)
op->flag &= ~op_flag;
return ret;
}
-/**
- * \return true if #WM_operator_repeat can run.
- * Simple check for now but may become more involved.
- * To be sure the operator can run call `WM_operator_poll(C, op->type)` also, since this call
- * checks if #WM_operator_repeat() can run at all, not that it WILL run at any time.
- */
bool WM_operator_repeat_check(const bContext *UNUSED(C), wmOperator *op)
{
if (op->type->exec != NULL) {
@@ -1592,7 +1558,6 @@ static int wm_operator_call_internal(bContext *C,
return 0;
}
-/* Invokes operator in context. */
int WM_operator_name_call_ptr(bContext *C,
wmOperatorType *ot,
wmOperatorCallContext context,
@@ -1614,6 +1579,16 @@ int WM_operator_name_call(bContext *C,
return 0;
}
+bool WM_operator_name_poll(bContext *C, const char *opstring)
+{
+ wmOperatorType *ot = WM_operatortype_find(opstring, 0);
+ if (!ot) {
+ return false;
+ }
+
+ return WM_operator_poll(C, ot);
+}
+
int WM_operator_name_call_with_properties(struct bContext *C,
const char *opstring,
wmOperatorCallContext context,
@@ -1625,9 +1600,6 @@ int WM_operator_name_call_with_properties(struct bContext *C,
return WM_operator_name_call_ptr(C, ot, context, &props_ptr);
}
-/**
- * Call an existent menu. The menu can be created in C or Python.
- */
void WM_menu_name_call(bContext *C, const char *menu_name, short context)
{
wmOperatorType *ot = WM_operatortype_find("WM_OT_call_menu", false);
@@ -1638,13 +1610,6 @@ void WM_menu_name_call(bContext *C, const char *menu_name, short context)
WM_operator_properties_free(&ptr);
}
-/**
- * Similar to #WM_operator_name_call called with #WM_OP_EXEC_DEFAULT context.
- *
- * - #wmOperatorType is used instead of operator name since python already has the operator type.
- * - `poll()` must be called by python before this runs.
- * - reports can be passed to this function (so python can report them as exceptions).
- */
int WM_operator_call_py(bContext *C,
wmOperatorType *ot,
wmOperatorCallContext context,
@@ -1849,9 +1814,9 @@ void WM_operator_name_call_ptr_with_depends_on_cursor(bContext *C,
* General API for different handler types.
* \{ */
-/* Future extra customadata free? */
void wm_event_free_handler(wmEventHandler *handler)
{
+ /* Future extra customa-data free? */
MEM_freeN(handler);
}
@@ -1923,7 +1888,6 @@ static void wm_handler_op_context(bContext *C, wmEventHandler_Op *handler, const
}
}
-/* Called on exit or remove area, only here call cancel callback. */
void WM_event_remove_handlers(bContext *C, ListBase *handlers)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -3525,8 +3489,6 @@ static void wm_event_handle_xrevent(bContext *C,
}
#endif /* WITH_XR_OPENXR */
-/* Called in main loop. */
-/* Goes over entire hierarchy: events -> window -> screen -> area -> region. */
void wm_event_do_handlers(bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -3836,12 +3798,6 @@ void WM_event_fileselect_event(wmWindowManager *wm, void *ophandle, int eventval
/* Operator is supposed to have a filled "path" property. */
/* Optional property: file-type (XXX enum?) */
-/**
- * The idea here is to keep a handler alive on window queue, owning the operator.
- * The file window can send event to make it execute, thus ensuring
- * executing happens outside of lower level queues, with UI refreshed.
- * Should also allow multiwin solutions.
- */
void WM_event_add_fileselect(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -3940,10 +3896,6 @@ wmEventHandler_Op *WM_event_add_modal_handler(bContext *C, wmOperator *op)
return handler;
}
-/**
- * Modal handlers store a pointer to an area which might be freed while the handler runs.
- * Use this function to NULL all handler pointers to \a old_area.
- */
void WM_event_modal_handler_area_replace(wmWindow *win, const ScrArea *old_area, ScrArea *new_area)
{
LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) {
@@ -3958,10 +3910,6 @@ void WM_event_modal_handler_area_replace(wmWindow *win, const ScrArea *old_area,
}
}
-/**
- * Modal handlers store a pointer to a region which might be freed while the handler runs.
- * Use this function to NULL all handler pointers to \a old_region.
- */
void WM_event_modal_handler_region_replace(wmWindow *win,
const ARegion *old_region,
ARegion *new_region)
@@ -4152,7 +4100,6 @@ struct wmEventHandler_Keymap *WM_event_add_keymap_handler_dynamic(
return handler;
}
-/* Priorities not implemented yet, for time being just insert in begin of list. */
wmEventHandler_Keymap *WM_event_add_keymap_handler_priority(ListBase *handlers,
wmKeyMap *keymap,
int UNUSED(priority))
@@ -4259,7 +4206,6 @@ wmEventHandler_UI *WM_event_add_ui_handler(const bContext *C,
return handler;
}
-/* Set "postpone" for win->modalhandlers, this is in a running for () loop in wm_handlers_do(). */
void WM_event_remove_ui_handler(ListBase *handlers,
wmUIHandlerFunc handle_fn,
wmUIHandlerRemoveFunc remove_fn,
@@ -4324,9 +4270,10 @@ wmEventHandler_Dropbox *WM_event_add_dropbox_handler(ListBase *handlers, ListBas
return handler;
}
-/* XXX(ton): solution works, still better check the real cause. */
void WM_event_remove_area_handler(ListBase *handlers, void *area)
{
+ /* XXX(ton): solution works, still better check the real cause. */
+
LISTBASE_FOREACH_MUTABLE (wmEventHandler *, handler_base, handlers) {
if (handler_base->type == WM_HANDLER_TYPE_UI) {
wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base;
@@ -4752,9 +4699,6 @@ static wmEvent *wm_event_add_trackpad(wmWindow *win, const wmEvent *event, int d
return event_new;
}
-/**
- * Windows store own event queues #wmWindow.event_queue (no #bContext here).
- */
void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void *customdata)
{
if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) {
@@ -5372,10 +5316,6 @@ const char *WM_window_cursor_keymap_status_get(const wmWindow *win,
return NULL;
}
-/**
- * Similar to #BKE_screen_area_map_find_area_xy and related functions,
- * use here since the area is stored in the window manager.
- */
ScrArea *WM_window_status_area_find(wmWindow *win, bScreen *screen)
{
if (screen->state == SCREENFULL) {
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index a301b17227d..1d3fa158ac1 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -111,6 +111,7 @@
#include "ED_fileselect.h"
#include "ED_image.h"
#include "ED_outliner.h"
+#include "ED_render.h"
#include "ED_screen.h"
#include "ED_undo.h"
#include "ED_util.h"
@@ -170,9 +171,6 @@ void WM_file_tag_modified(void)
}
}
-/**
- * Check if there is data that would be lost when closing the current file without saving.
- */
bool wm_file_or_session_data_has_unsaved_changes(const Main *bmain, const wmWindowManager *wm)
{
return !wm->file_saved || ED_image_should_save_modified(bmain) ||
@@ -620,6 +618,8 @@ static void wm_file_read_pre(bContext *C, bool use_data, bool UNUSED(use_userdef
/* Always do this as both startup and preferences may have loaded in many font's
* at a different zoom level to the file being loaded. */
UI_view2d_zoom_cache_reset();
+
+ ED_preview_restart_queue_free();
}
/**
@@ -955,16 +955,6 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* #BKE_blendfile_read_result_setup sets new Main into context. */
Main *bmain = CTX_data_main(C);
- /* When recovering a session from an unsaved file, this can have a blank path. */
- if (BKE_main_blendfile_path(bmain)[0] != '\0') {
- G.save_over = 1;
- G.relbase_valid = 1;
- }
- else {
- G.save_over = 0;
- G.relbase_valid = 0;
- }
-
/* match the read WM with current WM */
wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm);
WM_check(C); /* opens window(s), checks keymaps */
@@ -1032,12 +1022,6 @@ static struct {
bool override;
} wm_init_state_app_template = {{0}};
-/**
- * Used for setting app-template from the command line:
- * - non-empty string: overrides.
- * - empty string: override, using no app template.
- * - NULL: clears override.
- */
void WM_init_state_app_template_set(const char *app_template)
{
if (app_template) {
@@ -1061,16 +1045,6 @@ const char *WM_init_state_app_template_get(void)
/** \name Read Startup & Preferences Blend-File API
* \{ */
-/**
- * Called on startup, (context entirely filled with NULLs)
- * or called for 'New File' both `startup.blend` and `userpref.blend` are checked.
- *
- * \param r_params_file_read_post: Support postponed initialization,
- * needed for initial startup when only some sub-systems have been initialized.
- * When non-null, #wm_file_read_post doesn't run, instead it's arguments are stored
- * in this return argument.
- * The caller is responsible for calling #wm_homefile_read_post with this return argument.
- */
void wm_homefile_read_ex(bContext *C,
const struct wmHomeFileRead_Params *params_homefile,
ReportList *reports,
@@ -1167,8 +1141,6 @@ void wm_homefile_read_ex(bContext *C,
wm_file_read_pre(C, use_data, use_userdef);
if (use_data) {
- G.relbase_valid = 0;
-
/* put aside screens to match with persistent windows later */
wm_window_match_init(C, &wmbase);
}
@@ -1372,10 +1344,7 @@ void wm_homefile_read_ex(bContext *C,
if (use_data) {
WM_check(C); /* opens window(s), checks keymaps */
- bmain->name[0] = '\0';
-
- /* start with save preference untitled.blend */
- G.save_over = 0;
+ bmain->filepath[0] = '\0';
}
{
@@ -1406,10 +1375,6 @@ void wm_homefile_read(bContext *C,
wm_homefile_read_ex(C, params_homefile, reports, NULL);
}
-/**
- * Special case, support deferred execution of #wm_file_read_post,
- * Needed when loading for the first time to workaround order of initialization bug, see T89046.
- */
void wm_homefile_read_post(struct bContext *C,
const struct wmFileReadPost_Params *params_file_read_post)
{
@@ -1417,6 +1382,8 @@ void wm_homefile_read_post(struct bContext *C,
MEM_freeN((void *)params_file_read_post);
}
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Blend-File History API
* \{ */
@@ -1514,18 +1481,18 @@ static void wm_history_file_write(void)
static void wm_history_file_update(void)
{
RecentFile *recent;
- const char *blendfile_name = BKE_main_blendfile_path_from_global();
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
- /* no write history for recovered startup files */
- if (blendfile_name[0] == '\0') {
+ /* No write history for recovered startup files. */
+ if (blendfile_path[0] == '\0') {
return;
}
recent = G.recent_files.first;
/* refresh recent-files.txt of recent opened files, when current file was changed */
- if (!(recent) || (BLI_path_cmp(recent->filepath, blendfile_name) != 0)) {
+ if (!(recent) || (BLI_path_cmp(recent->filepath, blendfile_path) != 0)) {
- recent = wm_file_history_find(blendfile_name);
+ recent = wm_file_history_find(blendfile_path);
if (recent) {
BLI_remlink(&G.recent_files, recent);
}
@@ -1536,7 +1503,7 @@ static void wm_history_file_update(void)
recent_next = recent->next;
wm_history_file_free(recent);
}
- recent = wm_history_file_new(blendfile_name);
+ recent = wm_history_file_new(blendfile_path);
}
/* add current file to the beginning of list */
@@ -1546,7 +1513,7 @@ static void wm_history_file_update(void)
wm_history_file_write();
/* also update most recent files on System */
- GHOST_addToSystemRecentFiles(blendfile_name);
+ GHOST_addToSystemRecentFiles(blendfile_path);
}
}
@@ -1721,7 +1688,6 @@ static ImBuf *blend_file_thumb_from_camera(const bContext *C,
return ibuf;
}
-/* easy access from gdb */
bool write_crash_blend(void)
{
char path[FILE_MAX];
@@ -1817,8 +1783,9 @@ static bool wm_file_write(bContext *C,
if (file_preview_type == USER_FILE_PREVIEW_AUTO) {
Scene *scene = CTX_data_scene(C);
- bool do_render = (scene != NULL && scene->camera != NULL &&
- (BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0) != NULL));
+ bScreen *screen = CTX_wm_screen(C);
+ bool do_render = (scene != NULL && scene->camera != NULL && screen != NULL &&
+ (BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0) != NULL));
file_preview_type = do_render ? USER_FILE_PREVIEW_CAMERA : USER_FILE_PREVIEW_SCREENSHOT;
}
@@ -1846,16 +1813,10 @@ static bool wm_file_write(bContext *C,
ED_editors_flush_edits(bmain);
- /* First time saving. */
- /* XXX(ton): temp solution to solve bug, real fix coming. */
- if ((BKE_main_blendfile_path(bmain)[0] == '\0') && (use_save_as_copy == false)) {
- BLI_strncpy(bmain->name, filepath, sizeof(bmain->name));
- }
-
/* XXX(ton): temp solution to solve bug, real fix coming. */
bmain->recovered = 0;
- if (BLO_write_file(CTX_data_main(C),
+ if (BLO_write_file(bmain,
filepath,
fileflags,
&(const struct BlendFileWriteParams){
@@ -1869,10 +1830,7 @@ static bool wm_file_write(bContext *C,
(CTX_wm_manager(C)->op_undo_depth == 0);
if (use_save_as_copy == false) {
- G.relbase_valid = 1;
- BLI_strncpy(bmain->name, filepath, sizeof(bmain->name)); /* is guaranteed current file */
-
- G.save_over = 1; /* disable untitled.blend convention */
+ STRNCPY(bmain->filepath, filepath); /* is guaranteed current file */
}
SET_FLAG_FROM_TEST(G.fileflags, fileflags & G_FILE_COMPRESS, G_FILE_COMPRESS);
@@ -1923,8 +1881,13 @@ static void wm_autosave_location(char *filepath)
const char *savedir;
#endif
- if (G_MAIN && G.relbase_valid) {
- const char *basename = BLI_path_basename(BKE_main_blendfile_path_from_global());
+ /* Normally there is no need to check for this to be NULL,
+ * however this runs on exit when it may be cleared. */
+ Main *bmain = G_MAIN;
+ const char *blendfile_path = bmain ? BKE_main_blendfile_path(bmain) : NULL;
+
+ if (blendfile_path && (blendfile_path[0] != '\0')) {
+ const char *basename = BLI_path_basename(blendfile_path);
int len = strlen(basename) - 6;
BLI_snprintf(path, sizeof(path), "%.*s_%d_autosave.blend", len, basename, pid);
}
@@ -2006,9 +1969,6 @@ void WM_autosave_init(wmWindowManager *wm)
wm_autosave_timer_begin(wm);
}
-/**
- * Run the auto-save timer action.
- */
void wm_autosave_timer(Main *bmain, wmWindowManager *wm, wmTimer *UNUSED(wt))
{
wm_autosave_timer_end(wm);
@@ -2137,7 +2097,7 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
fileflags,
&(const struct BlendFileWriteParams){
/* Make all paths absolute when saving the startup file.
- * On load the `G.relbase_valid` will be false so the paths
+ * On load the `G.main->filepath` will be empty so the paths
* won't have a base for resolving the relative paths. */
.remap_mode = BLO_WRITE_PATH_REMAP_ABSOLUTE,
/* Don't apply any path changes to the current blend file. */
@@ -2150,7 +2110,6 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
printf("ok\n");
BKE_report(op->reports, RPT_INFO, "Startup file saved");
- G.save_over = 0;
BKE_callback_exec_null(bmain, BKE_CB_EVT_SAVE_POST);
@@ -2637,7 +2596,7 @@ static int wm_open_mainfile__select_file_path(bContext *C, wmOperator *op)
set_next_operator_state(op, OPEN_MAINFILE_STATE_OPEN);
Main *bmain = CTX_data_main(C);
- const char *openname = BKE_main_blendfile_path(bmain);
+ const char *blendfile_path = BKE_main_blendfile_path(bmain);
if (CTX_wm_window(C) == NULL) {
/* in rare cases this could happen, when trying to invoke in background
@@ -2650,10 +2609,10 @@ static int wm_open_mainfile__select_file_path(bContext *C, wmOperator *op)
/* if possible, get the name of the most recently used .blend file */
if (G.recent_files.first) {
struct RecentFile *recent = G.recent_files.first;
- openname = recent->filepath;
+ blendfile_path = recent->filepath;
}
- RNA_string_set(op->ptr, "filepath", openname);
+ RNA_string_set(op->ptr, "filepath", blendfile_path);
wm_open_init_load_ui(op, true);
wm_open_init_use_scripts(op, true);
op->customdata = NULL;
@@ -2876,7 +2835,8 @@ static int wm_revert_mainfile_exec(bContext *C, wmOperator *op)
static bool wm_revert_mainfile_poll(bContext *UNUSED(C))
{
- return G.relbase_valid;
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
+ return (blendfile_path[0] != '\0');
}
void WM_OT_revert_mainfile(wmOperatorType *ot)
@@ -3033,9 +2993,9 @@ void WM_OT_recover_auto_save(wmOperatorType *ot)
* Both #WM_OT_save_as_mainfile & #WM_OT_save_mainfile.
* \{ */
-static void wm_filepath_default(char *filepath)
+static void wm_filepath_default(const Main *bmain, char *filepath)
{
- if (G.save_over == false) {
+ if (bmain->filepath[0] == '\0') {
BLI_path_filename_ensure(filepath, FILE_MAX, "untitled.blend");
}
}
@@ -3046,7 +3006,8 @@ static void save_set_compress(wmOperator *op)
prop = RNA_struct_find_property(op->ptr, "compress");
if (!RNA_property_is_set(op->ptr, prop)) {
- if (G.save_over) { /* keep flag for existing file */
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
+ if (blendfile_path[0] != '\0') { /* Keep flag for existing file. */
RNA_property_boolean_set(op->ptr, prop, (G.fileflags & G_FILE_COMPRESS) != 0);
}
else { /* use userdef for new file */
@@ -3059,21 +3020,22 @@ static void save_set_filepath(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
PropertyRNA *prop;
- char name[FILE_MAX];
+ char filepath[FILE_MAX];
prop = RNA_struct_find_property(op->ptr, "filepath");
if (!RNA_property_is_set(op->ptr, prop)) {
+ const char *blendfile_path = BKE_main_blendfile_path(bmain);
/* if not saved before, get the name of the most recently used .blend file */
- if (BKE_main_blendfile_path(bmain)[0] == '\0' && G.recent_files.first) {
+ if ((blendfile_path[0] == '\0') && G.recent_files.first) {
struct RecentFile *recent = G.recent_files.first;
- BLI_strncpy(name, recent->filepath, FILE_MAX);
+ STRNCPY(filepath, recent->filepath);
}
else {
- BLI_strncpy(name, bmain->name, FILE_MAX);
+ STRNCPY(filepath, blendfile_path);
}
- wm_filepath_default(name);
- RNA_property_string_set(op->ptr, prop, name);
+ wm_filepath_default(bmain, filepath);
+ RNA_property_string_set(op->ptr, prop, filepath);
}
}
@@ -3105,12 +3067,32 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
BLO_WRITE_PATH_REMAP_NONE;
save_set_compress(op);
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ const bool is_filepath_set = RNA_struct_property_is_set(op->ptr, "filepath");
+ if (is_filepath_set) {
RNA_string_get(op->ptr, "filepath", path);
}
else {
- BLI_strncpy(path, BKE_main_blendfile_path(bmain), FILE_MAX);
- wm_filepath_default(path);
+ STRNCPY(path, BKE_main_blendfile_path(bmain));
+ }
+
+ if (path[0] == '\0') {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Unable to save an unsaved file with an empty or unset \"filepath\" property");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* NOTE(@campbellbarton): only check this for file-path properties so saving an already
+ * saved file never fails with an error.
+ * Even though this should never happen, there may be some corner case where a malformed
+ * path is stored in `G.main->filepath`: when the file path is initialized from recovering
+ * a blend file - for example, so in this case failing to save isn't ideal. */
+ if (is_filepath_set && !BLI_path_is_abs_from_cwd(path)) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "The \"filepath\" property was not an absolute path: \"%s\"",
+ path);
+ return OPERATOR_CANCELLED;
}
const int fileflags_orig = G.fileflags;
@@ -3227,14 +3209,15 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U
/* if we're saving for the first time and prefer relative paths -
* any existing paths will be absolute,
* enable the option to remap paths to avoid confusion T37240. */
- if ((G.relbase_valid == false) && (U.flag & USER_RELPATHS)) {
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
+ if ((blendfile_path[0] == '\0') && (U.flag & USER_RELPATHS)) {
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "relative_remap");
if (!RNA_property_is_set(op->ptr, prop)) {
RNA_property_boolean_set(op->ptr, prop, true);
}
}
- if (G.save_over) {
+ if (blendfile_path[0] != '\0') {
char path[FILE_MAX];
RNA_string_get(op->ptr, "filepath", path);
@@ -3336,6 +3319,7 @@ static uiBlock *block_create_autorun_warning(struct bContext *C,
struct ARegion *region,
void *UNUSED(arg1))
{
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
wmWindowManager *wm = CTX_wm_manager(C);
uiBlock *block = UI_block_begin(C, region, "autorun_warning_popup", UI_EMBOSS);
@@ -3383,7 +3367,7 @@ static uiBlock *block_create_autorun_warning(struct bContext *C,
/* Allow reload if we have a saved file.
* Otherwise just enable scripts and reset the depsgraphs. */
- if (G.relbase_valid && wm->file_saved) {
+ if ((blendfile_path[0] != '\0') && wm->file_saved) {
but = uiDefIconTextBut(block,
UI_BTYPE_BUT,
0,
@@ -3640,10 +3624,10 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C,
uiItemL_ex(layout, TIP_("Save changes before closing?"), ICON_NONE, true, false);
/* Filename. */
- const char *blendfile_pathpath = BKE_main_blendfile_path(CTX_data_main(C));
+ const char *blendfile_path = BKE_main_blendfile_path(CTX_data_main(C));
char filename[FILE_MAX];
- if (blendfile_pathpath[0] != '\0') {
- BLI_split_file_part(blendfile_pathpath, filename, sizeof(filename));
+ if (blendfile_path[0] != '\0') {
+ BLI_split_file_part(blendfile_path, filename, sizeof(filename));
}
else {
STRNCPY(filename, "untitled.blend");
@@ -3810,10 +3794,6 @@ static void wm_free_operator_properties_callback(void *user_data)
IDP_FreeProperty(properties);
}
-/**
- * \return True if the dialog was created, the calling operator should return #OPERATOR_INTERFACE
- * then.
- */
bool wm_operator_close_file_dialog_if_needed(bContext *C,
wmOperator *op,
wmGenericCallbackFn post_action_fn)
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index d373ecdac77..cf6ecd55757 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -52,9 +52,8 @@
#include "BLO_readfile.h"
-#include "BLT_translation.h"
-
#include "BKE_armature.h"
+#include "BKE_blendfile_link_append.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_key.h"
@@ -114,12 +113,13 @@ static bool wm_link_append_poll(bContext *C)
static int wm_link_append_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
if (G.lib[0] != '\0') {
RNA_string_set(op->ptr, "filepath", G.lib);
}
- else if (G.relbase_valid) {
+ else if (blendfile_path[0] != '\0') {
char path[FILE_MAX];
- BLI_strncpy(path, BKE_main_blendfile_path_from_global(), sizeof(path));
+ STRNCPY(path, blendfile_path);
BLI_path_parent_dir(path);
RNA_string_set(op->ptr, "filepath", path);
}
@@ -168,841 +168,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, DATA_("Appended Data"));
- }
- }
-}
-
-/* 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;
- if (!do_add_collection) {
- 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(bmain, id, 0);
- }
-
- /* 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.
*
@@ -1053,7 +218,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;
@@ -1120,7 +285,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;
@@ -1138,7 +310,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);
}
}
}
@@ -1150,7 +322,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;
@@ -1158,9 +330,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;
@@ -1168,16 +340,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;
@@ -1186,7 +359,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);
@@ -1196,10 +369,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 */
@@ -1351,33 +524,35 @@ 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);
return id;
}
-/*
- * NOTE: `scene` (and related `view_layer` and `v3d`) pointers may be NULL, in which case no
- * instantiation of linked objects, collections etc. will be performed.
- */
ID *WM_file_link_datablock(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
@@ -1392,10 +567,6 @@ ID *WM_file_link_datablock(Main *bmain,
bmain, scene, view_layer, v3d, filepath, id_code, id_name, flag);
}
-/*
- * NOTE: `scene` (and related `view_layer` and `v3d`) pointers may be NULL, in which case no
- * instantiation of appended objects, collections etc. will be performed.
- */
ID *WM_file_append_datablock(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
@@ -1444,291 +615,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)) {
@@ -1745,14 +631,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);
- wm_link_append_data_library_add(lapp_data, lib->filepath_abs);
+ BlendfileLinkAppendContext *lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
+
+ BKE_blendfile_link_append_context_library_add(lapp_context, lib->filepath_abs, NULL);
+
+ BKE_blendfile_library_relocate(lapp_context, reports, lib, true);
+
+ BKE_blendfile_link_append_context_free(lapp_context);
+
+ BKE_main_lib_objects_recalc_all(bmain);
+ IMB_colormanagement_check_file_config(bmain);
- lib_relocate_do(C, lib, lapp_data, reports, true);
+ /* 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);
- wm_link_append_data_free(lapp_data);
+ /* Recreate dependency graph to include new IDs. */
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
}
@@ -1768,7 +674,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;
@@ -1813,13 +719,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;
@@ -1839,7 +749,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") {
@@ -1852,27 +762,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_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index ab971901a20..47f51214a8e 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -50,7 +50,6 @@
#include "BIF_glutil.h"
-/* context checked on having screen, window and area */
wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent *event, int type)
{
wmGesture *gesture = MEM_callocN(sizeof(wmGesture), "new gesture");
@@ -129,7 +128,6 @@ bool WM_gesture_is_modal_first(const wmGesture *gesture)
return (gesture->is_active_prev == false);
}
-/* tweak and line gestures */
int wm_gesture_evaluate(wmGesture *gesture, const wmEvent *event)
{
if (gesture->type == WM_GESTURE_TWEAK) {
@@ -515,7 +513,6 @@ static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
immUnbindProgram();
}
-/* called in wm_draw.c */
void wm_gesture_draw(wmWindow *win)
{
wmGesture *gt = (wmGesture *)win->gesture.first;
diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c
index 19b678d79d8..8d45d5aed67 100644
--- a/source/blender/windowmanager/intern/wm_gesture_ops.c
+++ b/source/blender/windowmanager/intern/wm_gesture_ops.c
@@ -124,6 +124,7 @@ static int UNUSED_FUNCTION(gesture_modal_state_from_operator)(wmOperator *op)
}
return GESTURE_MODAL_NOP;
}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -569,7 +570,6 @@ static void gesture_tweak_modal(bContext *C, const wmEvent *event)
}
}
-/* standard tweak, called after window handlers passed on event */
void wm_tweakevent_test(bContext *C, const wmEvent *event, int action)
{
wmWindow *win = CTX_wm_window(C);
@@ -750,11 +750,6 @@ void WM_gesture_lines_cancel(bContext *C, wmOperator *op)
gesture_modal_end(C, op);
}
-/**
- * helper function, we may want to add options for conversion to view space
- *
- * caller must free.
- */
const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C),
wmOperator *op,
int *r_mcoords_len))[2]
@@ -889,10 +884,6 @@ int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *e
return OPERATOR_RUNNING_MODAL;
}
-/**
- * This invoke callback starts the straightline gesture with a viewport preview to the right side
- * of the line.
- */
int WM_gesture_straightline_active_side_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
WM_gesture_straightline_invoke(C, op, event);
@@ -928,11 +919,6 @@ static void wm_gesture_straightline_do_angle_snap(rcti *rect)
rect->ymax = (int)line_snapped_end[1];
}
-/**
- * This modal callback calls exec once per mouse move event while the gesture is active with the
- * updated line start and end values, so it can be used for tools that have a real time preview
- * (like a gradient updating in real time over the mesh).
- */
int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
@@ -1012,13 +998,6 @@ int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *ev
return OPERATOR_RUNNING_MODAL;
}
-/**
- * This modal one-shot callback only calls exec once after the gesture finishes without any updates
- * during the gesture execution. Should be used for operations that are intended to be applied once
- * without real time preview (like a trimming tool that only applies the bisect operation once
- * after finishing the gesture as the bisect operation is too heavy to be computed in real time for
- * a preview).
- */
int WM_gesture_straightline_oneshot_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index c382af03c4a..2f87e5789fe 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -223,10 +223,6 @@ static void sound_jack_sync_callback(Main *bmain, int mode, double time)
}
}
-/**
- * Initialize Blender and load the startup file & preferences
- * (only called once).
- */
void WM_init(bContext *C, int argc, const char **argv)
{
@@ -318,9 +314,9 @@ void WM_init(bContext *C, int argc, const char **argv)
NULL,
&params_file_read_post);
- /* NOTE: leave `G_MAIN->name` set to an empty string since this
+ /* NOTE: leave `G_MAIN->filepath` set to an empty string since this
* matches behavior after loading a new file. */
- BLI_assert(G_MAIN->name[0] == '\0');
+ BLI_assert(G_MAIN->filepath[0] == '\0');
/* Call again to set from preferences. */
BLT_lang_set(NULL);
@@ -432,10 +428,6 @@ static int wm_exit_handler(bContext *C, const wmEvent *event, void *userdata)
return WM_UI_HANDLER_BREAK;
}
-/**
- * Cause a delayed #WM_exit()
- * call to avoid leaking memory when trying to exit from within operators.
- */
void wm_exit_schedule_delayed(const bContext *C)
{
/* What we do here is a little bit hacky, but quite simple and doesn't require bigger
@@ -449,9 +441,6 @@ void wm_exit_schedule_delayed(const bContext *C)
WM_event_add_mousemove(win); /* ensure handler actually gets called */
}
-/**
- * \note doesn't run exit() call #WM_exit() for that.
- */
void WM_exit_ex(bContext *C, const bool do_python)
{
wmWindowManager *wm = C ? CTX_wm_manager(C) : NULL;
@@ -547,6 +536,7 @@ void WM_exit_ex(bContext *C, const bool do_python)
RE_engines_exit();
ED_preview_free_dbase(); /* frees a Main dbase, before BKE_blender_free! */
+ ED_preview_restart_queue_free();
ED_assetlist_storage_exit();
if (wm) {
@@ -655,11 +645,6 @@ void WM_exit_ex(bContext *C, const bool do_python)
BKE_tempdir_session_purge();
}
-/**
- * \brief Main exit function to close Blender ordinarily.
- * \note Use #wm_exit_schedule_delayed() to close Blender from an operator.
- * Might leak memory otherwise.
- */
void WM_exit(bContext *C)
{
WM_exit_ex(C, true);
@@ -677,10 +662,6 @@ void WM_exit(bContext *C)
exit(G.is_break == true);
}
-/**
- * Needed for cases when operators are re-registered
- * (when operator type pointers are stored).
- */
void WM_script_tag_reload(void)
{
UI_interface_tag_script_reload();
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index 2604105896d..66277ec57f4 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -187,12 +187,6 @@ static wmJob *wm_job_find(const wmWindowManager *wm, const void *owner, const in
/* ******************* public API ***************** */
-/**
- * \return current job or adds new job, but doesn't run it.
- *
- * \note every owner only gets a single job,
- * adding a new one will stop running job and when stopped it starts the new one.
- */
wmJob *WM_jobs_get(wmWindowManager *wm,
wmWindow *win,
const void *owner,
@@ -223,7 +217,6 @@ wmJob *WM_jobs_get(wmWindowManager *wm,
return wm_job;
}
-/* returns true if job runs, for UI (progress) indicators */
bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
{
/* job can be running or about to run (suspended) */
@@ -281,7 +274,6 @@ static void wm_jobs_update_progress_bars(wmWindowManager *wm)
}
}
-/* time that job started */
double WM_jobs_starttime(const wmWindowManager *wm, const void *owner)
{
const wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY);
@@ -447,10 +439,6 @@ static void wm_jobs_test_suspend_stop(wmWindowManager *wm, wmJob *test)
#endif
}
-/**
- * if job running, the same owner gave it a new job.
- * if different owner starts existing startjob, it suspends itself
- */
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
{
if (wm_job->running) {
@@ -550,7 +538,6 @@ static void wm_jobs_kill_job(wmWindowManager *wm, wmJob *wm_job)
}
}
-/* wait until every job ended */
void WM_jobs_kill_all(wmWindowManager *wm)
{
wmJob *wm_job;
@@ -563,7 +550,6 @@ void WM_jobs_kill_all(wmWindowManager *wm)
SEQ_prefetch_stop_all();
}
-/* wait until every job ended, except for one owner (used in undo to keep screen job alive) */
void WM_jobs_kill_all_except(wmWindowManager *wm, const void *owner)
{
LISTBASE_FOREACH_MUTABLE (wmJob *, wm_job, &wm->jobs) {
@@ -584,7 +570,6 @@ void WM_jobs_kill_type(struct wmWindowManager *wm, const void *owner, int job_ty
}
}
-/* signal job(s) from this owner or callback to stop, timer is required to get handled */
void WM_jobs_stop(wmWindowManager *wm, const void *owner, void *startjob)
{
LISTBASE_FOREACH (wmJob *, wm_job, &wm->jobs) {
@@ -596,7 +581,6 @@ void WM_jobs_stop(wmWindowManager *wm, const void *owner, void *startjob)
}
}
-/* actually terminate thread and job timer */
void WM_jobs_kill(wmWindowManager *wm,
void *owner,
void (*startjob)(void *, short int *, short int *, float *))
@@ -608,7 +592,6 @@ void WM_jobs_kill(wmWindowManager *wm,
}
}
-/* kill job entirely, also removes timer itself */
void wm_jobs_timer_end(wmWindowManager *wm, wmTimer *wt)
{
LISTBASE_FOREACH (wmJob *, wm_job, &wm->jobs) {
@@ -619,7 +602,6 @@ void wm_jobs_timer_end(wmWindowManager *wm, wmTimer *wt)
}
}
-/* hardcoded to event TIMERJOBS */
void wm_jobs_timer(wmWindowManager *wm, wmTimer *wt)
{
LISTBASE_FOREACH_MUTABLE (wmJob *, wm_job, &wm->jobs) {
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 35f6ce40dba..0214fce59b2 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -189,7 +189,6 @@ static bool wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b)
(a->flag & KMI_REPEAT_IGNORE) == (b->flag & KMI_REPEAT_IGNORE)));
}
-/* properties can be NULL, otherwise the arg passed is used and ownership is given to the kmi */
void WM_keymap_item_properties_reset(wmKeyMapItem *kmi, struct IDProperty *properties)
{
if (LIKELY(kmi->ptr)) {
@@ -514,7 +513,6 @@ static void keymap_item_set_id(wmKeyMap *keymap, wmKeyMapItem *kmi)
}
}
-/* always add item */
wmKeyMapItem *WM_keymap_add_item(
wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
{
@@ -1150,7 +1148,6 @@ const char *WM_key_event_string(const short type, const bool compact)
return CTX_IFACE_(BLT_I18NCONTEXT_UI_EVENTS, it->name);
}
-/* TODO: also support (some) value, like e.g. double-click? */
int WM_keymap_item_raw_to_string(const short shift,
const short ctrl,
const short alt,
@@ -1162,6 +1159,8 @@ int WM_keymap_item_raw_to_string(const short shift,
char *result,
const int result_len)
{
+ /* TODO: also support (some) value, like e.g. double-click? */
+
#define ADD_SEP \
if (p != buf) { \
*p++ = ' '; \
@@ -1307,6 +1306,10 @@ char *WM_modalkeymap_operator_items_to_string_buf(wmOperatorType *ot,
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Keymap Finding Utilities
+ * \{ */
+
static wmKeyMapItem *wm_keymap_item_find_in_keymap(wmKeyMap *keymap,
const char *opname,
IDProperty *properties,
@@ -1676,10 +1679,6 @@ static bool kmi_filter_is_visible_type_mask(const wmKeyMap *km,
kmi_filter_is_visible(km, kmi, user_data));
}
-/**
- * \param include_mask, exclude_mask:
- * Event types to include/exclude when looking up keys (#eEventType_Mask).
- */
wmKeyMapItem *WM_key_event_operator(const bContext *C,
const char *opname,
wmOperatorCallContext opcontext,
diff --git a/source/blender/windowmanager/intern/wm_keymap_utils.c b/source/blender/windowmanager/intern/wm_keymap_utils.c
index 795f78e215f..d424eef8262 100644
--- a/source/blender/windowmanager/intern/wm_keymap_utils.c
+++ b/source/blender/windowmanager/intern/wm_keymap_utils.c
@@ -43,7 +43,6 @@
/** \name Wrappers for #WM_keymap_add_item
* \{ */
-/* menu wrapper for WM_keymap_add_item */
wmKeyMapItem *WM_keymap_add_menu(
wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
{
@@ -73,7 +72,6 @@ wmKeyMapItem *WM_keymap_add_panel(
return kmi;
}
-/* tool wrapper for WM_keymap_add_item */
wmKeyMapItem *WM_keymap_add_tool(
wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
{
@@ -83,7 +81,6 @@ wmKeyMapItem *WM_keymap_add_tool(
return kmi;
}
-/** Useful for mapping numbers to an enum. */
void WM_keymap_add_context_enum_set_items(wmKeyMap *keymap,
const EnumPropertyItem *items,
const char *data_path,
@@ -203,8 +200,6 @@ wmKeyMap *WM_keymap_guess_from_context(const bContext *C)
return km;
}
-/* Guess an appropriate keymap from the operator name */
-/* Needs to be kept up to date with Keymap and Operator naming */
wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
{
/* Op types purposely skipped for now:
diff --git a/source/blender/windowmanager/intern/wm_menu_type.c b/source/blender/windowmanager/intern/wm_menu_type.c
index bcaa2243f9f..799b6fc2e52 100644
--- a/source/blender/windowmanager/intern/wm_menu_type.c
+++ b/source/blender/windowmanager/intern/wm_menu_type.c
@@ -77,7 +77,6 @@ void WM_menutype_freelink(MenuType *mt)
UNUSED_VARS_NDEBUG(ok);
}
-/* called on initialize WM_init() */
void WM_menutype_init(void)
{
/* reserve size is set based on blender default setup */
diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c
index 898671706d1..a5887fc07b3 100644
--- a/source/blender/windowmanager/intern/wm_operator_props.c
+++ b/source/blender/windowmanager/intern/wm_operator_props.c
@@ -72,7 +72,6 @@ static const EnumPropertyItem *wm_operator_properties_filesel_sort_items_itemf(
return items;
}
-/* default properties for fileselect */
void WM_operator_properties_filesel(wmOperatorType *ot,
int filter,
short type,
@@ -262,9 +261,6 @@ void WM_operator_properties_select_action(wmOperatorType *ot, int default_action
wm_operator_properties_select_action_ex(ot, default_action, select_actions, hide_gui);
}
-/**
- * only SELECT/DESELECT
- */
void WM_operator_properties_select_action_simple(wmOperatorType *ot,
int default_action,
bool hide_gui)
@@ -278,10 +274,6 @@ void WM_operator_properties_select_action_simple(wmOperatorType *ot,
wm_operator_properties_select_action_ex(ot, default_action, select_actions, hide_gui);
}
-/**
- * Use for all select random operators.
- * Adds properties: percent, seed, action.
- */
void WM_operator_properties_select_random(wmOperatorType *ot)
{
RNA_def_float_factor(ot->srna,
@@ -357,9 +349,6 @@ void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect)
BLI_rctf_rcti_copy(rect, &rect_i);
}
-/**
- * Use with #WM_gesture_box_invoke
- */
void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bool extend)
{
PropertyRNA *prop;
@@ -381,10 +370,6 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo
}
}
-/**
- * Disable using cursor position,
- * use when view operators are initialized from buttons.
- */
void WM_operator_properties_use_cursor_init(wmOperatorType *ot)
{
PropertyRNA *prop = RNA_def_boolean(ot->srna,
@@ -418,7 +403,6 @@ void WM_operator_properties_select_operation(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* Some tools don't support XOR/AND. */
void WM_operator_properties_select_operation_simple(wmOperatorType *ot)
{
static const EnumPropertyItem select_mode_items[] = {
@@ -450,31 +434,6 @@ void WM_operator_properties_select_walk_direction(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/**
- * Selecting and tweaking items are overlapping operations. Getting both to work without conflicts
- * requires special care. See
- * https://wiki.blender.org/wiki/Human_Interface_Guidelines/Selection#Select-tweaking for the
- * desired behavior.
- *
- * For default click selection (with no modifier keys held), the select operators can do the
- * following:
- * - On a mouse press on an unselected item, change selection and finish immediately after.
- * This sends an undo push and allows transform to take over should a tweak event be caught now.
- * - On a mouse press on a selected item, don't change selection state, but start modal execution
- * of the operator. Idea is that we wait with deselecting other items until we know that the
- * intention wasn't to tweak (mouse press+drag) all selected items.
- * - If a tweak is recognized before the release event happens, cancel the operator, so that
- * transform can take over and no undo-push is sent.
- * - If the release event occurs rather than a tweak one, deselect all items but the one under the
- * cursor, and finish the modal operator.
- *
- * This utility, together with #WM_generic_select_invoke() and #WM_generic_select_modal() should
- * help getting the wanted behavior to work. Most generic logic should be handled in these, so that
- * the select operators only have to care for the case dependent handling.
- *
- * Every select operator has slightly different requirements, e.g. sequencer strip selection
- * also needs to account for handle selection. This should be the baseline behavior though.
- */
void WM_operator_properties_generic_select(wmOperatorType *ot)
{
/* On the initial mouse press, this is set by #WM_generic_select_modal() to let the select
@@ -499,9 +458,6 @@ void WM_operator_properties_gesture_box_zoom(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
-/**
- * Use with #WM_gesture_lasso_invoke
- */
void WM_operator_properties_gesture_lasso(wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -509,9 +465,6 @@ void WM_operator_properties_gesture_lasso(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
-/**
- * Use with #WM_gesture_straightline_invoke
- */
void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor)
{
PropertyRNA *prop;
@@ -541,9 +494,6 @@ void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor)
}
}
-/**
- * Use with #WM_gesture_circle_invoke
- */
void WM_operator_properties_gesture_circle(wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -582,9 +532,6 @@ void WM_operator_properties_mouse_select(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/**
- * \param nth_can_disable: Enable if we want to be able to select no interval at all.
- */
void WM_operator_properties_checker_interval(wmOperatorType *ot, bool nth_can_disable)
{
const int nth_default = nth_can_disable ? 0 : 1;
diff --git a/source/blender/windowmanager/intern/wm_operator_type.c b/source/blender/windowmanager/intern/wm_operator_type.c
index 0e30df4ec99..0f6096e7b8b 100644
--- a/source/blender/windowmanager/intern/wm_operator_type.c
+++ b/source/blender/windowmanager/intern/wm_operator_type.c
@@ -89,7 +89,6 @@ wmOperatorType *WM_operatortype_find(const char *idname, bool quiet)
return NULL;
}
-/* caller must free */
void WM_operatortype_iter(GHashIterator *ghi)
{
BLI_ghashIterator_init(ghi, global_ops_hash);
@@ -132,7 +131,8 @@ static void wm_operatortype_append__end(wmOperatorType *ot)
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
}
-/* all ops in 1 list (for time being... needs evaluation later) */
+/* All ops in 1 list (for time being... needs evaluation later). */
+
void WM_operatortype_append(void (*opfunc)(wmOperatorType *))
{
wmOperatorType *ot = wm_operatortype_append__begin();
@@ -149,7 +149,6 @@ void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void *
/** \} */
-/* called on initialize WM_exit() */
void WM_operatortype_remove_ptr(wmOperatorType *ot)
{
BLI_assert(ot == WM_operatortype_find(ot->idname, false));
@@ -184,7 +183,6 @@ bool WM_operatortype_remove(const char *idname)
return true;
}
-/* called on initialize WM_init() */
void wm_operatortype_init(void)
{
/* reserve size is set based on blender default setup */
@@ -215,18 +213,6 @@ void wm_operatortype_free(void)
global_ops_hash = NULL;
}
-/**
- * Tag all operator-properties of \a ot defined after calling this, until
- * the next #WM_operatortype_props_advanced_end call (if available), with
- * #OP_PROP_TAG_ADVANCED. Previously defined ones properties not touched.
- *
- * Calling this multiple times without a call to #WM_operatortype_props_advanced_end,
- * all calls after the first one are ignored. Meaning all proprieties defined after the
- * first call are tagged as advanced.
- *
- * This doesn't do the actual tagging, #WM_operatortype_props_advanced_end does which is
- * called for all operators during registration (see #wm_operatortype_append__end).
- */
void WM_operatortype_props_advanced_begin(wmOperatorType *ot)
{
if (ot_prop_basic_count == -1) {
@@ -235,14 +221,6 @@ void WM_operatortype_props_advanced_begin(wmOperatorType *ot)
}
}
-/**
- * Tags all operator-properties of \a ot defined since the first
- * #WM_operatortype_props_advanced_begin call,
- * or the last #WM_operatortype_props_advanced_end call, with #OP_PROP_TAG_ADVANCED.
- *
- * \note This is called for all operators during registration (see #wm_operatortype_append__end).
- * So it does not need to be explicitly called in operator-type definition.
- */
void WM_operatortype_props_advanced_end(wmOperatorType *ot)
{
PointerRNA struct_ptr;
@@ -266,9 +244,6 @@ void WM_operatortype_props_advanced_end(wmOperatorType *ot)
ot_prop_basic_count = -1;
}
-/**
- * Remove memory of all previously executed tools.
- */
void WM_operatortype_last_properties_clear_all(void)
{
GHashIterator iter;
@@ -471,7 +446,6 @@ static void wm_macro_cancel(bContext *C, wmOperator *op)
wm_macro_end(op, OPERATOR_CANCELLED);
}
-/* Names have to be static for now */
wmOperatorType *WM_operatortype_append_macro(const char *idname,
const char *name,
const char *description,
@@ -613,9 +587,6 @@ char *WM_operatortype_description(struct bContext *C,
return NULL;
}
-/**
- * Use when we want a label, preferring the description.
- */
char *WM_operatortype_description_or_name(struct bContext *C,
struct wmOperatorType *ot,
struct PointerRNA *properties)
diff --git a/source/blender/windowmanager/intern/wm_operator_utils.c b/source/blender/windowmanager/intern/wm_operator_utils.c
index 85a0a28de79..dbcfd814692 100644
--- a/source/blender/windowmanager/intern/wm_operator_utils.c
+++ b/source/blender/windowmanager/intern/wm_operator_utils.c
@@ -44,9 +44,6 @@
/** \name Generic Utilities
* \{ */
-/**
- * Only finish + pass through for press events (allowing press-tweak).
- */
int WM_operator_flag_only_pass_through_on_press(int retval, const struct wmEvent *event)
{
if ((event->val != KM_PRESS) &&
@@ -337,10 +334,6 @@ static int op_generic_value_modal(bContext *C, wmOperator *op, const wmEvent *ev
return OPERATOR_RUNNING_MODAL;
}
-/**
- * Allow an operator with only and execute function to run modally,
- * re-doing the action, using vertex coordinate store/restore instead of operator undo.
- */
void WM_operator_type_modal_from_exec_for_object_edit_coords(wmOperatorType *ot)
{
PropertyRNA *prop;
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index ffdc99152b1..6c9b0af5186 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -116,13 +116,10 @@
#define UNDOCUMENTED_OPERATOR_TIP N_("(undocumented operator)")
-/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Operator API
* \{ */
-/* SOME_OT_op -> some.op */
void WM_operator_py_idname(char *to, const char *from)
{
const char *sep = strstr(from, "_OT_");
@@ -143,7 +140,6 @@ void WM_operator_py_idname(char *to, const char *from)
}
}
-/* some.op -> SOME_OT_op */
void WM_operator_bl_idname(char *to, const char *from)
{
if (from) {
@@ -167,10 +163,6 @@ void WM_operator_bl_idname(char *to, const char *from)
}
}
-/**
- * Sanity check to ensure #WM_operator_bl_idname won't fail.
- * \returns true when there are no problems with \a idname, otherwise report an error.
- */
bool WM_operator_py_idname_ok_or_report(ReportList *reports,
const char *classname,
const char *idname)
@@ -219,15 +211,6 @@ bool WM_operator_py_idname_ok_or_report(ReportList *reports,
return true;
}
-/**
- * Print a string representation of the operator,
- * with the args that it runs so python can run it again.
- *
- * When calling from an existing wmOperator, better to use simple version:
- * `WM_operator_pystring(C, op);`
- *
- * \note Both \a op and \a opptr may be `NULL` (\a op is only used for macro operators).
- */
char *WM_operator_pystring_ex(bContext *C,
wmOperator *op,
const bool all_args,
@@ -308,9 +291,6 @@ char *WM_operator_pystring(bContext *C, wmOperator *op, const bool all_args, con
return WM_operator_pystring_ex(C, op, all_args, macro_args, op->type, op->ptr);
}
-/**
- * \return true if the string was shortened
- */
bool WM_operator_pystring_abbreviate(char *str, int str_len_max)
{
const int str_len = strlen(str);
@@ -608,9 +588,6 @@ static const char *wm_context_member_from_ptr(const bContext *C,
}
#endif
-/**
- * Calculate the path to `ptr` from context `C`, or return NULL if it can't be calculated.
- */
char *WM_context_path_resolve_property_full(const bContext *C,
const PointerRNA *ptr,
PropertyRNA *prop,
@@ -711,8 +688,6 @@ void WM_operator_properties_create(PointerRNA *ptr, const char *opstring)
}
}
-/* similar to the function above except its uses ID properties
- * used for keymaps and macros */
void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *opstring)
{
IDProperty *tmp_properties = NULL;
@@ -763,14 +738,6 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
RNA_STRUCT_END;
}
-/**
- * Set all props to their default.
- *
- * \param do_update: Only update un-initialized props.
- *
- * \note There's nothing specific to operators here.
- * This could be made a general function.
- */
bool WM_operator_properties_default(PointerRNA *ptr, const bool do_update)
{
bool changed = false;
@@ -798,7 +765,6 @@ bool WM_operator_properties_default(PointerRNA *ptr, const bool do_update)
return changed;
}
-/* remove all props without PROP_SKIP_SAVE */
void WM_operator_properties_reset(wmOperator *op)
{
if (op->ptr->data) {
@@ -945,13 +911,6 @@ bool WM_operator_last_properties_store(wmOperator *UNUSED(op))
/** \name Default Operator Callbacks
* \{ */
-/**
- * Helper to get select and tweak-transform to work conflict free and as desired. See
- * #WM_operator_properties_generic_select() for details.
- *
- * To be used together with #WM_generic_select_invoke() and
- * #WM_operator_properties_generic_select().
- */
int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
PropertyRNA *wait_to_deselect_prop = RNA_struct_find_property(op->ptr,
@@ -1012,13 +971,6 @@ int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
}
-/**
- * Helper to get select and tweak-transform to work conflict free and as desired. See
- * #WM_operator_properties_generic_select() for details.
- *
- * To be used together with #WM_generic_select_modal() and
- * #WM_operator_properties_generic_select().
- */
int WM_generic_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
@@ -1063,7 +1015,6 @@ int WM_operator_smooth_viewtx_get(const wmOperator *op)
return (op->flag & OP_IS_INVOKE) ? U.smooth_viewtx : 0;
}
-/* invoke callback, uses enum property named "type" */
int WM_menu_invoke_ex(bContext *C, wmOperator *op, wmOperatorCallContext opcontext)
{
PropertyRNA *prop = op->type->prop;
@@ -1184,10 +1135,6 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *region, void *arg)
return block;
}
-/**
- * Similar to #WM_enum_search_invoke, but draws previews. Also, this can't
- * be used as invoke callback directly since it needs additional info.
- */
int WM_enum_search_invoke_previews(bContext *C, wmOperator *op, short prv_cols, short prv_rows)
{
static struct EnumSearchMenu search_menu;
@@ -1210,7 +1157,6 @@ int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(eve
return OPERATOR_INTERFACE;
}
-/* Can't be used as an invoke directly, needs message arg (can be NULL) */
int WM_operator_confirm_message_ex(bContext *C,
wmOperator *op,
const char *title,
@@ -1255,7 +1201,6 @@ int WM_operator_confirm_or_exec(bContext *C, wmOperator *op, const wmEvent *UNUS
return op->type->exec(C, op);
}
-/* op->invoke, opens fileselect if path property not set, otherwise executes */
int WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
@@ -1280,7 +1225,6 @@ bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFor
return false;
}
-/* op->poll */
bool WM_operator_winactive(bContext *C)
{
if (CTX_wm_window(C) == NULL) {
@@ -1289,7 +1233,6 @@ bool WM_operator_winactive(bContext *C)
return 1;
}
-/* return false, if the UI should be disabled */
bool WM_operator_check_ui_enabled(const bContext *C, const char *idname)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -1327,9 +1270,6 @@ void WM_operator_last_properties_ensure(wmOperatorType *ot, PointerRNA *ptr)
RNA_pointer_create(G_MAIN->wm.first, ot->srna, props, ptr);
}
-/**
- * Use for drag & drop a path or name with operators invoke() function.
- */
ID *WM_operator_drop_load_path(struct bContext *C, wmOperator *op, const short idcode)
{
Main *bmain = CTX_data_main(C);
@@ -1633,20 +1573,11 @@ static int wm_operator_props_popup_ex(bContext *C,
return OPERATOR_RUNNING_MODAL;
}
-/**
- * Same as #WM_operator_props_popup but don't use operator redo.
- * just wraps #WM_operator_props_dialog_popup.
- */
int WM_operator_props_popup_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return wm_operator_props_popup_ex(C, op, false, false);
}
-/**
- * Same as #WM_operator_props_popup but call the operator first,
- * This way - the button values correspond to the result of the operator.
- * Without this, first access to a button will make the result jump, see T32452.
- */
int WM_operator_props_popup_call(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return wm_operator_props_popup_ex(C, op, true, true);
@@ -3999,7 +3930,6 @@ static void gesture_zoom_border_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "IMAGE_OT_view_zoom_border");
}
-/* default keymap for windows and screens, only call once per WM */
void wm_window_keymap(wmKeyConfig *keyconf)
{
WM_keymap_ensure(keyconf, "Window", 0, 0);
@@ -4067,7 +3997,8 @@ static const EnumPropertyItem *rna_id_itemf(bool *r_free,
return item;
}
-/* can add more as needed */
+/* Can add more ID types as needed. */
+
const EnumPropertyItem *RNA_action_itemf(bContext *C,
PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop),
diff --git a/source/blender/windowmanager/intern/wm_panel_type.c b/source/blender/windowmanager/intern/wm_panel_type.c
index 24508c377a6..609bb55e075 100644
--- a/source/blender/windowmanager/intern/wm_panel_type.c
+++ b/source/blender/windowmanager/intern/wm_panel_type.c
@@ -69,7 +69,6 @@ void WM_paneltype_remove(PanelType *pt)
UNUSED_VARS_NDEBUG(ok);
}
-/* called on initialize WM_init() */
void WM_paneltype_init(void)
{
/* reserve size is set based on blender default setup */
diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c
index 16a17484f4f..a62ced1a4bf 100644
--- a/source/blender/windowmanager/intern/wm_stereo.c
+++ b/source/blender/windowmanager/intern/wm_stereo.c
@@ -177,10 +177,6 @@ bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check)
return true;
}
-/**
- * If needed, adjust \a r_mouse_xy
- * so that drawn cursor and handled mouse position are matching visually.
- */
void wm_stereo3d_mouse_offset_apply(wmWindow *win, int r_mouse_xy[2])
{
if (!WM_stereo3d_enabled(win, false)) {
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index 0cb76404258..524580ac88f 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -116,7 +116,6 @@ static void wmOrtho2_offset(const float x, const float y, const float ofs)
wmOrtho2(ofs, x + ofs, ofs, y + ofs);
}
-/* Default pixel alignment for regions. */
void wmOrtho2_region_pixelspace(const ARegion *region)
{
wmOrtho2_offset(region->winx, region->winy, -0.01f);
diff --git a/source/blender/windowmanager/intern/wm_surface.c b/source/blender/windowmanager/intern/wm_surface.c
index 715f72d70cf..385b55f36f9 100644
--- a/source/blender/windowmanager/intern/wm_surface.c
+++ b/source/blender/windowmanager/intern/wm_surface.c
@@ -45,11 +45,24 @@ static wmSurface *g_drawable = NULL;
void wm_surfaces_iter(bContext *C, void (*cb)(bContext *C, wmSurface *))
{
- LISTBASE_FOREACH (wmSurface *, surf, &global_surface_list) {
+ /* Mutable iterator in case a surface is freed. */
+ LISTBASE_FOREACH_MUTABLE (wmSurface *, surf, &global_surface_list) {
cb(C, surf);
}
}
+static void wm_surface_do_depsgraph_fn(bContext *C, wmSurface *surface)
+{
+ if (surface->do_depsgraph) {
+ surface->do_depsgraph(C);
+ }
+}
+
+void wm_surfaces_do_depsgraph(bContext *C)
+{
+ wm_surfaces_iter(C, wm_surface_do_depsgraph_fn);
+}
+
void wm_surface_clear_drawable(void)
{
if (g_drawable) {
@@ -107,6 +120,9 @@ void wm_surface_add(wmSurface *surface)
void wm_surface_remove(wmSurface *surface)
{
+ if (surface == g_drawable) {
+ wm_surface_clear_drawable();
+ }
BLI_remlink(&global_surface_list, surface);
surface->free_data(surface);
MEM_freeN(surface);
diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c
index 3ac1a7c0be1..7b8feac45b4 100644
--- a/source/blender/windowmanager/intern/wm_toolsystem.c
+++ b/source/blender/windowmanager/intern/wm_toolsystem.c
@@ -251,7 +251,6 @@ void WM_toolsystem_reinit(bContext *C, WorkSpace *workspace, const bToolKey *tke
}
}
-/* Operate on all active tools. */
void WM_toolsystem_unlink_all(struct bContext *C, struct WorkSpace *workspace)
{
LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
@@ -362,12 +361,6 @@ void WM_toolsystem_ref_set_from_runtime(struct bContext *C,
}
}
-/**
- * Sync the internal active state of a tool back into the tool system,
- * this is needed for active brushes where the real active state is not stored in the tool system.
- *
- * \see #toolsystem_ref_link
- */
void WM_toolsystem_ref_sync_from_context(Main *bmain, WorkSpace *workspace, bToolRef *tref)
{
bToolRef_Runtime *tref_rt = tref->runtime;
@@ -505,14 +498,6 @@ bool WM_toolsystem_key_from_context(ViewLayer *view_layer, ScrArea *area, bToolK
return false;
}
-/**
- * Use to update the active tool (shown in the top bar) in the least disruptive way.
- *
- * This is a little involved since there may be multiple valid active tools
- * depending on the mode and space type.
- *
- * Used when undoing since the active mode may have changed.
- */
void WM_toolsystem_refresh_active(bContext *C)
{
Main *bmain = CTX_data_main(C);
@@ -800,16 +785,12 @@ void WM_toolsystem_update_from_context(bContext *C,
}
}
-/**
- * For paint modes to support non-brush tools.
- */
bool WM_toolsystem_active_tool_is_brush(const bContext *C)
{
bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
return tref_rt && (tref_rt->data_block[0] != '\0');
}
-/* Follow wmMsgNotifyFn spec */
void WM_toolsystem_do_msg_notify_tag_refresh(bContext *C,
wmMsgSubscribeKey *UNUSED(msg_key),
wmMsgSubscribeValue *msg_val)
diff --git a/source/blender/windowmanager/intern/wm_uilist_type.c b/source/blender/windowmanager/intern/wm_uilist_type.c
index 82ba4aa6e6f..a2ae42d5ead 100644
--- a/source/blender/windowmanager/intern/wm_uilist_type.c
+++ b/source/blender/windowmanager/intern/wm_uilist_type.c
@@ -131,7 +131,6 @@ void WM_uilisttype_remove_ptr(Main *bmain, uiListType *ult)
UNUSED_VARS_NDEBUG(ok);
}
-/* called on initialize WM_init() */
void WM_uilisttype_init(void)
{
uilisttypes_hash = BLI_ghash_str_new_ex("uilisttypes_hash gh", 16);
@@ -151,16 +150,6 @@ void WM_uilisttype_free(void)
uilisttypes_hash = NULL;
}
-/**
- * The "full" list-ID is an internal name used for storing and identifying a list. It is built like
- * this:
- * "{uiListType.idname}_{list_id}", whereby "list_id" is an optional parameter passed to
- * `UILayout.template_list()`. If it is not set, the full list-ID is just "{uiListType.idname}_".
- *
- * Note that whenever the Python API refers to the list-ID, it's the short, "non-full" one it
- * passed to `UILayout.template_list()`. C code can query that through
- * #WM_uilisttype_list_id_get().
- */
void WM_uilisttype_to_full_list_id(const uiListType *ult,
const char *list_id,
char r_full_list_id[/*UI_MAX_NAME_STR*/])
@@ -169,11 +158,6 @@ void WM_uilisttype_to_full_list_id(const uiListType *ult,
BLI_snprintf(r_full_list_id, UI_MAX_NAME_STR, "%s_%s", ult->idname, list_id ? list_id : "");
}
-/**
- * Get the "non-full" list-ID, see #WM_uilisttype_to_full_list_id() for details.
- *
- * \note Assumes `uiList.list_id` was set using #WM_uilisttype_to_full_list_id()!
- */
const char *WM_uilisttype_list_id_get(const uiListType *ult, uiList *list)
{
/* Some sanity check for the assumed behavior of #WM_uilisttype_to_full_list_id(). */
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 5f684a752d8..29c9f53f735 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -136,8 +136,6 @@ static struct WMInitStruct {
static void wm_window_set_drawable(wmWindowManager *wm, wmWindow *win, bool activate);
static bool wm_window_timer(const bContext *C);
-/* XXX this one should correctly check for apple top header...
- * done for Cocoa : returns window contents (and not frame) max size. */
void wm_get_screensize(int *r_width, int *r_height)
{
unsigned int uiwidth;
@@ -148,7 +146,6 @@ void wm_get_screensize(int *r_width, int *r_height)
*r_height = uiheight;
}
-/* size of all screens (desktop), useful since the mouse is bound by this */
void wm_get_desktopsize(int *r_width, int *r_height)
{
unsigned int uiwidth;
@@ -198,8 +195,6 @@ static void wm_ghostwindow_destroy(wmWindowManager *wm, wmWindow *win)
}
}
-/* including window itself, C can be NULL.
- * ED_screen_exit should have been called */
void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
{
/* update context */
@@ -260,7 +255,6 @@ static int find_free_winid(wmWindowManager *wm)
return id;
}
-/* don't change context itself */
wmWindow *wm_window_new(const Main *bmain, wmWindowManager *wm, wmWindow *parent, bool dialog)
{
wmWindow *win = MEM_callocN(sizeof(wmWindow), "window");
@@ -276,7 +270,6 @@ wmWindow *wm_window_new(const Main *bmain, wmWindowManager *wm, wmWindow *parent
return win;
}
-/* part of wm_window.c api */
wmWindow *wm_window_copy(Main *bmain,
wmWindowManager *wm,
wmWindow *win_src,
@@ -307,10 +300,6 @@ wmWindow *wm_window_copy(Main *bmain,
return win_dst;
}
-/**
- * A higher level version of copy that tests the new window can be added.
- * (called from the operator directly)
- */
wmWindow *wm_window_copy_test(bContext *C,
wmWindow *win_src,
const bool duplicate_layout,
@@ -353,13 +342,6 @@ static void wm_confirm_quit(bContext *C)
wm_close_file_dialog(C, action);
}
-/**
- * Call the quit confirmation prompt or exit directly if needed. The use can
- * still cancel via the confirmation popup. Also, this may not quit Blender
- * immediately, but rather schedule the closing.
- *
- * \param win: The window to show the confirmation popup/window in.
- */
void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
{
wmWindow *win_ctx = CTX_wm_window(C);
@@ -387,7 +369,6 @@ void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
/** \} */
-/* this is event from ghost, or exit-blender op */
void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
{
wmWindow *win_other;
@@ -447,13 +428,14 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
}
else if (win->ghostwin) {
/* this is set to 1 if you don't have startup.blend open */
- if (G.save_over && BKE_main_blendfile_path_from_global()[0]) {
- char str[sizeof(((Main *)NULL)->name) + 24];
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
+ if (blendfile_path[0] != '\0') {
+ char str[sizeof(((Main *)NULL)->filepath) + 24];
BLI_snprintf(str,
sizeof(str),
"Blender%s [%s%s]",
wm->file_saved ? "" : "*",
- BKE_main_blendfile_path_from_global(),
+ blendfile_path,
G_MAIN->recovered ? " (Recovered)" : "");
GHOST_SetTitle(win->ghostwin, str);
}
@@ -679,19 +661,6 @@ static void wm_window_ghostwindow_ensure(wmWindowManager *wm, wmWindow *win, boo
ED_screen_global_areas_refresh(win);
}
-/**
- * Initialize #wmWindow without ghostwin, open these and clear.
- *
- * window size is read from window, if 0 it uses prefsize
- * called in #WM_check, also inits stuff after file read.
- *
- * \warning
- * After running, 'win->ghostwin' can be NULL in rare cases
- * (where OpenGL driver fails to create a context for eg).
- * We could remove them with #wm_window_ghostwindows_remove_invalid
- * but better not since caller may continue to use.
- * Instead, caller needs to handle the error case and cleanup.
- */
void wm_window_ghostwindows_ensure(wmWindowManager *wm)
{
BLI_assert(G.background == false);
@@ -715,10 +684,6 @@ void wm_window_ghostwindows_ensure(wmWindowManager *wm)
}
}
-/**
- * Call after #wm_window_ghostwindows_ensure or #WM_check
- * (after loading a new file) in the unlikely event a window couldn't be created.
- */
void wm_window_ghostwindows_remove_invalid(bContext *C, wmWindowManager *wm)
{
BLI_assert(G.background == false);
@@ -756,14 +721,6 @@ static bool wm_window_update_size_position(wmWindow *win)
return false;
}
-/**
- * \param space_type: SPACE_VIEW3D, SPACE_INFO, ... (eSpace_Type)
- * \param toplevel: Not a child owned by other windows. A peer of main window.
- * \param dialog: whether this should be made as a dialog-style window
- * \param temp: whether this is considered a short-lived window
- * \param alignment: how this window is positioned relative to its parent
- * \return the window or NULL in case of failure.
- */
wmWindow *WM_window_open(bContext *C,
const char *title,
int x,
@@ -952,7 +909,6 @@ int wm_window_new_main_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/* fullscreen operator callback */
int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
wmWindow *window = CTX_wm_window(C);
@@ -1083,7 +1039,6 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
}
}
-/* Reset active the current window opengl drawing context. */
void wm_window_reset_drawable(void)
{
BLI_assert(BLI_thread_is_main());
@@ -1585,10 +1540,6 @@ void wm_window_process_events(const bContext *C)
/** \name Ghost Init/Exit
* \{ */
-/**
- * \note #bContext can be null in background mode because we don't
- * need to event handling.
- */
void wm_ghost_init(bContext *C)
{
if (!g_system) {
@@ -1627,7 +1578,6 @@ void wm_ghost_exit(void)
/** \name Event Timer
* \{ */
-/* to (de)activate running timers temporary */
void WM_event_timer_sleep(wmWindowManager *wm,
wmWindow *UNUSED(win),
wmTimer *timer,
@@ -1769,19 +1719,11 @@ static char *wm_clipboard_text_get_ex(bool selection, int *r_len, bool firstline
return newbuf;
}
-/**
- * Return text from the clipboard.
- *
- * \note Caller needs to check for valid utf8 if this is a requirement.
- */
char *WM_clipboard_text_get(bool selection, int *r_len)
{
return wm_clipboard_text_get_ex(selection, r_len, false);
}
-/**
- * Convenience function for pasting to areas of Blender which don't support newlines.
- */
char *WM_clipboard_text_get_firstline(bool selection, int *r_len)
{
return wm_clipboard_text_get_ex(selection, r_len, true);
@@ -1890,9 +1832,6 @@ void wm_window_raise(wmWindow *win)
/** \name Window Buffers
* \{ */
-/**
- * \brief Push rendered buffer to the screen.
- */
void wm_window_swap_buffers(wmWindow *win)
{
GHOST_SwapWindowBuffers(win->ghostwin);
@@ -1913,6 +1852,7 @@ bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut)
/* -------------------------------------------------------------------- */
/** \name Find Window Utility
* \{ */
+
static void wm_window_desktop_pos_get(const wmWindow *win,
const int screen_pos[2],
int r_desk_pos[2])
@@ -2034,7 +1974,6 @@ uint *WM_window_pixels_read(wmWindowManager *wm, wmWindow *win, int r_size[2])
/** \name Initial Window State API
* \{ */
-/* called whem no ghost system was initialized */
void WM_init_state_size_set(int stax, int stay, int sizx, int sizy)
{
wm_init_state.start_x = stax; /* left hand pos */
@@ -2044,7 +1983,6 @@ void WM_init_state_size_set(int stax, int stay, int sizx, int sizy)
wm_init_state.override_flag |= WIN_OVERRIDE_GEOM;
}
-/* for borderless and border windows set from command-line */
void WM_init_state_fullscreen_set(void)
{
wm_init_state.windowstate = GHOST_kWindowStateFullScreen;
@@ -2097,7 +2035,6 @@ void WM_init_tablet_api(void)
}
}
-/* This function requires access to the GHOST_SystemHandle (g_system) */
void WM_cursor_warp(wmWindow *win, int x, int y)
{
if (win && win->ghostwin) {
@@ -2114,9 +2051,6 @@ void WM_cursor_warp(wmWindow *win, int x, int y)
}
}
-/**
- * Set x, y to values we can actually position the cursor to.
- */
void WM_cursor_compatible_xy(wmWindow *win, int *x, int *y)
{
float f = GHOST_GetNativePixelSize(win->ghostwin);
@@ -2132,11 +2066,6 @@ void WM_cursor_compatible_xy(wmWindow *win, int *x, int *y)
/** \name Window Size (public)
* \{ */
-/**
- * Support for native pixel size
- *
- * \note macOS retina opens window in size X, but it has up to 2 x more pixels.
- */
int WM_window_pixels_x(const wmWindow *win)
{
float f = GHOST_GetNativePixelSize(win->ghostwin);
@@ -2150,17 +2079,10 @@ int WM_window_pixels_y(const wmWindow *win)
return (int)(f * (float)win->sizey);
}
-/**
- * Get boundaries usable by all window contents, including global areas.
- */
void WM_window_rect_calc(const wmWindow *win, rcti *r_rect)
{
BLI_rcti_init(r_rect, 0, WM_window_pixels_x(win), 0, WM_window_pixels_y(win));
}
-/**
- * Get boundaries usable by screen-layouts, excluding global areas.
- * \note Depends on U.dpi_fac. Should that be outdated, call #WM_window_set_dpi first.
- */
void WM_window_screen_rect_calc(const wmWindow *win, rcti *r_rect)
{
rcti window_rect, screen_rect;
@@ -2210,11 +2132,6 @@ bool WM_window_is_maximized(const wmWindow *win)
/** \name Window Screen/Scene/WorkSpaceViewLayer API
* \{ */
-/**
- * Some editor data may need to be synced with scene data (3D View camera and layers).
- * This function ensures data is synced for editors
- * in visible workspaces and their visible layouts.
- */
void WM_windows_scene_data_sync(const ListBase *win_lb, Scene *scene)
{
LISTBASE_FOREACH (wmWindow *, win, win_lb) {
@@ -2261,9 +2178,6 @@ Scene *WM_window_get_active_scene(const wmWindow *win)
return win->scene;
}
-/**
- * \warning Only call outside of area/region loops
- */
void WM_window_set_active_scene(Main *bmain, bContext *C, wmWindow *win, Scene *scene)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -2376,9 +2290,6 @@ void WM_window_set_active_layout(wmWindow *win, WorkSpace *workspace, WorkSpaceL
BKE_workspace_active_layout_set(win->workspace_hook, win->winid, workspace, layout);
}
-/**
- * Get the active screen of the active workspace in \a win.
- */
bScreen *WM_window_get_active_screen(const wmWindow *win)
{
const WorkSpace *workspace = WM_window_get_active_workspace(win);
@@ -2481,4 +2392,5 @@ void WM_ghost_show_message_box(const char *title,
BLI_assert(g_system);
GHOST_ShowMessageBox(g_system, title, message, help_label, continue_label, link, dialog_options);
}
+
/** \} */
diff --git a/source/blender/windowmanager/message_bus/intern/wm_message_bus.c b/source/blender/windowmanager/message_bus/intern/wm_message_bus.c
index 86a106462c3..81ef8c881f5 100644
--- a/source/blender/windowmanager/message_bus/intern/wm_message_bus.c
+++ b/source/blender/windowmanager/message_bus/intern/wm_message_bus.c
@@ -147,16 +147,6 @@ void WM_msgbus_handle(struct wmMsgBus *mbus, struct bContext *C)
// printf("msgbus: keys=%u values=%u\n", a, b);
}
-/**
- * \param msg_key_test: Needs following #wmMsgSubscribeKey fields filled in:
- * - msg.params
- * - msg.head.type
- * - msg.head.id
- * .. other values should be zeroed.
- *
- * \return The key for this subscription.
- * note that this is only needed in rare cases when the key needs further manipulation.
- */
wmMsgSubscribeKey *WM_msg_subscribe_with_key(struct wmMsgBus *mbus,
const wmMsgSubscribeKey *msg_key_test,
const wmMsgSubscribeValue *msg_val_params)
@@ -239,9 +229,6 @@ void WM_msg_id_remove(struct wmMsgBus *mbus, const struct ID *id)
* \note While we could have a separate type for ID's, use RNA since there is enough overlap.
* \{ */
-/**
- * \note #wmMsgBus.messages_tag_count isn't updated, caller must handle.
- */
void wm_msg_subscribe_value_free(wmMsgSubscribeKey *msg_key, wmMsgSubscribeValueLink *msg_lnk)
{
if (msg_lnk->params.free_data) {
diff --git a/source/blender/windowmanager/message_bus/intern/wm_message_bus_intern.h b/source/blender/windowmanager/message_bus/intern/wm_message_bus_intern.h
index 24c0192fe14..18df17c3d1c 100644
--- a/source/blender/windowmanager/message_bus/intern/wm_message_bus_intern.h
+++ b/source/blender/windowmanager/message_bus/intern/wm_message_bus_intern.h
@@ -30,6 +30,9 @@ struct wmMsgBus {
uint messages_tag_count;
};
+/**
+ * \note #wmMsgBus.messages_tag_count isn't updated, caller must handle.
+ */
void wm_msg_subscribe_value_free(struct wmMsgSubscribeKey *msg_key,
struct wmMsgSubscribeValueLink *msg_lnk);
diff --git a/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c b/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c
index 460dca57e4f..bc083793395 100644
--- a/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c
+++ b/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c
@@ -35,7 +35,9 @@
#include "RNA_access.h"
-/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------- */
+/** \name Internal Utilities
+ * \{ */
BLI_INLINE uint void_hash_uint(const void *key)
{
@@ -208,7 +210,11 @@ void WM_msgtypeinfo_init_rna(wmMsgTypeInfo *msgtype_info)
msgtype_info->msg_key_size = sizeof(wmMsgSubscribeKey_RNA);
}
-/* -------------------------------------------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name RNA API
+ * \{ */
wmMsgSubscribeKey_RNA *WM_msg_lookup_rna(struct wmMsgBus *mbus,
const wmMsgParams_RNA *msg_key_params)
diff --git a/source/blender/windowmanager/message_bus/wm_message_bus.h b/source/blender/windowmanager/message_bus/wm_message_bus.h
index 7ae356cf806..7ee2e5b6ee6 100644
--- a/source/blender/windowmanager/message_bus/wm_message_bus.h
+++ b/source/blender/windowmanager/message_bus/wm_message_bus.h
@@ -79,7 +79,7 @@ typedef struct wmMsg {
} wmMsg;
typedef struct wmMsgSubscribeKey {
- /** Linked list for predicable ordering, otherwise we would depend on ghash bucketing. */
+ /** Linked list for predicable ordering, otherwise we would depend on #GHash bucketing. */
struct wmMsgSubscribeKey *next, *prev;
ListBase values;
/* over-alloc, eg: wmMsgSubscribeKey_RNA */
@@ -124,6 +124,16 @@ void WM_msg_dump(struct wmMsgBus *mbus, const char *info);
void WM_msgbus_handle(struct wmMsgBus *mbus, struct bContext *C);
void WM_msg_publish_with_key(struct wmMsgBus *mbus, wmMsgSubscribeKey *msg_key);
+/**
+ * \param msg_key_test: Needs following #wmMsgSubscribeKey fields filled in:
+ * - `msg.params`
+ * - `msg.head.type`
+ * - `msg.head.id`
+ * .. other values should be zeroed.
+ *
+ * \return The key for this subscription.
+ * note that this is only needed in rare cases when the key needs further manipulation.
+ */
wmMsgSubscribeKey *WM_msg_subscribe_with_key(struct wmMsgBus *mbus,
const wmMsgSubscribeKey *msg_key_test,
const wmMsgSubscribeValue *msg_val_params);
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index cfef70b7dcc..e67b1581875 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -43,49 +43,98 @@ typedef struct wmPaintCursor {
short region_type;
} wmPaintCursor;
+/**
+ * Cause a delayed #WM_exit()
+ * call to avoid leaking memory when trying to exit from within operators.
+ */
void wm_exit_schedule_delayed(const bContext *C);
+/**
+ * Context is allowed to be NULL, do not free wm itself (lib_id.c).
+ */
extern void wm_close_and_free(bContext *C, wmWindowManager *);
extern void wm_close_and_free_all(bContext *C, ListBase *);
+/**
+ * On startup, it adds all data, for matching.
+ */
extern void wm_add_default(struct Main *bmain, bContext *C);
extern void wm_clear_default_size(bContext *C);
/* register to windowmanager for redo or macro */
+
+/**
+ * Called on event handling by `event_system.c`.
+ *
+ * All operations get registered in the windowmanager here.
+ */
void wm_operator_register(bContext *C, wmOperator *op);
/* wm_operator.c, for init/exit */
+
void wm_operatortype_free(void);
+/**
+ * Called on initialize #WM_init().
+ */
void wm_operatortype_init(void);
+/**
+ * Default key-map for windows and screens, only call once per WM.
+ */
void wm_window_keymap(wmKeyConfig *keyconf);
void wm_operatortypes_register(void);
/* wm_gesture.c */
+/* called in wm_draw.c */
+
void wm_gesture_draw(struct wmWindow *win);
+/**
+ * Tweak and line gestures.
+ */
int wm_gesture_evaluate(wmGesture *gesture, const struct wmEvent *event);
void wm_gesture_tag_redraw(struct wmWindow *win);
/* wm_gesture_ops.c */
+
+/**
+ * Standard tweak, called after window handlers passed on event.
+ */
void wm_tweakevent_test(bContext *C, const wmEvent *event, int action);
/* wm_jobs.c */
+
+/**
+ * Hard-coded to event #TIMERJOBS.
+ */
void wm_jobs_timer(wmWindowManager *wm, wmTimer *wt);
+/**
+ * Kill job entirely, also removes timer itself.
+ */
void wm_jobs_timer_end(wmWindowManager *wm, wmTimer *wt);
/* wm_files.c */
+
+/**
+ * Run the auto-save timer action.
+ */
void wm_autosave_timer(struct Main *bmain, wmWindowManager *wm, wmTimer *wt);
void wm_autosave_timer_begin(struct wmWindowManager *wm);
void wm_autosave_timer_end(wmWindowManager *wm);
void wm_autosave_delete(void);
/* wm_splash_screen.c */
+
void WM_OT_splash(wmOperatorType *ot);
void WM_OT_splash_about(wmOperatorType *ot);
/* wm_stereo.c */
+
void wm_stereo3d_draw_sidebyside(wmWindow *win, int view);
void wm_stereo3d_draw_topbottom(wmWindow *win, int view);
+/**
+ * If needed, adjust \a r_mouse_xy
+ * so that drawn cursor and handled mouse position are matching visually.
+ */
void wm_stereo3d_mouse_offset_apply(wmWindow *win, int r_mouse_xy[2]);
int wm_stereo3d_set_exec(bContext *C, wmOperator *op);
int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *event);
@@ -93,7 +142,9 @@ void wm_stereo3d_set_draw(bContext *C, wmOperator *op);
bool wm_stereo3d_set_check(bContext *C, wmOperator *op);
void wm_stereo3d_set_cancel(bContext *C, wmOperator *op);
-/* init operator properties */
+/**
+ * Initialize operator properties.
+ */
void wm_open_init_load_ui(wmOperator *op, bool use_prefs);
void wm_open_init_use_scripts(wmOperator *op, bool use_prefs);
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index 9b0f128d071..925be8ab183 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -144,20 +144,36 @@ typedef struct wmEventHandler_Dropbox {
} wmEventHandler_Dropbox;
/* wm_event_system.c */
+
void wm_event_free_all(wmWindow *win);
void wm_event_free(wmEvent *event);
void wm_event_free_handler(wmEventHandler *handler);
-/* goes over entire hierarchy: events -> window -> screen -> area -> region */
+/**
+ * Goes over entire hierarchy: events -> window -> screen -> area -> region.
+ *
+ * \note Called in main loop.
+ */
void wm_event_do_handlers(bContext *C);
+/**
+ * Windows store own event queues #wmWindow.event_queue (no #bContext here).
+ */
void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void *customdata);
#ifdef WITH_XR_OPENXR
void wm_event_add_xrevent(wmWindow *win, struct wmXrActionData *actiondata, short val);
#endif
void wm_event_do_depsgraph(bContext *C, bool is_after_open_file);
+/**
+ * Was part of #wm_event_do_notifiers,
+ * split out so it can be called once before entering the #WM_main loop.
+ * This ensures operators don't run before the UI and depsgraph are initialized.
+ */
void wm_event_do_refresh_wm_and_depsgraph(bContext *C);
+/**
+ * Called in main-loop.
+ */
void wm_event_do_notifiers(bContext *C);
void wm_event_handler_ui_cancel_ex(bContext *C,
@@ -166,17 +182,36 @@ void wm_event_handler_ui_cancel_ex(bContext *C,
bool reactivate_button);
/* wm_event_query.c */
+
+/**
+ * Applies the global tablet pressure correction curve.
+ */
float wm_pressure_curve(float raw_pressure);
void wm_tablet_data_from_ghost(const struct GHOST_TabletData *tablet_data, wmTabletData *wmtab);
-/* wm_keymap.c */
-
/* wm_dropbox.c */
+
void wm_dropbox_free(void);
+/**
+ * Additional work to cleanly end dragging. Additional because this doesn't actually remove the
+ * drag items. Should be called whenever dragging is stopped
+ * (successful or not, also when canceled).
+ */
void wm_drags_exit(wmWindowManager *wm, wmWindow *win);
void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop);
+/**
+ * Called in inner handler loop, region context.
+ */
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 *drop);
+/**
+ * Called in #wm_draw_window_onscreen.
+ */
void wm_drags_draw(bContext *C, wmWindow *win);
#ifdef __cplusplus
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index c175c211db6..437bd1057c2 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -405,7 +405,7 @@ enum {
#define _VA_IS_EVENT_MOD4(v, a, b, c) (_VA_IS_EVENT_MOD3(v, a, b) || ((v)->c))
#define _VA_IS_EVENT_MOD5(v, a, b, c, d) (_VA_IS_EVENT_MOD4(v, a, b, c) || ((v)->d))
-/* reusable IS_EVENT_MOD(event, shift, ctrl, alt, oskey), macro */
+/** Reusable `IS_EVENT_MOD(event, shift, ctrl, alt, oskey)` macro. */
#define IS_EVENT_MOD(...) VA_NARGS_CALL_OVERLOAD(_VA_IS_EVENT_MOD, __VA_ARGS__)
enum eEventType_Mask {
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index 135f31cf8ac..e63afb2ed2f 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -33,6 +33,7 @@ extern "C" {
#endif
/* wm_files.c */
+
void wm_history_file_read(void);
struct wmHomeFileRead_Params {
@@ -62,6 +63,16 @@ struct wmHomeFileRead_Params {
const char *app_template_override;
};
+/**
+ * Called on startup, (context entirely filled with NULLs)
+ * or called for 'New File' both `startup.blend` and `userpref.blend` are checked.
+ *
+ * \param r_params_file_read_post: Support postponed initialization,
+ * needed for initial startup when only some sub-systems have been initialized.
+ * When non-null, #wm_file_read_post doesn't run, instead it's arguments are stored
+ * in this return argument.
+ * The caller is responsible for calling #wm_homefile_read_post with this return argument.
+ */
void wm_homefile_read_ex(struct bContext *C,
const struct wmHomeFileRead_Params *params_homefile,
struct ReportList *reports,
@@ -70,15 +81,26 @@ void wm_homefile_read(struct bContext *C,
const struct wmHomeFileRead_Params *params_homefile,
struct ReportList *reports);
+/**
+ * Special case, support deferred execution of #wm_file_read_post,
+ * Needed when loading for the first time to workaround order of initialization bug, see T89046.
+ */
void wm_homefile_read_post(struct bContext *C,
const struct wmFileReadPost_Params *params_file_read_post);
void wm_file_read_report(bContext *C, struct Main *bmain);
void wm_close_file_dialog(bContext *C, struct wmGenericCallback *post_action);
+/**
+ * \return True if the dialog was created, the calling operator should return #OPERATOR_INTERFACE
+ * then.
+ */
bool wm_operator_close_file_dialog_if_needed(bContext *C,
wmOperator *op,
wmGenericCallbackFn exec_fn);
+/**
+ * Check if there is data that would be lost when closing the current file without saving.
+ */
bool wm_file_or_session_data_has_unsaved_changes(const Main *bmain, const wmWindowManager *wm);
void WM_OT_save_homefile(struct wmOperatorType *ot);
@@ -99,6 +121,7 @@ void WM_OT_save_as_mainfile(struct wmOperatorType *ot);
void WM_OT_save_mainfile(struct wmOperatorType *ot);
/* wm_files_link.c */
+
void WM_OT_link(struct wmOperatorType *ot);
void WM_OT_append(struct wmOperatorType *ot);
diff --git a/source/blender/windowmanager/wm_surface.h b/source/blender/windowmanager/wm_surface.h
index a2483d38154..e924b1e47ad 100644
--- a/source/blender/windowmanager/wm_surface.h
+++ b/source/blender/windowmanager/wm_surface.h
@@ -39,6 +39,8 @@ typedef struct wmSurface {
void *customdata;
void (*draw)(struct bContext *);
+ /* To evaluate the surface's depsgraph. Called as part of the main loop. */
+ void (*do_depsgraph)(struct bContext *C);
/** Free customdata, not the surface itself (done by wm_surface API) */
void (*free_data)(struct wmSurface *);
@@ -56,6 +58,9 @@ void wm_surfaces_free(void);
/* Utils */
void wm_surfaces_iter(struct bContext *C, void (*cb)(struct bContext *, wmSurface *));
+/* Evaluation. */
+void wm_surfaces_do_depsgraph(struct bContext *C);
+
/* Drawing */
void wm_surface_make_drawable(wmSurface *surface);
void wm_surface_clear_drawable(void);
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index f205f923ec8..e44a39ecf1a 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -30,41 +30,93 @@ extern "C" {
#endif
/* *************** internal api ************** */
+
+/**
+ * \note #bContext can be null in background mode because we don't
+ * need to event handling.
+ */
void wm_ghost_init(bContext *C);
void wm_ghost_exit(void);
+/**
+ * This one should correctly check for apple top header...
+ * done for Cocoa: returns window contents (and not frame) max size.
+ */
void wm_get_screensize(int *r_width, int *r_height);
+/**
+ * Size of all screens (desktop), useful since the mouse is bound by this.
+ */
void wm_get_desktopsize(int *r_width, int *r_height);
+/**
+ * Don't change context itself.
+ */
wmWindow *wm_window_new(const struct Main *bmain,
wmWindowManager *wm,
wmWindow *parent,
bool dialog);
+/**
+ * Part of `wm_window.c` API.
+ */
wmWindow *wm_window_copy(struct Main *bmain,
wmWindowManager *wm,
wmWindow *win_src,
const bool duplicate_layout,
const bool child);
+/**
+ * A higher level version of copy that tests the new window can be added.
+ * (called from the operator directly).
+ */
wmWindow *wm_window_copy_test(bContext *C,
wmWindow *win_src,
const bool duplicate_layout,
const bool child);
+/**
+ * Including window itself.
+ * \param C: can be NULL.
+ * \note #ED_screen_exit should have been called.
+ */
void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win);
+/**
+ * This is event from ghost, or exit-Blender operator.
+ */
void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win);
void wm_window_title(wmWindowManager *wm, wmWindow *win);
+/**
+ * Initialize #wmWindow without `ghostwin`, open these and clear.
+ *
+ * Window size is read from window, if 0 it uses prefsize
+ * called in #WM_check, also initialize stuff after file read.
+ *
+ * \warning After running, `win->ghostwin` can be NULL in rare cases
+ * (where OpenGL driver fails to create a context for eg).
+ * We could remove them with #wm_window_ghostwindows_remove_invalid
+ * but better not since caller may continue to use.
+ * Instead, caller needs to handle the error case and cleanup.
+ */
void wm_window_ghostwindows_ensure(wmWindowManager *wm);
+/**
+ * Call after #wm_window_ghostwindows_ensure or #WM_check
+ * (after loading a new file) in the unlikely event a window couldn't be created.
+ */
void wm_window_ghostwindows_remove_invalid(bContext *C, wmWindowManager *wm);
void wm_window_process_events(const bContext *C);
void wm_window_clear_drawable(wmWindowManager *wm);
void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win);
+/**
+ * Reset active the current window opengl drawing context.
+ */
void wm_window_reset_drawable(void);
void wm_window_raise(wmWindow *win);
void wm_window_lower(wmWindow *win);
void wm_window_set_size(wmWindow *win, int width, int height);
void wm_window_get_position(wmWindow *win, int *r_pos_x, int *r_pos_y);
+/**
+ * \brief Push rendered buffer to the screen.
+ */
void wm_window_swap_buffers(wmWindow *win);
void wm_window_set_swap_interval(wmWindow *win, int interval);
bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut);
@@ -79,8 +131,19 @@ void wm_window_IME_end(wmWindow *win);
#endif
/* *************** window operators ************** */
+
int wm_window_close_exec(bContext *C, struct wmOperator *op);
+/**
+ * Full-screen operator callback.
+ */
int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op);
+/**
+ * Call the quit confirmation prompt or exit directly if needed. The use can
+ * still cancel via the confirmation popup. Also, this may not quit Blender
+ * immediately, but rather schedule the closing.
+ *
+ * \param win: The window to show the confirmation popup/window in.
+ */
void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win) ATTR_NONNULL();
int wm_window_new_exec(bContext *C, struct wmOperator *op);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c b/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c
index 8903305adb4..076f279ccbb 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c
@@ -85,9 +85,6 @@ static XrActionMapBinding *wm_xr_actionmap_binding_find_except(XrActionMapItem *
return NULL;
}
-/**
- * Ensure unique name among all action map bindings.
- */
void WM_xr_actionmap_binding_ensure_unique(XrActionMapItem *ami, XrActionMapBinding *amb)
{
char name[MAX_NAME];
@@ -118,7 +115,6 @@ void WM_xr_actionmap_binding_ensure_unique(XrActionMapItem *ami, XrActionMapBind
static XrActionMapBinding *wm_xr_actionmap_binding_copy(XrActionMapBinding *amb_src)
{
XrActionMapBinding *amb_dst = MEM_dupallocN(amb_src);
-
amb_dst->prev = amb_dst->next = NULL;
return amb_dst;
@@ -198,10 +194,6 @@ static void wm_xr_actionmap_item_properties_free(XrActionMapItem *ami)
}
}
-/**
- * Similar to #wm_xr_actionmap_item_properties_set()
- * but checks for the #eXrActionType and #wmOperatorType having changed.
- */
void WM_xr_actionmap_item_properties_update_ot(XrActionMapItem *ami)
{
switch (ami->type) {
@@ -278,9 +270,6 @@ static XrActionMapItem *wm_xr_actionmap_item_find_except(XrActionMap *actionmap,
return NULL;
}
-/**
- * Ensure unique name among all action map items.
- */
void WM_xr_actionmap_item_ensure_unique(XrActionMap *actionmap, XrActionMapItem *ami)
{
char name[MAX_NAME];
@@ -308,25 +297,29 @@ void WM_xr_actionmap_item_ensure_unique(XrActionMap *actionmap, XrActionMapItem
BLI_strncpy(ami->name, name, MAX_NAME);
}
-static XrActionMapItem *wm_xr_actionmap_item_copy(XrActionMapItem *ami)
+static XrActionMapItem *wm_xr_actionmap_item_copy(XrActionMapItem *ami_src)
{
- XrActionMapItem *amin = MEM_dupallocN(ami);
-
- amin->prev = amin->next = NULL;
+ XrActionMapItem *ami_dst = MEM_dupallocN(ami_src);
+ ami_dst->prev = ami_dst->next = NULL;
- if (amin->op_properties) {
- amin->op_properties_ptr = MEM_callocN(sizeof(PointerRNA), "wmOpItemPtr");
- WM_operator_properties_create(amin->op_properties_ptr, amin->op);
+ BLI_listbase_clear(&ami_dst->bindings);
+ LISTBASE_FOREACH (XrActionMapBinding *, amb, &ami_src->bindings) {
+ XrActionMapBinding *amb_new = wm_xr_actionmap_binding_copy(amb);
+ BLI_addtail(&ami_dst->bindings, amb_new);
+ }
- amin->op_properties = IDP_CopyProperty(amin->op_properties);
- amin->op_properties_ptr->data = amin->op_properties;
+ if (ami_dst->op_properties) {
+ ami_dst->op_properties_ptr = MEM_callocN(sizeof(PointerRNA), "wmOpItemPtr");
+ WM_operator_properties_create(ami_dst->op_properties_ptr, ami_dst->op);
+ ami_dst->op_properties = IDP_CopyProperty(ami_src->op_properties);
+ ami_dst->op_properties_ptr->data = ami_dst->op_properties;
}
else {
- amin->op_properties = NULL;
- amin->op_properties_ptr = NULL;
+ ami_dst->op_properties = NULL;
+ ami_dst->op_properties_ptr = NULL;
}
- return amin;
+ return ami_dst;
}
XrActionMapItem *WM_xr_actionmap_item_add_copy(XrActionMap *actionmap, XrActionMapItem *ami_src)
@@ -411,9 +404,6 @@ static XrActionMap *wm_xr_actionmap_find_except(wmXrRuntimeData *runtime,
return NULL;
}
-/**
- * Ensure unique name among all action maps.
- */
void WM_xr_actionmap_ensure_unique(wmXrRuntimeData *runtime, XrActionMap *actionmap)
{
char name[MAX_NAME];
@@ -444,10 +434,9 @@ void WM_xr_actionmap_ensure_unique(wmXrRuntimeData *runtime, XrActionMap *action
static XrActionMap *wm_xr_actionmap_copy(XrActionMap *am_src)
{
XrActionMap *am_dst = MEM_dupallocN(am_src);
-
am_dst->prev = am_dst->next = NULL;
- BLI_listbase_clear(&am_dst->items);
+ BLI_listbase_clear(&am_dst->items);
LISTBASE_FOREACH (XrActionMapItem *, ami, &am_src->items) {
XrActionMapItem *ami_new = wm_xr_actionmap_item_copy(ami);
BLI_addtail(&am_dst->items, ami_new);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_draw.c b/source/blender/windowmanager/xr/intern/wm_xr_draw.c
index 72d88bb3043..5d0163af5e1 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_draw.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_draw.c
@@ -139,12 +139,6 @@ static void wm_xr_draw_viewport_buffers_to_active_framebuffer(
GPU_viewport_draw_to_screen_ex(vp->viewport, 0, &rect, draw_view->expects_srgb_buffer, true);
}
-/**
- * \brief Draw a viewport for a single eye.
- *
- * This is the main viewport drawing function for VR sessions. It's assigned to Ghost-XR as a
- * callback (see GHOST_XrDrawViewFunc()) and executed for each view (read: eye).
- */
void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
{
wmXrDrawData *draw_data = customdata;
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
index 7de1f254224..e2368901757 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h
+++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
@@ -213,6 +213,11 @@ void wm_xr_session_draw_data_update(wmXrSessionState *state,
const XrSessionSettings *settings,
const GHOST_XrDrawViewInfo *draw_view,
wmXrDrawData *draw_data);
+/**
+ * Update information that is only stored for external state queries. E.g. for Python API to
+ * request the current (as in, last known) viewer pose.
+ * Controller data and action sets will be updated separately via wm_xr_session_actions_update().
+ */
void wm_xr_session_state_update(const XrSessionSettings *settings,
const wmXrDrawData *draw_data,
const GHOST_XrDrawViewInfo *draw_view,
@@ -230,9 +235,16 @@ void wm_xr_session_controller_data_populate(const wmXrAction *grip_action,
void wm_xr_session_controller_data_clear(wmXrSessionState *state);
/* wm_xr_draw.c */
+
void wm_xr_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]);
void wm_xr_pose_scale_to_mat(const GHOST_XrPose *pose, float scale, float r_mat[4][4]);
void wm_xr_pose_to_imat(const GHOST_XrPose *pose, float r_imat[4][4]);
void wm_xr_pose_scale_to_imat(const GHOST_XrPose *pose, float scale, float r_imat[4][4]);
+/**
+ * \brief Draw a viewport for a single eye.
+ *
+ * This is the main viewport drawing function for VR sessions. It's assigned to Ghost-XR as a
+ * callback (see GHOST_XrDrawViewFunc()) and executed for each view (read: eye).
+ */
void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata);
void wm_xr_draw_controllers(const struct bContext *C, struct ARegion *region, void *customdata);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_operators.c b/source/blender/windowmanager/xr/intern/wm_xr_operators.c
index f3470edf2f7..c503f5d4fee 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_operators.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_operators.c
@@ -553,7 +553,7 @@ 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
+ /* 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). */
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c
index 3224869b04a..bad735ee598 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_session.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c
@@ -30,6 +30,7 @@
#include "BLI_math.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "DNA_camera_types.h"
#include "DNA_space_types.h"
@@ -154,10 +155,6 @@ void wm_xr_session_toggle(wmWindowManager *wm,
}
}
-/**
- * Check if the XR-Session was triggered.
- * If an error happened while trying to start a session, this returns false too.
- */
bool WM_xr_session_exists(const wmXrData *xr)
{
return xr->runtime && xr->runtime->context && xr->runtime->session_state.is_started;
@@ -168,9 +165,6 @@ void WM_xr_session_base_pose_reset(wmXrData *xr)
xr->runtime->session_state.force_reset_to_base_pose = true;
}
-/**
- * Check if the session is running, according to the OpenXR definition.
- */
bool WM_xr_session_is_ready(const wmXrData *xr)
{
return WM_xr_session_exists(xr) && GHOST_XrSessionIsRunning(xr->runtime->context);
@@ -250,10 +244,9 @@ wmWindow *wm_xr_session_root_window_or_fallback_get(const wmWindowManager *wm,
* It's important that the VR session follows some existing window, otherwise it would need to have
* an own depsgraph, which is an expense we should avoid.
*/
-static void wm_xr_session_scene_and_evaluated_depsgraph_get(Main *bmain,
- const wmWindowManager *wm,
- Scene **r_scene,
- Depsgraph **r_depsgraph)
+static void wm_xr_session_scene_and_depsgraph_get(const wmWindowManager *wm,
+ Scene **r_scene,
+ Depsgraph **r_depsgraph)
{
const wmWindow *root_win = wm_xr_session_root_window_or_fallback_get(wm, wm->xr.runtime);
@@ -263,7 +256,6 @@ static void wm_xr_session_scene_and_evaluated_depsgraph_get(Main *bmain,
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer);
BLI_assert(scene && view_layer && depsgraph);
- BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
*r_scene = scene;
*r_depsgraph = depsgraph;
}
@@ -354,11 +346,6 @@ void wm_xr_session_draw_data_update(wmXrSessionState *state,
}
}
-/**
- * Update information that is only stored for external state queries. E.g. for Python API to
- * request the current (as in, last known) viewer pose.
- * Controller data and action sets will be updated separately via wm_xr_session_actions_update().
- */
void wm_xr_session_state_update(const XrSessionSettings *settings,
const wmXrDrawData *draw_data,
const GHOST_XrDrawViewInfo *draw_view,
@@ -1314,7 +1301,6 @@ void wm_xr_session_controller_data_clear(wmXrSessionState *state)
static void wm_xr_session_surface_draw(bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
- Main *bmain = CTX_data_main(C);
wmXrDrawData draw_data;
if (!WM_xr_session_is_ready(&wm->xr)) {
@@ -1323,12 +1309,32 @@ static void wm_xr_session_surface_draw(bContext *C)
Scene *scene;
Depsgraph *depsgraph;
- wm_xr_session_scene_and_evaluated_depsgraph_get(bmain, wm, &scene, &depsgraph);
+ wm_xr_session_scene_and_depsgraph_get(wm, &scene, &depsgraph);
+ /* Might fail when force-redrawing windows with #WM_redraw_windows(), which is done on file
+ * writing for example. */
+ // BLI_assert(DEG_is_fully_evaluated(depsgraph));
wm_xr_session_draw_data_populate(&wm->xr, scene, depsgraph, &draw_data);
GHOST_XrSessionDrawViews(wm->xr.runtime->context, &draw_data);
- GPU_framebuffer_restore();
+ /* There's no active framebuffer if the session was cancelled (exception while drawing views). */
+ if (GPU_framebuffer_active_get()) {
+ GPU_framebuffer_restore();
+ }
+}
+
+static void wm_xr_session_do_depsgraph(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ if (!WM_xr_session_is_ready(&wm->xr)) {
+ return;
+ }
+
+ Scene *scene;
+ Depsgraph *depsgraph;
+ wm_xr_session_scene_and_depsgraph_get(wm, &scene, &depsgraph);
+ BKE_scene_graph_evaluated_ensure(depsgraph, CTX_data_main(C));
}
bool wm_xr_session_surface_offscreen_ensure(wmXrSurfaceData *surface_data,
@@ -1439,6 +1445,7 @@ static wmSurface *wm_xr_session_surface_create(void)
data->controller_art = MEM_callocN(sizeof(*(data->controller_art)), "XrControllerRegionType");
surface->draw = wm_xr_session_surface_draw;
+ surface->do_depsgraph = wm_xr_session_do_depsgraph;
surface->free_data = wm_xr_session_surface_free_data;
surface->activate = DRW_xr_drawing_begin;
surface->deactivate = DRW_xr_drawing_end;