diff options
author | Jacques Lucke <jacques@blender.org> | 2021-03-05 12:22:39 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-03-05 12:22:39 +0300 |
commit | 381e2d4dc2b2773e348bfb481ab22bb9d553986c (patch) | |
tree | 6f41b98209a8203391c40a19c3d7fb41b8ea3fa2 | |
parent | cf6208382eb6142085e7ce3052b177344ea156cc (diff) | |
parent | b5d154f400e46ba322f0e08a231bb2557bf51a1e (diff) |
Merge branch 'master' into temp-spreadsheet-editortemp-spreadsheet-editor
123 files changed, 869 insertions, 456 deletions
diff --git a/intern/clog/clog.c b/intern/clog/clog.c index 2bc3985c71f..a26ac10a61f 100644 --- a/intern/clog/clog.c +++ b/intern/clog/clog.c @@ -1,4 +1,4 @@ -/* +/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -38,8 +38,13 @@ #endif #if defined(_MSC_VER) +# include <Windows.h> + +# include <VersionHelpers.h> /* This needs to be included after Windows.h. */ # include <io.h> -# include <windows.h> +# if !defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) +# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 +# endif #endif /* For printing timestamp. */ @@ -228,6 +233,9 @@ enum eCLogColor { #define COLOR_LEN (COLOR_RESET + 1) static const char *clg_color_table[COLOR_LEN] = {NULL}; +#ifdef _WIN32 +static DWORD clg_previous_console_mode = 0; +#endif static void clg_color_table_init(bool use_color) { @@ -548,13 +556,22 @@ static void CLG_ctx_output_set(CLogContext *ctx, void *file_handle) #if defined(__unix__) || defined(__APPLE__) ctx->use_color = isatty(ctx->output); #elif defined(WIN32) - /* Windows Terminal supports color like the Linux terminals do while the standard console does - * not, the way to tell the two apart is to look at the `WT_SESSION` environment variable which - * will only be defined for Windows Terminal. */ - - /* #getenv is used here rather than #BLI_getenv since it would be a bad level call - * and there are no benefits for using it in this context. */ - ctx->use_color = isatty(ctx->output) && getenv("WT_SESSION"); + /* As of Windows 10 build 18298 all the standard consoles supports color + * like the Linux Terminal do, but it needs to be turned on. + * To turn on colors we need to enable virtual terminal processing by passing the flag + * ENABLE_VIRTUAL_TERMINAL_PROCESSING into SetConsoleMode. + * If the system doesn't support virtual terminal processing it will fail silently and the flag + * will not be set. */ + + GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &clg_previous_console_mode); + + ctx->use_color = 0; + if (IsWindows10OrGreater() && isatty(ctx->output)) { + DWORD mode = clg_previous_console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), mode)) { + ctx->use_color = 1; + } + } #endif } @@ -638,6 +655,9 @@ static CLogContext *CLG_ctx_init(void) static void CLG_ctx_free(CLogContext *ctx) { +#if defined(WIN32) + SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), clg_previous_console_mode); +#endif while (ctx->types != NULL) { CLG_LogType *item = ctx->types; ctx->types = item->next; diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm index ab76b78e6df..687173ded09 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.mm +++ b/intern/ghost/intern/GHOST_ContextCGL.mm @@ -278,7 +278,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext() #ifdef GHOST_WAIT_FOR_VSYNC { GLint swapInt = 1; - /* wait for vsync, to avoid tearing artifacts */ + /* Wait for vertical-sync, to avoid tearing artifacts. */ [m_openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; } #endif diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 3b20c95c954..4a23b30e078 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -646,6 +646,11 @@ GHOST_TSuccess GHOST_SystemCocoa::init() [NSApp setDelegate:appDelegate]; } + // AppKit provides automatic window tabbing. Blender is a single-tabbed application without a + // macOS tab bar, and should explicitly opt-out of this. This is also controlled by the macOS + // user default #NSWindowTabbingEnabled. + NSWindow.allowsAutomaticWindowTabbing = NO; + [NSApp finishLaunching]; [pool drain]; diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index a7e325bc9e1..ed5e945f69e 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -34,9 +34,9 @@ #ifdef WITH_X11_XINPUT # include <X11/extensions/XInput.h> -/* Disable xinput warp, currently not implemented by Xorg for multi-head display. - * (see comment in xserver "Xi/xiwarppointer.c" -> "FIXME: panoramix stuff is missing" ~ v1.13.4) - * If this is supported we can add back xinput for warping (fixing T48901). +/* Disable XINPUT warp, currently not implemented by Xorg for multi-head display. + * (see comment in XSERVER `Xi/xiwarppointer.c` -> `FIXME: panoramix stuff is missing` ~ v1.13.4) + * If this is supported we can add back XINPUT for warping (fixing T48901). * For now disable (see T50383). */ // # define USE_X11_XINPUT_WARP #endif diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 73927317b24..add7962d924 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -336,11 +336,6 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, backing:NSBackingStoreBuffered defer:NO]; - if (m_window == nil) { - [pool drain]; - return; - } - [m_window setSystemAndWindowCocoa:systemCocoa windowCocoa:this]; // Forbid to resize the window below the blender defined minimum one diff --git a/intern/ghost/intern/GHOST_WindowViewCocoa.h b/intern/ghost/intern/GHOST_WindowViewCocoa.h index 14c70382916..f47e02704b2 100644 --- a/intern/ghost/intern/GHOST_WindowViewCocoa.h +++ b/intern/ghost/intern/GHOST_WindowViewCocoa.h @@ -253,7 +253,7 @@ - (NSAttributedString *)attributedSubstringFromRange:(NSRange)range { - return [NSAttributedString new]; // XXX does this leak? + return [[[NSAttributedString alloc] init] autorelease]; } - (NSRange)markedRange @@ -284,7 +284,7 @@ - (NSArray *)validAttributesForMarkedText { - return [NSArray array]; // XXX does this leak? + return [NSArray array]; } @end diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index ad5643fcd89..de4e77ffc24 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -92,16 +92,11 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, { wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0); RECT win_rect = {left, top, (long)(left + width), (long)(top + height)}; - RECT parent_rect = {0, 0, 0, 0}; // Initialize tablet variables memset(&m_wintab, 0, sizeof(m_wintab)); m_tabletData = GHOST_TABLET_DATA_NONE; - if (parentwindow) { - GetWindowRect(m_parentWindowHwnd, &parent_rect); - } - DWORD style = parentwindow ? WS_POPUPWINDOW | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX : WS_OVERLAPPEDWINDOW; @@ -124,9 +119,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, MONITORINFOEX monitor; monitor.cbSize = sizeof(MONITORINFOEX); monitor.dwFlags = 0; - GetMonitorInfo( - MonitorFromRect(parentwindow ? &parent_rect : &win_rect, MONITOR_DEFAULTTONEAREST), - &monitor); + GetMonitorInfo(MonitorFromRect(&win_rect, MONITOR_DEFAULTTONEAREST), &monitor); /* Adjust our requested size to allow for caption and borders and constrain to monitor. */ AdjustWindowRectEx(&win_rect, WS_CAPTION, FALSE, 0); @@ -1200,7 +1193,7 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 *bitmap GHOST_TUns32 fullBitRow, fullMaskRow; int x, y, cols; - cols = sizeX / 8; /* Number of whole bytes per row (width of bm/mask). */ + cols = sizeX / 8; /* Number of whole bytes per row (width of bitmap/mask). */ if (sizeX % 8) cols++; diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 5d89763f34b..e90739debf8 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -900,6 +900,7 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta): layout = self.layout import os + import re import bpy.utils layout = self.layout @@ -920,7 +921,11 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta): (filter_path(f))) ]) - files.sort() + # Perform a "natural sort", so 20 comes after 3 (for example). + files.sort( + key=lambda file_path: + tuple(int(t) if t.isdigit() else t for t in re.split("(\d+)", file_path[0].lower())), + ) col = layout.column(align=True) diff --git a/release/scripts/presets/framerate/120.py b/release/scripts/presets/framerate/120.py new file mode 100644 index 00000000000..53328907d2b --- /dev/null +++ b/release/scripts/presets/framerate/120.py @@ -0,0 +1,3 @@ +import bpy +bpy.context.scene.render.fps = 120 +bpy.context.scene.render.fps_base = 1 diff --git a/release/scripts/presets/framerate/240.py b/release/scripts/presets/framerate/240.py new file mode 100644 index 00000000000..096af4e38ec --- /dev/null +++ b/release/scripts/presets/framerate/240.py @@ -0,0 +1,3 @@ +import bpy +bpy.context.scene.render.fps = 240 +bpy.context.scene.render.fps_base = 1 diff --git a/release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py b/release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py index 9b0a260dc95..192ba2cf5b5 100644 --- a/release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py +++ b/release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py @@ -58,6 +58,7 @@ def load_handler(dummy): # Grease pencil object scene = bpy.data.scenes[0] if scene: + scene.tool_settings.use_keyframe_insert_auto = True for ob in scene.objects: if ob.type == 'GPENCIL': gpd = ob.data diff --git a/release/scripts/startup/bl_ui/properties_output.py b/release/scripts/startup/bl_ui/properties_output.py index 69c557d336f..75c1f69f84f 100644 --- a/release/scripts/startup/bl_ui/properties_output.py +++ b/release/scripts/startup/bl_ui/properties_output.py @@ -80,7 +80,7 @@ class RENDER_PT_dimensions(RenderOutputButtonsPanel, Panel): fps_rate = round(fps / fps_base, 2) # TODO: Change the following to iterate over existing presets - custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60}) + custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60, 120, 240}) if custom_framerate is True: fps_label_text = tip_("Custom (%.4g fps)") % fps_rate diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 17eb6e19292..66bfe620df7 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 9 +#define BLENDER_FILE_SUBVERSION 10 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_cryptomatte.h b/source/blender/blenkernel/BKE_cryptomatte.h index 96e853e7ff8..7d295929e77 100644 --- a/source/blender/blenkernel/BKE_cryptomatte.h +++ b/source/blender/blenkernel/BKE_cryptomatte.h @@ -31,8 +31,6 @@ extern "C" { #endif struct CryptomatteSession; -struct ID; -struct Main; struct Material; struct Object; struct RenderResult; diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index b6116b32ca5..2c6e5ed3873 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -223,7 +223,7 @@ struct GSet *BKE_main_gset_create(struct Main *bmain, struct GSet *gset); #define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb) \ { \ - ListBase *_lbarray[MAX_LIBARRAY]; \ + ListBase *_lbarray[INDEX_ID_MAX]; \ int _i = set_listbasepointers((_bmain), _lbarray); \ while (_i--) { \ (_lb) = _lbarray[_i]; @@ -234,9 +234,13 @@ struct GSet *BKE_main_gset_create(struct Main *bmain, struct GSet *gset); ((void)0) /** - * DO NOT use break statement with that macro, - * use #FOREACH_MAIN_LISTBASE and #FOREACH_MAIN_LISTBASE_ID instead - * if you need that kind of control flow. */ + * Top level `foreach`-like macro allowing to loop over all IDs in a given #Main data-base. + * + * NOTE: Order tries to go from 'user IDs' to 'used IDs' (e.g. collections will be processed + * before objects, which will be processed before obdata types, etc.). + * + * WARNING: DO NOT use break statement with that macro, use #FOREACH_MAIN_LISTBASE and + * #FOREACH_MAIN_LISTBASE_ID instead if you need that kind of control flow. */ #define FOREACH_MAIN_ID_BEGIN(_bmain, _id) \ { \ ListBase *_lb; \ @@ -259,8 +263,8 @@ const char *BKE_main_blendfile_path_from_global(void); struct ListBase *which_libbase(struct Main *bmain, short type); -#define MAX_LIBARRAY 41 -int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]); +//#define INDEX_ID_MAX 41 +int set_listbasepointers(struct Main *main, struct ListBase *lb[]); #define MAIN_VERSION_ATLEAST(main, ver, subver) \ ((main)->versionfile > (ver) || \ diff --git a/source/blender/blenkernel/BKE_volume_to_mesh.hh b/source/blender/blenkernel/BKE_volume_to_mesh.hh index 1ec8a8e84cd..1f6e89636c4 100644 --- a/source/blender/blenkernel/BKE_volume_to_mesh.hh +++ b/source/blender/blenkernel/BKE_volume_to_mesh.hh @@ -21,7 +21,6 @@ #endif struct Mesh; -struct VolumeGrid; namespace blender::bke { diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 32710c4fa60..101f4b7caf6 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -865,7 +865,7 @@ bool BKE_blendfile_write_partial(Main *bmain_src, ReportList *reports) { Main *bmain_dst = MEM_callocN(sizeof(Main), "copybuffer"); - ListBase *lbarray_dst[MAX_LIBARRAY], *lbarray_src[MAX_LIBARRAY]; + ListBase *lbarray_dst[INDEX_ID_MAX], *lbarray_src[INDEX_ID_MAX]; int a, retval; void *path_list_backup = NULL; diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 2ad0ac950d0..47427beccba 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -783,7 +783,7 @@ void BKE_bpath_traverse_main(Main *bmain, const int flag, void *bpath_user_data) { - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int a = set_listbasepointers(bmain, lbarray); while (a--) { BKE_bpath_traverse_id_list(bmain, lbarray[a], visit_cb, flag, bpath_user_data); diff --git a/source/blender/blenkernel/intern/idtype.c b/source/blender/blenkernel/intern/idtype.c index 1889d1c4eb0..fee70922570 100644 --- a/source/blender/blenkernel/intern/idtype.c +++ b/source/blender/blenkernel/intern/idtype.c @@ -63,7 +63,7 @@ bool BKE_idtype_cache_key_cmp(const void *key_a_v, const void *key_b_v) (key_a->offset_in_ID != key_b->offset_in_ID) || (key_a->cache_v != key_b->cache_v); } -static IDTypeInfo *id_types[MAX_LIBARRAY] = {NULL}; +static IDTypeInfo *id_types[INDEX_ID_MAX] = {NULL}; static void id_type_init(void) { diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 54c2f5f5565..a511c1f9c4c 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -916,7 +916,7 @@ void BKE_main_id_tag_idcode(struct Main *mainvar, */ void BKE_main_id_tag_all(struct Main *mainvar, const int tag, const bool value) { - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int a; a = set_listbasepointers(mainvar, lbarray); @@ -949,7 +949,7 @@ void BKE_main_id_flag_listbase(ListBase *lb, const int flag, const bool value) */ void BKE_main_id_flag_all(Main *bmain, const int flag, const bool value) { - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int a; a = set_listbasepointers(bmain, lbarray); while (a--) { @@ -1870,7 +1870,7 @@ void BKE_library_make_local(Main *bmain, const bool untagged_only, const bool set_fake) { - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; LinkNode *todo_ids = NULL; LinkNode *copied_ids = NULL; diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index 7c5032c97f4..1d7f89e1e8d 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -240,7 +240,7 @@ void BKE_id_free_us(Main *bmain, void *idv) /* test users */ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) { const int tag = LIB_TAG_DOIT; - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; Link dummy_link = {0}; int base_count, i; diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c index 796bc3dc3d0..acd0c10040c 100644 --- a/source/blender/blenkernel/intern/lib_query.c +++ b/source/blender/blenkernel/intern/lib_query.c @@ -440,7 +440,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) typedef struct IDUsersIter { ID *id; - ListBase *lb_array[MAX_LIBARRAY]; + ListBase *lb_array[INDEX_ID_MAX]; int lb_idx; ID *curr_id; @@ -514,7 +514,7 @@ int BKE_library_ID_use_ID(ID *id_user, ID *id_used) static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked) { IDUsersIter iter; - ListBase *lb_array[MAX_LIBARRAY]; + ListBase *lb_array[INDEX_ID_MAX]; ID *id = idv; int i = set_listbasepointers(bmain, lb_array); bool is_defined = false; @@ -567,7 +567,7 @@ bool BKE_library_ID_is_indirectly_used(Main *bmain, void *idv) void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, bool *is_used_linked) { IDUsersIter iter; - ListBase *lb_array[MAX_LIBARRAY]; + ListBase *lb_array[INDEX_ID_MAX]; ID *id = idv; int i = set_listbasepointers(bmain, lb_array); bool is_defined = false; @@ -805,7 +805,7 @@ void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag) */ void BKE_library_indirectly_used_data_tag_clear(Main *bmain) { - ListBase *lb_array[MAX_LIBARRAY]; + ListBase *lb_array[INDEX_ID_MAX]; bool do_loop = true; while (do_loop) { diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c index 6f94b3355fa..d1f34ad8ce9 100644 --- a/source/blender/blenkernel/intern/main.c +++ b/source/blender/blenkernel/intern/main.c @@ -53,7 +53,7 @@ Main *BKE_main_new(void) void BKE_main_free(Main *mainvar) { /* also call when reading a file, erase all, etc */ - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int a; /* Since we are removing whole main, no need to bother 'properly' @@ -532,18 +532,17 @@ ListBase *which_libbase(Main *bmain, short type) } /** - * puts into array *lb pointers to all the #ListBase structs in main, - * and returns the number of them as the function result. This is useful for - * generic traversal of all the blocks in a Main (by traversing all the - * lists in turn), without worrying about block types. + * Put the pointers to all the #ListBase structs in given `bmain` into the `*lb[INDEX_ID_MAX]` + * array, and return the number of those for convenience. * - * \note #MAX_LIBARRAY define should match this code */ -int set_listbasepointers(Main *bmain, ListBase **lb) + * This is useful for generic traversal of all the blocks in a #Main (by traversing all the lists + * in turn), without worrying about block types. + * + * \note The order of each ID type #ListBase in the array is determined by the `INDEX_ID_<IDTYPE>` + * enum definitions in `DNA_ID.h`. See also the #FOREACH_MAIN_ID_BEGIN macro in `BKE_main.h` + */ +int set_listbasepointers(Main *bmain, ListBase *lb[INDEX_ID_MAX]) { - /* BACKWARDS! also watch order of free-ing! (mesh<->mat), first items freed last. - * This is important because freeing data decreases user-counts of other data-blocks, - * if this data is its self freed it can crash. */ - /* Libraries may be accessed from pretty much any other ID. */ lb[INDEX_ID_LI] = &(bmain->libraries); @@ -606,5 +605,5 @@ int set_listbasepointers(Main *bmain, ListBase **lb) lb[INDEX_ID_NULL] = NULL; - return (MAX_LIBARRAY - 1); + return (INDEX_ID_MAX - 1); } diff --git a/source/blender/blenkernel/intern/main_idmap.c b/source/blender/blenkernel/intern/main_idmap.c index 21f5e9c6fb2..1d362db4432 100644 --- a/source/blender/blenkernel/intern/main_idmap.c +++ b/source/blender/blenkernel/intern/main_idmap.c @@ -66,7 +66,7 @@ struct IDNameLib_TypeMap { * Opaque structure, external API users only see this. */ struct IDNameLib_Map { - struct IDNameLib_TypeMap type_maps[MAX_LIBARRAY]; + struct IDNameLib_TypeMap type_maps[INDEX_ID_MAX]; struct GHash *uuid_map; struct Main *bmain; struct GSet *valid_id_pointers; @@ -77,7 +77,7 @@ static struct IDNameLib_TypeMap *main_idmap_from_idcode(struct IDNameLib_Map *id short id_type) { if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) { - for (int i = 0; i < MAX_LIBARRAY; i++) { + for (int i = 0; i < INDEX_ID_MAX; i++) { if (id_map->type_maps[i].id_type == id_type) { return &id_map->type_maps[i]; } @@ -108,13 +108,13 @@ struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain, id_map->idmap_types = idmap_types; int index = 0; - while (index < MAX_LIBARRAY) { + while (index < INDEX_ID_MAX) { struct IDNameLib_TypeMap *type_map = &id_map->type_maps[index]; type_map->map = NULL; type_map->id_type = BKE_idtype_idcode_iter_step(&index); BLI_assert(type_map->id_type != 0); } - BLI_assert(index == MAX_LIBARRAY); + BLI_assert(index == INDEX_ID_MAX); if (idmap_types & MAIN_IDMAP_TYPE_UUID) { ID *id; @@ -231,7 +231,7 @@ void BKE_main_idmap_destroy(struct IDNameLib_Map *id_map) { if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) { struct IDNameLib_TypeMap *type_map = id_map->type_maps; - for (int i = 0; i < MAX_LIBARRAY; i++, type_map++) { + for (int i = 0; i < INDEX_ID_MAX; i++, type_map++) { if (type_map->map) { BLI_ghash_free(type_map->map, NULL, NULL); type_map->map = NULL; diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c index 5bffcd4d9e7..4cc2d101b02 100644 --- a/source/blender/blenkernel/intern/studiolight.c +++ b/source/blender/blenkernel/intern/studiolight.c @@ -514,7 +514,7 @@ static void studiolight_create_matcap_gputexture(StudioLightImage *sli) ImBuf *ibuf = sli->ibuf; float *gpu_matcap_3components = MEM_callocN(sizeof(float[3]) * ibuf->x * ibuf->y, __func__); - float(*offset4)[4] = (float(*)[4])ibuf->rect_float; + const float(*offset4)[4] = (const float(*)[4])ibuf->rect_float; float(*offset3)[3] = (float(*)[3])gpu_matcap_3components; for (int i = 0; i < ibuf->x * ibuf->y; i++, offset4++, offset3++) { copy_v3_v3(*offset3, *offset4); diff --git a/source/blender/blenlib/BLI_multi_value_map.hh b/source/blender/blenlib/BLI_multi_value_map.hh index 018f080e633..4113085a1e3 100644 --- a/source/blender/blenlib/BLI_multi_value_map.hh +++ b/source/blender/blenlib/BLI_multi_value_map.hh @@ -104,6 +104,22 @@ template<typename Key, typename Value> class MultiValueMap { } /** + * Get a mutable span to all the values that are stored for the given key. + */ + MutableSpan<Value> lookup(const Key &key) + { + return this->lookup_as(key); + } + template<typename ForwardKey> MutableSpan<Value> lookup_as(const ForwardKey &key) + { + Vector<Value> *vector = map_.lookup_ptr_as(key); + if (vector != nullptr) { + return vector->as_mutable_span(); + } + return {}; + } + + /** * Note: This signature will change when the implementation changes. */ typename MapType::ItemIterator items() const diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index bb00755e901..287334a34ee 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -377,7 +377,7 @@ int BLI_exists(const char *path) struct stat st; BLI_assert(!BLI_path_is_rel(path)); if (stat(path, &st)) { - return (0); + return 0; } #endif return (st.st_mode); diff --git a/source/blender/blenlib/intern/string_search.cc b/source/blender/blenlib/intern/string_search.cc index a09aa7a4bc2..44baff1f5e3 100644 --- a/source/blender/blenlib/intern/string_search.cc +++ b/source/blender/blenlib/intern/string_search.cc @@ -395,6 +395,7 @@ void extract_normalized_words(StringRef str, struct SearchItem { blender::Span<blender::StringRef> normalized_words; + int length; void *user_data; }; @@ -416,8 +417,10 @@ void BLI_string_search_add(StringSearch *search, const char *str, void *user_dat { using namespace blender; Vector<StringRef, 64> words; - string_search::extract_normalized_words(str, search->allocator, words); - search->items.append({search->allocator.construct_array_copy(words.as_span()), user_data}); + StringRef str_ref{str}; + string_search::extract_normalized_words(str_ref, search->allocator, words); + search->items.append( + {search->allocator.construct_array_copy(words.as_span()), (int)str_ref.size(), user_data}); } /** @@ -453,7 +456,15 @@ int BLI_string_search_query(StringSearch *search, const char *query, void ***r_d * score. Results with the same score are in the order they have been added to the search. */ Vector<int> sorted_result_indices; for (const int score : found_scores) { - Span<int> indices = result_indices_by_score.lookup(score); + MutableSpan<int> indices = result_indices_by_score.lookup(score); + if (score == found_scores[0]) { + /* Sort items with best score by length. Shorter items are more likely the ones you are + * looking for. This also ensures that exact matches will be at the top, even if the query is + * a substring of another item. */ + std::sort(indices.begin(), indices.end(), [&](int a, int b) { + return search->items[a].length < search->items[b].length; + }); + } sorted_result_indices.extend(indices); } diff --git a/source/blender/blenlib/tests/BLI_multi_value_map_test.cc b/source/blender/blenlib/tests/BLI_multi_value_map_test.cc index 7501fbe0d87..a910f2935d4 100644 --- a/source/blender/blenlib/tests/BLI_multi_value_map_test.cc +++ b/source/blender/blenlib/tests/BLI_multi_value_map_test.cc @@ -29,6 +29,27 @@ TEST(multi_value_map, LookupExistant) EXPECT_EQ(map.lookup(3)[0], 6); } +TEST(multi_value_map, LookupMutable) +{ + MultiValueMap<int, int> map; + map.add(1, 2); + map.add(4, 5); + map.add(4, 6); + map.add(6, 7); + + MutableSpan<int> span = map.lookup(4); + EXPECT_EQ(span.size(), 2); + span[0] = 10; + span[1] = 20; + + map.add(4, 5); + MutableSpan<int> new_span = map.lookup(4); + EXPECT_EQ(new_span.size(), 3); + EXPECT_EQ(new_span[0], 10); + EXPECT_EQ(new_span[1], 20); + EXPECT_EQ(new_span[2], 5); +} + TEST(multi_value_map, AddMultiple) { MultiValueMap<int, int> map; diff --git a/source/blender/blenloader/intern/blend_validate.c b/source/blender/blenloader/intern/blend_validate.c index 7261db5d3a6..f3fc1453461 100644 --- a/source/blender/blenloader/intern/blend_validate.c +++ b/source/blender/blenloader/intern/blend_validate.c @@ -60,7 +60,7 @@ bool BLO_main_validate_libraries(Main *bmain, ReportList *reports) blo_split_main(&mainlist, bmain); - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int i = set_listbasepointers(bmain, lbarray); while (i--) { for (ID *id = lbarray[i]->first; id != NULL; id = id->next) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index c0293c1f8f2..2200f7c291b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -449,7 +449,7 @@ static void oldnewmap_free(OldNewMap *onm) static void add_main_to_main(Main *mainvar, Main *from) { - ListBase *lbarray[MAX_LIBARRAY], *fromarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX], *fromarray[INDEX_ID_MAX]; int a; set_listbasepointers(mainvar, lbarray); @@ -517,7 +517,7 @@ void blo_split_main(ListBase *mainlist, Main *main) lib_main_array[i] = libmain; } - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; i = set_listbasepointers(main, lbarray); while (i--) { ID *id = lbarray[i]->first; @@ -1965,7 +1965,7 @@ void blo_end_packed_pointer_map(FileData *fd, Main *oldmain) /* undo file support: add all library pointers in lookup */ void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd) { - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; LISTBASE_FOREACH (Main *, ptr, old_mainlist) { int i = set_listbasepointers(ptr, lbarray); @@ -4543,7 +4543,7 @@ void BLO_main_expander(BLOExpandDoitCallback expand_doit_func) */ void BLO_expand_main(void *fdhandle, Main *mainvar) { - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; FileData *fd = fdhandle; ID *id; int a; @@ -4713,7 +4713,7 @@ static void add_loose_object_data_to_scene(Main *mainvar, } /* Loop over all ID types, instancing object-data for ID types that have support for it. */ - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int i = set_listbasepointers(mainvar, lbarray); while (i--) { const short idcode = BKE_idtype_idcode_from_index(i); @@ -4979,7 +4979,7 @@ static bool library_link_idcode_needs_tag_check(const short idcode, const int fl */ static void library_link_clear_tag(Main *mainvar, const int flag) { - for (int i = 0; i < MAX_LIBARRAY; i++) { + for (int i = 0; i < INDEX_ID_MAX; i++) { const short idcode = BKE_idtype_idcode_from_index(i); BLI_assert(idcode != -1); if (library_link_idcode_needs_tag_check(idcode, flag)) { @@ -5068,8 +5068,8 @@ static void split_main_newid(Main *mainptr, Main *main_newid) BLI_strncpy(main_newid->name, mainptr->name, sizeof(main_newid->name)); main_newid->curlib = mainptr->curlib; - ListBase *lbarray[MAX_LIBARRAY]; - ListBase *lbarray_newid[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; + ListBase *lbarray_newid[INDEX_ID_MAX]; int i = set_listbasepointers(mainptr, lbarray); set_listbasepointers(main_newid, lbarray_newid); while (i--) { @@ -5227,7 +5227,7 @@ void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname) static int has_linked_ids_to_read(Main *mainvar) { - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int a = set_listbasepointers(mainvar, lbarray); while (a--) { @@ -5295,7 +5295,7 @@ static void read_library_linked_ids(FileData *basefd, { GHash *loaded_ids = BLI_ghash_str_new(__func__); - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int a = set_listbasepointers(mainvar, lbarray); while (a--) { @@ -5344,7 +5344,7 @@ static void read_library_clear_weak_links(FileData *basefd, ListBase *mainlist, { /* Any remaining weak links at this point have been lost, silently drop * those by setting them to NULL pointers. */ - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int a = set_listbasepointers(mainvar, lbarray); while (a--) { diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index d86ddc5b646..289092f7f19 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -1141,7 +1141,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain) } } if (!MAIN_VERSION_ATLEAST(bmain, 276, 5)) { - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int a; /* Important to clear all non-persistent flags from older versions here, diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index fa9f00d67ec..5c8e9da41c4 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1789,6 +1789,24 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) FOREACH_NODETREE_END; } + if (!MAIN_VERSION_ATLEAST(bmain, 293, 10)) { + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_GEOMETRY) { + version_node_socket_name(ntree, GEO_NODE_ATTRIBUTE_PROXIMITY, "Location", "Position"); + } + } + FOREACH_NODETREE_END; + + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + /* Fix old scene with too many samples that were not being used. + * Now they are properly used and might produce a huge slowdown. + * So we clamp to what the old max actual was. */ + if (scene->eevee.volumetric_shadow_samples > 32) { + scene->eevee.volumetric_shadow_samples = 32; + } + } + } + /** * Versioning code until next subversion bump goes here. * @@ -1800,12 +1818,5 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) */ { /* Keep this block, even when empty. */ - - FOREACH_NODETREE_BEGIN (bmain, ntree, id) { - if (ntree->type == NTREE_GEOMETRY) { - version_node_socket_name(ntree, GEO_NODE_ATTRIBUTE_PROXIMITY, "Location", "Position"); - } - } - FOREACH_NODETREE_END; } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 0a4f2fde93f..6fbd4b77487 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -768,7 +768,7 @@ static void write_userdef(BlendWriter *writer, const UserDef *userdef) /* Keep it last of write_foodata functions. */ static void write_libraries(WriteData *wd, Main *main) { - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; ID *id; int a, tot; bool found_one; @@ -954,7 +954,7 @@ static bool write_file_handle(Main *mainvar, * if needed, without duplicating whole code. */ Main *bmain = mainvar; do { - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int a = set_listbasepointers(bmain, lbarray); while (a--) { ID *id = lbarray[a]->first; diff --git a/source/blender/compositor/intern/COM_MetaData.h b/source/blender/compositor/intern/COM_MetaData.h index 6fdd8d3945e..fa3de895b4e 100644 --- a/source/blender/compositor/intern/COM_MetaData.h +++ b/source/blender/compositor/intern/COM_MetaData.h @@ -27,7 +27,6 @@ /* Forward declarations. */ struct RenderResult; -struct StampData; /* Cryptomatte includes hash in its meta data keys. The hash is generated from the render * layer/pass name. Compositing happens without the knowledge of the original layer and pass. The diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index 14c91834739..df8c8215d2f 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -33,9 +33,7 @@ #include "MEM_guardedalloc.h" -#include "DNA_ID.h" /* for ID_Type */ - -#include "BKE_main.h" /* for MAX_LIBARRAY */ +#include "DNA_ID.h" /* for ID_Type and INDEX_ID_MAX */ #include "BLI_threads.h" /* for SpinLock */ @@ -111,10 +109,10 @@ struct Depsgraph { bool need_update; /* Indicates which ID types were updated. */ - char id_type_updated[MAX_LIBARRAY]; + char id_type_updated[INDEX_ID_MAX]; /* Indicates type of IDs present in the depsgraph. */ - char id_type_exist[MAX_LIBARRAY]; + char id_type_exist[INDEX_ID_MAX]; /* Quick-Access Temp Data ............. */ diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index ae01aee5dae..7fd39007263 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -208,12 +208,14 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, DRW_shgroup_stencil_mask(shgrp, sss_id); { + eGPUSamplerState state = GPU_SAMPLER_DEFAULT; + DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_subsurface_first_pass_sh_get(), psl->sss_blur_ps); DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src); - DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance); - DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius); + DRW_shgroup_uniform_texture_ref_ex(grp, "sssIrradiance", &effects->sss_irradiance, state); + DRW_shgroup_uniform_texture_ref_ex(grp, "sssRadius", &effects->sss_radius, state); DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); @@ -223,9 +225,9 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, grp = DRW_shgroup_create(EEVEE_shaders_subsurface_second_pass_sh_get(), psl->sss_resolve_ps); DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src); - DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur); - DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo); - DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius); + DRW_shgroup_uniform_texture_ref_ex(grp, "sssIrradiance", &effects->sss_blur, state); + DRW_shgroup_uniform_texture_ref_ex(grp, "sssAlbedo", &effects->sss_albedo, state); + DRW_shgroup_uniform_texture_ref_ex(grp, "sssRadius", &effects->sss_radius, state); DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index bc2895ef3df..5f0fde134d1 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -135,6 +135,60 @@ void accumulate_light(vec3 light, float fac, inout vec4 accum) accum += vec4(light, 1.0) * min(fac, (1.0 - accum.a)); } +/* Same thing as Cycles without the comments to make it shorter. */ +vec3 ensure_valid_reflection(vec3 Ng, vec3 I, vec3 N) +{ + vec3 R = -reflect(I, N); + + /* Reflection rays may always be at least as shallow as the incoming ray. */ + float threshold = min(0.9 * dot(Ng, I), 0.025); + if (dot(Ng, R) >= threshold) { + return N; + } + + float NdotNg = dot(N, Ng); + vec3 X = normalize(N - NdotNg * Ng); + + float Ix = dot(I, X), Iz = dot(I, Ng); + float Ix2 = sqr(Ix), Iz2 = sqr(Iz); + float a = Ix2 + Iz2; + + float b = sqrt(Ix2 * (a - sqr(threshold))); + float c = Iz * threshold + a; + + float fac = 0.5 / a; + float N1_z2 = fac * (b + c), N2_z2 = fac * (-b + c); + bool valid1 = (N1_z2 > 1e-5) && (N1_z2 <= (1.0 + 1e-5)); + bool valid2 = (N2_z2 > 1e-5) && (N2_z2 <= (1.0 + 1e-5)); + + vec2 N_new; + if (valid1 && valid2) { + /* If both are possible, do the expensive reflection-based check. */ + vec2 N1 = vec2(sqrt(1.0 - N1_z2), sqrt(N1_z2)); + vec2 N2 = vec2(sqrt(1.0 - N2_z2), sqrt(N2_z2)); + + float R1 = 2.0 * (N1.x * Ix + N1.y * Iz) * N1.y - Iz; + float R2 = 2.0 * (N2.x * Ix + N2.y * Iz) * N2.y - Iz; + + valid1 = (R1 >= 1e-5); + valid2 = (R2 >= 1e-5); + if (valid1 && valid2) { + N_new = (R1 < R2) ? N1 : N2; + } + else { + N_new = (R1 > R2) ? N1 : N2; + } + } + else if (valid1 || valid2) { + float Nz2 = valid1 ? N1_z2 : N2_z2; + N_new = vec2(sqrt(1.0 - Nz2), sqrt(Nz2)); + } + else { + return Ng; + } + return N_new.x * X + N_new.y * Ng; +} + /* ----------- Cone angle Approximation --------- */ /* Return a fitted cone angle given the input roughness */ diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl index 5c10a7f451f..00d265a48b0 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl @@ -3,6 +3,7 @@ #pragma BLENDER_REQUIRE(lights_lib.glsl) #pragma BLENDER_REQUIRE(lightprobe_lib.glsl) #pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl) +#pragma BLENDER_REQUIRE(bsdf_common_lib.glsl) struct ClosureInputGlossy { vec3 N; /** Shading normal. */ @@ -39,6 +40,10 @@ ClosureEvalGlossy closure_Glossy_eval_init(inout ClosureInputGlossy cl_in, cl_in.roughness = clamp(cl_in.roughness, 1e-8, 0.9999); cl_out.radiance = vec3(0.0); +#ifndef STEP_RESOLVE /* SSR */ + cl_in.N = ensure_valid_reflection(cl_common.Ng, cl_common.V, cl_in.N); +#endif + float NV = dot(cl_in.N, cl_common.V); vec2 lut_uv = lut_coords(NV, cl_in.roughness); diff --git a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl index a4b29d68ac4..ecff28dcd38 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl @@ -80,25 +80,24 @@ void do_ssr(vec3 V, vec3 N, vec3 T, vec3 B, vec3 vP, float a2, vec4 rand) vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH); vec3 R = reflect(-V, H); + const float bad_ray_threshold = 0.01; + + vec3 vNg = safe_normalize(cross(dFdx(vP), dFdy(vP))); + /* If ray is bad (i.e. going below the surface) regenerate. */ - /* This threshold is a bit higher than 0 to improve self intersection cases. */ - const float bad_ray_threshold = 0.085; - if (dot(R, N) <= bad_ray_threshold) { + if (dot(R, vNg) < bad_ray_threshold) { H = sample_ggx(rand.xzw * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); R = reflect(-V, H); } - - if (dot(R, N) <= bad_ray_threshold) { + if (dot(R, vNg) < bad_ray_threshold) { H = sample_ggx(rand.xzw * vec3(1.0, 1.0, -1.0), a2, N, T, B, NH); R = reflect(-V, H); } - - if (dot(R, N) <= bad_ray_threshold) { + if (dot(R, vNg) < bad_ray_threshold) { H = sample_ggx(rand.xzw * vec3(1.0, -1.0, 1.0), a2, N, T, B, NH); R = reflect(-V, H); } - - if (dot(R, N) <= bad_ray_threshold) { + if (dot(R, vNg) < bad_ray_threshold) { /* Not worth tracing. */ return; } diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl index 2a53a4f119f..1964adf3059 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl @@ -26,7 +26,7 @@ void main(void) vec2 pixel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); /* TODO precompute */ vec2 uvs = gl_FragCoord.xy * pixel_size; vec3 sss_irradiance = texture(sssIrradiance, uvs).rgb; - float sss_radius = texture(sssRadius, uvs).r; + float sss_radius = texture(sssRadius, uvs).r * radii_max_radius.w; float depth = texture(depthBuffer, uvs).r; float depth_view = get_view_z_from_depth(depth); @@ -43,8 +43,7 @@ void main(void) /* Compute kernel bounds in 2D. */ float homcoord = ProjectionMatrix[2][3] * depth_view + ProjectionMatrix[3][3]; vec2 scale = vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * sss_radius / homcoord; - vec2 finalStep = scale * radii_max_radius.w; - finalStep *= 0.5; /* samples range -1..1 */ + vec2 finalStep = scale * 0.5; /* samples range -1..1 */ /* Center sample */ vec3 accum = sss_irradiance * kernel[0].rgb; @@ -55,15 +54,18 @@ void main(void) vec3 color = texture(sssIrradiance, sample_uv).rgb; float sample_depth = texture(depthBuffer, sample_uv).r; sample_depth = get_view_z_from_depth(sample_depth); - /* Depth correction factor. */ - float depth_delta = depth_view - sample_depth; - float s = clamp(1.0 - exp(-(depth_delta * depth_delta) / (2.0 * sss_radius)), 0.0, 1.0); + /* Depth correction factor. See Real Time Realistic Skin Translucency 2010 + * by Jimenez, eqs. 2 and 9, and D9740. + * Coefficient -2 follows from gaussian_profile() from gpu_material.c and + * from the definition of finalStep. */ + float depth_delta = (depth_view - sample_depth) / sss_radius; + float s = exp(-2.0 * sqr(depth_delta)); /* Out of view samples. */ if (any(lessThan(sample_uv, vec2(0.0))) || any(greaterThan(sample_uv, vec2(1.0)))) { - s = 1.0; + s = 0.0; } /* Mix with first sample in failure case and apply kernel color. */ - accum += kernel[i].rgb * mix(color, sss_irradiance, s); + accum += kernel[i].rgb * mix(sss_irradiance, color, s); } #if defined(FIRST_PASS) diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl index de384146b80..c9b5d0dea36 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl @@ -304,5 +304,8 @@ vec3 probe_evaluate_grid(GridData gd, vec3 P, vec3 N, vec3 localpos) vec3 probe_evaluate_world_diff(vec3 N) { + if (prbNumRenderGrid == 0) { + return vec3(0); + } return irradiance_from_cell_get(0, N); } diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index fcd626eb92b..f902a95a19a 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -935,8 +935,15 @@ GPUVertBuf *DRW_cache_object_pos_vertbuf_get(Object *ob) int DRW_cache_object_material_count_get(struct Object *ob) { + short type = ob->type; + Mesh *me = BKE_object_get_evaluated_mesh(ob); - short type = (me != NULL) ? OB_MESH : ob->type; + if (me != NULL && type != OB_POINTCLOUD) { + /* Some object types (e.g. curves) can have a Curve in ob->data, but will be rendered as mesh. + * For point clouds this never happens. Ideally this check would happen at another level and we + * would just have to care about ob->data here. */ + type = OB_MESH; + } switch (type) { case OB_MESH: diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 38820e05869..711ec0a9d22 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -2544,7 +2544,7 @@ static bool animchannels_find_poll(bContext *C) } /* find_invoke() - Get initial channels */ -static int animchannels_find_invoke(bContext *C, wmOperator *op, const wmEvent *evt) +static int animchannels_find_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; @@ -2557,7 +2557,7 @@ static int animchannels_find_invoke(bContext *C, wmOperator *op, const wmEvent * RNA_string_set(op->ptr, "query", ac.ads->searchstr); /* defer to popup */ - return WM_operator_props_popup(C, op, evt); + return WM_operator_props_popup(C, op, event); } /* find_exec() - Called to set the value */ diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index b344e67f62d..1809daa3fcb 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -305,6 +305,7 @@ static void fmodifier_frame_range_draw(const bContext *C, Panel *panel) PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL); uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); FModifier *fcm = (FModifier *)ptr->data; uiLayoutSetActive(layout, fcm->flag & FMODIFIER_FLAG_RANGERESTRICT); @@ -478,6 +479,7 @@ static void fn_generator_panel_draw(const bContext *C, Panel *panel) uiItemR(layout, ptr, "function_type", 0, "", ICON_NONE); uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); col = uiLayoutColumn(layout, false); uiItemR(col, ptr, "use_additive", 0, NULL, ICON_NONE); @@ -698,6 +700,7 @@ static void envelope_panel_draw(const bContext *C, Panel *panel) FMod_Envelope *env = (FMod_Envelope *)fcm->data; uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); /* General settings. */ col = uiLayoutColumn(layout, true); @@ -792,6 +795,7 @@ static void limits_panel_draw(const bContext *C, Panel *panel) PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL); uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); /* Minimums. */ col = uiLayoutColumn(layout, false); @@ -853,6 +857,7 @@ static void stepped_panel_draw(const bContext *C, Panel *panel) PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL); uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); /* Stepping Settings. */ col = uiLayoutColumn(layout, false); diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index 78bce8679bb..e65871c0896 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -476,9 +476,9 @@ static int pose_clear_paths_exec(bContext *C, wmOperator *op) } /* operator callback/wrapper */ -static int pose_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *evt) +static int pose_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if ((evt->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) { + if ((event->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) { RNA_boolean_set(op->ptr, "only_selected", true); } return pose_clear_paths_exec(C, op); diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index 45f623f3a9d..dd90f9f2cc3 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -1321,10 +1321,10 @@ static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step) } /* specially handle events for searching */ -static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, ushort event, char ascii) +static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, ushort event_type, char ascii) { /* try doing some form of string manipulation first */ - switch (event) { + switch (event_type) { case EVT_BACKSPACEKEY: if (pld->searchstr[0] && pld->search_cursor) { short len = strlen(pld->searchstr); diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index c8bd38d58fe..e9817f82090 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -2093,7 +2093,7 @@ static void annotation_draw_apply_event( p->mval[1] = (float)event->mval[1] - y; /* Key to toggle stabilization. */ - if (event->shift > 0 && p->paintmode == GP_PAINTMODE_DRAW) { + if (event->shift && p->paintmode == GP_PAINTMODE_DRAW) { /* Using permanent stabilization, shift will deactivate the flag. */ if (p->flags & GP_PAINTFLAG_USE_STABILIZER) { if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { @@ -2108,7 +2108,7 @@ static void annotation_draw_apply_event( } } /* verify key status for straight lines */ - else if ((event->ctrl > 0) || (event->alt > 0)) { + else if (event->ctrl || event->alt) { if (p->straight[0] == 0) { int dx = abs((int)(p->mval[0] - p->mvalo[0])); int dy = abs((int)(p->mval[1] - p->mvalo[1])); @@ -2348,7 +2348,7 @@ static int annotation_draw_invoke(bContext *C, wmOperator *op, const wmEvent *ev p->flags |= GP_PAINTFLAG_USE_STABILIZER | GP_PAINTFLAG_USE_STABILIZER_TEMP; annotation_draw_toggle_stabilizer_cursor(p, true); } - else if (event->shift > 0) { + else if (event->shift) { p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; annotation_draw_toggle_stabilizer_cursor(p, true); } diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 039bc50fcc9..fd2758c8a08 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -1420,7 +1420,7 @@ void GPENCIL_OT_layer_merge(wmOperatorType *ot) /* ********************** Change Layer ***************************** */ -static int gpencil_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt)) +static int gpencil_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { uiPopupMenu *pup; uiLayout *layout; diff --git a/source/blender/editors/gpencil/gpencil_edit_curve.c b/source/blender/editors/gpencil/gpencil_edit_curve.c index 0f9a8c93df9..e766a410889 100644 --- a/source/blender/editors/gpencil/gpencil_edit_curve.c +++ b/source/blender/editors/gpencil/gpencil_edit_curve.c @@ -131,7 +131,7 @@ void GPENCIL_OT_stroke_enter_editcurve_mode(wmOperatorType *ot) "Error Threshold", "Threshold on the maximum deviation from the actual stroke", FLT_MIN, - 10.f); + 10.0f); RNA_def_property_ui_range(prop, FLT_MIN, 10.0f, 0.1f, 5); } diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 406daf9f92e..85130e89ad1 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -55,6 +55,7 @@ #include "BKE_screen.h" #include "ED_gpencil.h" +#include "ED_keyframing.h" #include "ED_screen.h" #include "ED_space_api.h" #include "ED_view3d.h" @@ -542,12 +543,18 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) if (gpl == tgpf->gpl) { if ((gpl->actframe == NULL) || (gpl->actframe->framenum != tgpf->active_cfra)) { short add_frame_mode; - if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { - add_frame_mode = GP_GETFRAME_ADD_COPY; + if (IS_AUTOKEY_ON(tgpf->scene)) { + if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { + add_frame_mode = GP_GETFRAME_ADD_COPY; + } + else { + add_frame_mode = GP_GETFRAME_ADD_NEW; + } } else { - add_frame_mode = GP_GETFRAME_ADD_NEW; + add_frame_mode = GP_GETFRAME_USE_PREV; } + BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, add_frame_mode); } } @@ -1456,7 +1463,10 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) tgpf->done = true; /* Get frame or create a new one. */ - tgpf->gpf = BKE_gpencil_layer_frame_get(tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW); + tgpf->gpf = BKE_gpencil_layer_frame_get(tgpf->gpl, + tgpf->active_cfra, + IS_AUTOKEY_ON(tgpf->scene) ? GP_GETFRAME_ADD_NEW : + GP_GETFRAME_USE_PREV); /* Set frame as selected. */ tgpf->gpf->flag |= GP_FRAME_SELECT; @@ -2064,6 +2074,12 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) estate = OPERATOR_CANCELLED; break; case LEFTMOUSE: + if (!IS_AUTOKEY_ON(tgpf->scene) && (!is_multiedit) && (tgpf->gpl->actframe == NULL)) { + BKE_report(op->reports, RPT_INFO, "No available frame for creating stroke"); + estate = OPERATOR_CANCELLED; + break; + } + /* first time the event is not enabled to show help lines. */ if ((tgpf->oldkey != -1) || (!help_lines)) { ARegion *region = BKE_area_find_region_xy( @@ -2088,17 +2104,24 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) gpencil_stroke_convertcoords_tpoint( tgpf->scene, tgpf->region, tgpf->ob, &point2D, NULL, &pt->x); + /* Hash of selected frames.*/ + GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64); + /* If not multiframe and there is no frame in CFRA for the active layer, create - * a new frame before to make the hash function can find something. */ + * a new frame. */ if (!is_multiedit) { tgpf->gpf = BKE_gpencil_layer_frame_get( - tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW); + tgpf->gpl, + tgpf->active_cfra, + IS_AUTOKEY_ON(tgpf->scene) ? GP_GETFRAME_ADD_NEW : GP_GETFRAME_USE_PREV); tgpf->gpf->flag |= GP_FRAME_SELECT; - } - /* Hash of selected frames.*/ - GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64); - BKE_gpencil_frame_selected_hash(tgpf->gpd, frame_list); + BLI_ghash_insert( + frame_list, POINTER_FROM_INT(tgpf->active_cfra), tgpf->gpl->actframe); + } + else { + BKE_gpencil_frame_selected_hash(tgpf->gpd, frame_list); + } /* Loop all frames. */ wmWindow *win = CTX_wm_window(C); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 974f51ff90b..1217a3a7e8f 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -67,6 +67,7 @@ #include "ED_clip.h" #include "ED_gpencil.h" +#include "ED_keyframing.h" #include "ED_object.h" #include "ED_screen.h" #include "ED_view3d.h" @@ -2155,6 +2156,10 @@ static void gpencil_paint_initstroke(tGPsdata *p, continue; } + if (!IS_AUTOKEY_ON(scene) && (gpl->actframe == NULL)) { + continue; + } + /* Add a new frame if needed (and based off the active frame, * as we need some existing strokes to erase) * @@ -2164,7 +2169,8 @@ static void gpencil_paint_initstroke(tGPsdata *p, */ if (gpl->actframe && gpl->actframe->strokes.first) { if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { - gpl->actframe = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY); + short frame_mode = IS_AUTOKEY_ON(scene) ? GP_GETFRAME_ADD_COPY : GP_GETFRAME_USE_PREV; + gpl->actframe = BKE_gpencil_layer_frame_get(gpl, CFRA, frame_mode); } has_layer_to_erase = true; break; @@ -2187,11 +2193,16 @@ static void gpencil_paint_initstroke(tGPsdata *p, /* Drawing Modes - Add a new frame if needed on the active layer */ short add_frame_mode; - if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { - add_frame_mode = GP_GETFRAME_ADD_COPY; + if (IS_AUTOKEY_ON(scene)) { + if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { + add_frame_mode = GP_GETFRAME_ADD_COPY; + } + else { + add_frame_mode = GP_GETFRAME_ADD_NEW; + } } else { - add_frame_mode = GP_GETFRAME_ADD_NEW; + add_frame_mode = GP_GETFRAME_USE_PREV; } bool need_tag = p->gpl->actframe == NULL; @@ -2206,6 +2217,10 @@ static void gpencil_paint_initstroke(tGPsdata *p, if (G.debug & G_DEBUG) { printf("Error: No frame created (gpencil_paint_init)\n"); } + if (!IS_AUTOKEY_ON(scene)) { + BKE_report(p->reports, RPT_INFO, "No available frame for creating stroke"); + } + return; } p->gpf->flag |= GP_FRAME_PAINT; @@ -2469,6 +2484,8 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) return 0; } + p->reports = op->reports; + /* init painting data */ gpencil_paint_initstroke(p, paintmode, CTX_data_ensure_evaluated_depsgraph(C)); if (p->status == GP_STATUS_ERROR) { @@ -2483,8 +2500,6 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) p->keymodifier = -1; } - p->reports = op->reports; - /* everything is now setup ok */ return 1; } @@ -2835,7 +2850,7 @@ static void gpencil_draw_apply_event(bContext *C, /* verify direction for straight lines and guides */ if ((is_speed_guide) || - ((event->alt > 0) && (RNA_boolean_get(op->ptr, "disable_straight") == false))) { + (event->alt && (RNA_boolean_get(op->ptr, "disable_straight") == false))) { if (p->straight == 0) { int dx = (int)fabsf(p->mval[0] - p->mvali[0]); int dy = (int)fabsf(p->mval[1] - p->mvali[1]); @@ -2876,13 +2891,13 @@ static void gpencil_draw_apply_event(bContext *C, /* special eraser modes */ if (p->paintmode == GP_PAINTMODE_ERASER) { - if (event->shift > 0) { + if (event->shift) { p->flags |= GP_PAINTFLAG_HARD_ERASER; } else { p->flags &= ~GP_PAINTFLAG_HARD_ERASER; } - if (event->alt > 0) { + if (event->alt) { p->flags |= GP_PAINTFLAG_STROKE_ERASER; } else { diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 12d399f32ca..b29ef2e7ee2 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -71,6 +71,7 @@ #include "RNA_enum_types.h" #include "ED_gpencil.h" +#include "ED_keyframing.h" #include "ED_object.h" #include "ED_screen.h" #include "ED_space_api.h" @@ -1253,9 +1254,18 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op) static int gpencil_primitive_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); + Scene *scene = CTX_data_scene(C); bGPdata *gpd = CTX_data_gpencil_data(C); tGPDprimitive *tgpi = NULL; + if (!IS_AUTOKEY_ON(scene)) { + bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); + if ((gpl == NULL) || (gpl->actframe == NULL)) { + BKE_report(op->reports, RPT_INFO, "No available frame for creating stroke"); + return OPERATOR_CANCELLED; + } + } + /* initialize operator runtime data */ gpencil_primitive_init(C, op); tgpi = op->customdata; @@ -1310,11 +1320,16 @@ static void gpencil_primitive_interaction_end(bContext *C, /* insert keyframes as required... */ short add_frame_mode; - if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { - add_frame_mode = GP_GETFRAME_ADD_COPY; + if (IS_AUTOKEY_ON(tgpi->scene)) { + if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { + add_frame_mode = GP_GETFRAME_ADD_COPY; + } + else { + add_frame_mode = GP_GETFRAME_ADD_NEW; + } } else { - add_frame_mode = GP_GETFRAME_ADD_NEW; + add_frame_mode = GP_GETFRAME_USE_PREV; } bool need_tag = tgpi->gpl->actframe == NULL; diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index 0d3ab9011d6..9666aca5254 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -73,6 +73,7 @@ #include "UI_view2d.h" #include "ED_gpencil.h" +#include "ED_keyframing.h" #include "ED_screen.h" #include "ED_view3d.h" @@ -1019,7 +1020,11 @@ static void gpencil_brush_clone_add(bContext *C, tGP_BrushEditData *gso) if (gpl == NULL) { gpl = CTX_data_active_gpencil_layer(C); } - bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW); + bGPDframe *gpf = BKE_gpencil_layer_frame_get( + gpl, CFRA, IS_AUTOKEY_ON(scene) ? GP_GETFRAME_ADD_NEW : GP_GETFRAME_USE_PREV); + if (gpf == NULL) { + continue; + } /* Make a new stroke */ new_stroke = BKE_gpencil_stroke_duplicate(gps, true, true); @@ -1334,6 +1339,10 @@ static void gpencil_sculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso /* go through each layer, and ensure that we've got a valid frame to use */ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + if (!IS_AUTOKEY_ON(scene) && (gpl->actframe == NULL)) { + continue; + } + /* only editable and visible layers are considered */ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { bGPDframe *gpf = gpl->actframe; @@ -1343,7 +1352,7 @@ static void gpencil_sculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso * - This is useful when animating as it saves that "uh-oh" moment when you realize you've * spent too much time editing the wrong frame. */ - if (gpf->framenum != cfra) { + if ((IS_AUTOKEY_ON(scene)) && (gpf->framenum != cfra)) { BKE_gpencil_frame_addcopy(gpl, cfra); /* Need tag to recalculate evaluated data to avoid crashes. */ DEG_id_tag_update(&gso->gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 2415c85e299..4b440aa7367 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -55,7 +55,6 @@ struct FModifier; struct bAction; struct uiBlock; -struct uiLayout; struct PointerRNA; struct PropertyRNA; diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 61e1f0fdf7d..b3205acb8ee 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -52,7 +52,6 @@ struct rcti; struct uiBlock; struct uiLayout; struct wmKeyConfig; -struct wmMsgBus; struct wmMsgSubscribeKey; struct wmMsgSubscribeValue; struct wmNotifier; diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index d10cdc207c2..40cfcaea883 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -120,7 +120,7 @@ void UI_draw_roundbox_4fv_ex(const rctf *rect, }; GPUBatch *batch = ui_batch_roundbox_widget_get(); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); - GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float(*)[4]) & widget_params); + GPU_batch_uniform_4fv_array(batch, "parameters", 11, (const float(*)[4]) & widget_params); GPU_blend(GPU_BLEND_ALPHA); GPU_batch_draw(batch); GPU_blend(GPU_BLEND_NONE); @@ -2376,7 +2376,7 @@ void ui_draw_dropshadow( GPUBatch *batch = ui_batch_roundbox_shadow_get(); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_SHADOW); - GPU_batch_uniform_4fv_array(batch, "parameters", 4, (float(*)[4]) & widget_params); + GPU_batch_uniform_4fv_array(batch, "parameters", 4, (const float(*)[4]) & widget_params); GPU_batch_uniform_1f(batch, "alpha", 1.0f - visibility); GPU_batch_draw(batch); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 75ee3300e63..042f10ddded 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -168,12 +168,14 @@ static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEve #define PIE_MENU_INTERVAL 0.01 #define BUTTON_AUTO_OPEN_THRESH 0.2 #define BUTTON_MOUSE_TOWARDS_THRESH 1.0 -/* pixels to move the cursor to get out of keyboard navigation */ +/** Pixels to move the cursor to get out of keyboard navigation. */ #define BUTTON_KEYNAV_PX_LIMIT 8 -#define MENU_TOWARDS_MARGIN 20 /* margin in pixels */ -#define MENU_TOWARDS_WIGGLE_ROOM 64 /* tolerance in pixels */ -/* drag-lock distance threshold in pixels */ +/** Margin around the menu, use to check if we're moving towards this rectangle (in pixels). */ +#define MENU_TOWARDS_MARGIN 20 +/** Tolerance for closing menus (in pixels). */ +#define MENU_TOWARDS_WIGGLE_ROOM 64 +/** Drag-lock distance threshold (in pixels). */ #define BUTTON_DRAGLOCK_THRESH 3 typedef enum uiButtonActivateType { @@ -10444,7 +10446,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle } } - if (event->type == block->pie_data.event && !is_click_style) { + if (event->type == block->pie_data.event_type && !is_click_style) { if (event->val != KM_RELEASE) { ui_handle_menu_button(C, event, menu); @@ -10618,7 +10620,7 @@ static int ui_handle_menus_recursive(bContext *C, /* root pie menus accept the key that spawned * them as double click to improve responsiveness */ const bool do_recursion = (!(block->flag & UI_BLOCK_RADIAL) || - event->type != block->pie_data.event); + event->type != block->pie_data.event_type); if (do_recursion) { if (is_parent_inside == false) { @@ -10911,7 +10913,7 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata) /* set last pie event to allow chained pie spawning */ if (block->flag & UI_BLOCK_RADIAL) { - win->last_pie_event = block->pie_data.event; + win->pie_event_type_last = block->pie_data.event_type; reset_pie = true; } @@ -10954,7 +10956,7 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata) wmWindow *win = CTX_wm_window(C); if (win) { - win->last_pie_event = EVENT_NONE; + win->pie_event_type_last = EVENT_NONE; } } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index c39e2b3ff8a..1d4a44e0c76 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -424,8 +424,8 @@ struct PieMenuData { float last_pos[2]; double duration_gesture; int flags; - /** initial event used to fire the pie menu, store here so we can query for release */ - int event; + /** Initial event used to fire the pie menu, store here so we can query for release */ + short event_type; float alphafac; }; diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c index 81c627816b9..05aa139e055 100644 --- a/source/blender/editors/interface/interface_region_menu_pie.c +++ b/source/blender/editors/interface/interface_region_menu_pie.c @@ -122,26 +122,26 @@ uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, co * it is always assumed to be click style */ if (event->type == LEFTMOUSE || ELEM(event->val, KM_RELEASE, KM_CLICK)) { pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE; - pie->block_radial->pie_data.event = EVENT_NONE; - win->lock_pie_event = EVENT_NONE; + pie->block_radial->pie_data.event_type = EVENT_NONE; + win->pie_event_type_lock = EVENT_NONE; } else { - if (win->last_pie_event != EVENT_NONE) { + if (win->pie_event_type_last != EVENT_NONE) { /* original pie key has been released, so don't propagate the event */ - if (win->lock_pie_event == EVENT_NONE) { + if (win->pie_event_type_lock == EVENT_NONE) { event_type = EVENT_NONE; pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE; } else { - event_type = win->last_pie_event; + event_type = win->pie_event_type_last; } } else { event_type = event->type; } - pie->block_radial->pie_data.event = event_type; - win->lock_pie_event = event_type; + pie->block_radial->pie_data.event_type = event_type; + win->pie_event_type_lock = event_type; } pie->layout = UI_block_layout( diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 0fa5999976b..06b87dd857f 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1180,7 +1180,7 @@ void UI_widgetbase_draw_cache_flush(void) /* draw single */ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); GPU_batch_uniform_4fv_array( - batch, "parameters", MAX_WIDGET_PARAMETERS, (float(*)[4])g_widget_base_batch.params); + batch, "parameters", MAX_WIDGET_PARAMETERS, (const float(*)[4])g_widget_base_batch.params); GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params); GPU_batch_draw(batch); } diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 1f894ec0f1d..b5ec3f388a0 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -966,7 +966,7 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd) float planes[4][4]; planes_from_projmat( - (float(*)[4])kcd->projmat, planes[2], planes[0], planes[3], planes[1], NULL, NULL); + (const float(*)[4])kcd->projmat, planes[2], planes[0], planes[3], planes[1], NULL, NULL); /* ray-cast all planes */ { diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 43e0ab97f5d..7502b77ae02 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4172,15 +4172,7 @@ static Base *mesh_separate_tagged( })); BM_mesh_elem_toolflags_ensure(bm_new); /* needed for 'duplicate' bmo */ - CustomData_copy(&bm_old->vdata, &bm_new->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0); - CustomData_copy(&bm_old->edata, &bm_new->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0); - CustomData_copy(&bm_old->ldata, &bm_new->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0); - CustomData_copy(&bm_old->pdata, &bm_new->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0); - - CustomData_bmesh_init_pool(&bm_new->vdata, bm_mesh_allocsize_default.totvert, BM_VERT); - CustomData_bmesh_init_pool(&bm_new->edata, bm_mesh_allocsize_default.totedge, BM_EDGE); - CustomData_bmesh_init_pool(&bm_new->ldata, bm_mesh_allocsize_default.totloop, BM_LOOP); - CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE); + BM_mesh_copy_init_customdata(bm_new, bm_old, &bm_mesh_allocsize_default); /* Take into account user preferences for duplicating actions. */ const eDupli_ID_Flags dupflag = USER_DUP_MESH | (U.dupflag & USER_DUP_ACT); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index da14d4ef52a..c774bc9f9cc 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1330,9 +1330,9 @@ static int object_clear_paths_exec(bContext *C, wmOperator *op) } /* operator callback/wrapper */ -static int object_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *evt) +static int object_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if ((evt->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) { + if ((event->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) { RNA_boolean_set(op->ptr, "only_selected", true); } return object_clear_paths_exec(C, op); diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index 3a584a7f0cb..efa714e315d 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -663,11 +663,11 @@ static int action_unlink_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt) +static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *event) { /* NOTE: this is hardcoded to match the behavior for the unlink button * (in interface_templates.c). */ - RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0); + RNA_boolean_set(op->ptr, "force_delete", event->shift != 0); return action_unlink_exec(C, op); } diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index fb297672f0f..f2cea23af76 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -594,11 +594,11 @@ static int nla_action_unlink_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt) +static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *event) { /* NOTE: this is hardcoded to match the behavior for the unlink button * (in interface_templates.c) */ - RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0); + RNA_boolean_set(op->ptr, "force_delete", event->shift != 0); return nla_action_unlink_exec(C, op); } diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 162f3878f7e..5a0cacf070b 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -1236,16 +1236,15 @@ static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char for (const NodeWarning &warning : warnings.drop_back(1)) { complete_string += warning.message; + /* Adding the period is not ideal for multi-line messages, but it is consistent + * with other tooltip implementations in Blender, so it is added here. */ + complete_string += '.'; complete_string += '\n'; } + /* Let the tooltip system automatically add the last period. */ complete_string += warnings.last().message; - /* Remove the last period-- the tooltip system adds this automatically. */ - if (complete_string.back() == '.') { - complete_string.pop_back(); - } - return BLI_strdupn(complete_string.c_str(), complete_string.size()); } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 4826b6c72ba..5205e50b0bf 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -2231,10 +2231,13 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) link->tosock->new_sock); } - ntreeUpdateTree(CTX_data_main(C), snode->edittree); + Main *bmain = CTX_data_main(C); + ntreeUpdateTree(bmain, snode->edittree); snode_notify(C, snode); snode_dag_update(C, snode); + /* Pasting nodes can create arbitrary new relations, because nodes can reference IDs. */ + DEG_relations_tag_update(bmain); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc index 41f04dad221..982c57eb3ec 100644 --- a/source/blender/editors/space_node/node_geometry_attribute_search.cc +++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc @@ -69,6 +69,12 @@ static void attribute_search_update_fn( UI_search_item_add(items, str, (void *)str, ICON_ADD, 0, 0); } + if (str[0] == '\0' && !is_first) { + /* Allow clearing the text field when the string is empty, but not on the first pass, + * or opening an attribute field for the first time would show this search item. */ + UI_search_item_add(items, str, (void *)str, ICON_X, 0, 0); + } + /* Skip the filter when the menu is first opened, so all of the items are visible. */ if (is_first) { for (const std::string &attribute_name : attribute_name_hints) { diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 4ec8f56480e..19700b258ae 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -38,11 +38,9 @@ struct bContext; struct bNode; struct bNodeLink; struct bNodeSocket; -struct uiBut; struct wmGizmoGroupType; struct wmKeyConfig; struct wmWindow; -struct uiBlock; #ifdef __cplusplus extern "C" { diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index d1260f02c67..09aa268d856 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -2267,7 +2267,7 @@ static bool ed_operator_outliner_id_orphans_active(bContext *C) /** \} */ -static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt)) +static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Main *bmain = CTX_data_main(C); int num_tagged[INDEX_ID_MAX] = {0}; diff --git a/source/blender/editors/space_outliner/tree/tree_display_libraries.cc b/source/blender/editors/space_outliner/tree/tree_display_libraries.cc index cb5f42f08e1..a81ce11498a 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_libraries.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_libraries.cc @@ -111,7 +111,7 @@ TreeElement *TreeDisplayLibraries::add_library_contents(Main &mainvar, { const short filter_id_type = id_filter_get(); - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int tot; if (filter_id_type) { lbarray[0] = which_libbase(&mainvar, space_outliner_.filter_id_type); diff --git a/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc b/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc index 0b17ea98831..559cb289f3f 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc @@ -42,7 +42,7 @@ TreeDisplayIDOrphans::TreeDisplayIDOrphans(SpaceOutliner &space_outliner) ListBase TreeDisplayIDOrphans::buildTree(const TreeSourceData &source_data) { ListBase tree = {nullptr}; - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; short filter_id_type = (space_outliner_.filter & SO_FILTER_ID_TYPE) ? space_outliner_.filter_id_type : 0; diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 43cbcb0aba4..2037981e655 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -550,7 +550,7 @@ static void applyObjectConstraintSize(TransInfo *t, } static void constraints_rotation_impl(TransInfo *t, - float axismtx[3][3], + const float axismtx[3][3], float r_vec[3], float *r_angle) { @@ -621,7 +621,7 @@ static void applyObjectConstraintRot( { if (t->con.mode & CON_APPLY) { float tmp_axismtx[3][3]; - float(*axismtx)[3]; + const float(*axismtx)[3]; /* on setup call, use first object */ if (td == NULL) { diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c index 244cd552495..45df0e66691 100644 --- a/source/blender/editors/transform/transform_convert_gpencil.c +++ b/source/blender/editors/transform/transform_convert_gpencil.c @@ -37,6 +37,7 @@ #include "BKE_gpencil_geom.h" #include "ED_gpencil.h" +#include "ED_keyframing.h" #include "transform.h" #include "transform_convert.h" @@ -114,6 +115,7 @@ static void createTransGPencil_curves(bContext *C, #define SEL_F3 (1 << 2) View3D *v3d = t->view; + Scene *scene = CTX_data_scene(C); const bool handle_only_selected_visible = (v3d->overlay.handle_display == CURVE_HANDLE_SELECTED); const bool handle_all_visible = (v3d->overlay.handle_display == CURVE_HANDLE_ALL); @@ -230,7 +232,9 @@ static void createTransGPencil_curves(bContext *C, } if ((gpf->framenum != cfra) && (!is_multiedit)) { - gpf = BKE_gpencil_frame_addcopy(gpl, cfra); + if (IS_AUTOKEY_ON(scene)) { + gpf = BKE_gpencil_frame_addcopy(gpl, cfra); + } /* in some weird situations (framelock enabled) return NULL */ if (gpf == NULL) { continue; @@ -405,6 +409,7 @@ static void createTransGPencil_strokes(bContext *C, const bool is_prop_edit_connected, const bool is_scale_thickness) { + Scene *scene = CTX_data_scene(C); TransData *td = NULL; float mtx[3][3], smtx[3][3]; @@ -517,7 +522,9 @@ static void createTransGPencil_strokes(bContext *C, * spent too much time editing the wrong frame... */ if ((gpf->framenum != cfra) && (!is_multiedit)) { - gpf = BKE_gpencil_frame_addcopy(gpl, cfra); + if (IS_AUTOKEY_ON(scene)) { + gpf = BKE_gpencil_frame_addcopy(gpl, cfra); + } /* in some weird situations (framelock enabled) return NULL */ if (gpf == NULL) { continue; diff --git a/source/blender/editors/util/ed_draw.c b/source/blender/editors/util/ed_draw.c index 94adba36664..d7b22b4f601 100644 --- a/source/blender/editors/util/ed_draw.c +++ b/source/blender/editors/util/ed_draw.c @@ -116,7 +116,7 @@ BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int off BLI_INLINE bool metadata_is_custom_drawable(const char *field) { - /* Metadata field stored by Blender for multilayer EXR images. Is rather + /* Metadata field stored by Blender for multi-layer EXR images. Is rather * useless to be viewed all the time. Can still be seen in the Metadata * panel. */ if (STREQ(field, "BlenderMultiChannel")) { diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc index e56dcd16528..062741a6270 100644 --- a/source/blender/gpu/intern/gpu_immediate.cc +++ b/source/blender/gpu/intern/gpu_immediate.cc @@ -606,7 +606,7 @@ void immUniform4fv(const char *name, const float data[4]) /* Note array index is not supported for name (i.e: "array[0]"). */ void immUniformArray4fv(const char *name, const float *data, int count) { - GPU_shader_uniform_4fv_array(imm->shader, name, count, (float(*)[4])data); + GPU_shader_uniform_4fv_array(imm->shader, name, count, (const float(*)[4])data); } void immUniformMatrix4fv(const char *name, const float data[4][4]) diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index 31dca888732..89e648a7d6a 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -32,7 +32,6 @@ extern "C" { struct ImBuf; struct OCIO_ConstCPUProcessorRcPtr; -struct OCIO_ConstProcessorRcPtr; extern float imbuf_luma_coefficients[3]; extern float imbuf_xyz_to_rgb[3][3]; diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 67e33366199..14f0fef5270 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -722,8 +722,36 @@ typedef enum IDRecalcFlag { FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS | \ FILTER_ID_LP | FILTER_ID_HA | FILTER_ID_PT | FILTER_ID_VO | FILTER_ID_SIM) -/* IMPORTANT: this enum matches the order currently use in set_listbasepointers, - * keep them in sync! */ +/** + * This enum defines the index assigned to each type of IDs in the array returned by + * #set_listbasepointers, and by extension, controls the default order in which each ID type is + * processed during standard 'foreach' looping over all IDs of a #Main data-base. + * + * About Order: + * ------------ + * + * This is (loosely) defined with a relationship order in mind, from lowest level (ID types using, + * referencing almost no other ID types) to highest level (ID types potentially using many other ID + * types). + * + * So e.g. it ensures that this dependency chain is respected: + * #Material <- #Mesh <- #Object <- #Collection <- #Scene + * + * Default order of processing of IDs in 'foreach' macros (#FOREACH_MAIN_ID_BEGIN and the like), + * built on top of #set_listbasepointers, is actually reversed compared to the order defined here, + * since processing usually needs to happen on users before it happens on used IDs (when freeing + * e.g.). + * + * DO NOT rely on this order as being full-proofed dependency order, there are many cases were it + * can be violated (most obvious cases being custom properties and drivers, which can reference any + * other ID types). + * + * However, this order can be considered as an optimization heuristic, especially when processing + * relationships in a non-recursive pattern: in typical cases, a vast majority of those + * relationships can be processed fine in the first pass, and only few additional passes are + * required to address all remaining relationship cases. + * See e.g. how #BKE_library_unused_linked_data_set_tag is doing this. + */ enum { INDEX_ID_LI = 0, INDEX_ID_IP, @@ -763,6 +791,8 @@ enum { INDEX_ID_SCE, INDEX_ID_WS, INDEX_ID_WM, + /* TODO: This should probably be tweaked, #Mask and #Simulation are rather low-level types that + * should most likely be defined //before// #Object and geometry type indices? */ INDEX_ID_MSK, INDEX_ID_SIM, INDEX_ID_NULL, diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 89e547aaf22..68d69a671ba 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -154,8 +154,8 @@ typedef struct wmWindowManager { /** Operator registry. */ ListBase operators; - /** Refresh/redraw wmNotifier structs. */ - ListBase queue; + /** Refresh/redraw #wmNotifier structs. */ + ListBase notifier_queue; /** Information and error reports. */ struct ReportList reports; @@ -251,13 +251,14 @@ typedef struct wmWindow { struct bScreen *screen DNA_DEPRECATED; + /** Winid also in screens, is for retrieving this window after read. */ + int winid; /** Window coords. */ short posx, posy, sizex, sizey; /** Borderless, full. */ char windowstate; /** Set to 1 if an active window, for quick rejects. */ char active; - char _pad0[4]; /** Current mouse cursor type. */ short cursor; /** Previous cursor when setting modal one. */ @@ -271,16 +272,22 @@ typedef struct wmWindow { char addmousemove; char tag_cursor_refresh; - /** Winid also in screens, is for retrieving this window after read. */ - int winid; + /* Track the state of the event queue, + * these store the state that needs to be kept between handling events in the queue. */ + /** Enable when #KM_PRESS events are not handled (keyboard/mouse-buttons only). */ + char event_queue_check_click; + /** Enable when #KM_PRESS events are not handled (keyboard/mouse-buttons only). */ + char event_queue_check_drag; + + char _pad0[2]; /** Internal, lock pie creation from this event until released. */ - short lock_pie_event; + short pie_event_type_lock; /** * Exception to the above rule for nested pies, store last pie event for operators * that spawn a new pie right after destruction of last pie. */ - short last_pie_event; + short pie_event_type_last; /** Storage for event system. */ struct wmEvent *eventstate; @@ -292,8 +299,8 @@ typedef struct wmWindow { * Currently WIN32, runtime-only data. */ struct wmIMEData *ime_data; - /** All events (ghost level events were handled). */ - ListBase queue; + /** All events #wmEvent (ghost level events were handled). */ + ListBase event_queue; /** Window+screen handlers, handled last. */ ListBase handlers; /** Priority handlers, handled first. */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index b9fc89db0d1..1ac224b27e4 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -5977,7 +5977,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "frs_sec"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 1, SHRT_MAX); - RNA_def_property_ui_range(prop, 1, 120, 1, -1); + RNA_def_property_ui_range(prop, 1, 240, 1, -1); RNA_def_property_ui_text(prop, "FPS", "Framerate, expressed in frames per second"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_fps_update"); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 796b8164cd9..4097e2dddea 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -6090,7 +6090,9 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) prop = RNA_def_property(srna, "use_relative_paths", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_RELPATHS); RNA_def_property_ui_text( - prop, "Relative Paths", "Default relative path option for the file selector"); + prop, + "Relative Paths", + "Default relative path option for the file selector, when no path is defined yet"); prop = RNA_def_property(srna, "use_file_compression", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_FILECOMPRESS); @@ -6215,7 +6217,8 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_SAVE_PREVIEWS); RNA_def_property_ui_text(prop, "Save Preview Images", - "Enables automatic saving of preview images in the .blend file"); + "Enables automatic saving of preview images in the .blend file " + "as well as a thumbnail of the .blend"); rna_def_userdef_filepaths_asset_library(brna); diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 8122f4617c1..a6b83ed60ea 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -135,10 +135,11 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, return mesh; } - /* make sure there are UV Maps available */ - + /* Create a new layer if no UV Maps are available + * (e.g. if a preceding modifier could not preserve it). */ if (!CustomData_has_layer(&mesh->ldata, CD_MLOOPUV)) { - return mesh; + CustomData_add_layer_named( + &mesh->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, mesh->totloop, umd->uvlayer_name); } /* make sure we're using an existing layer */ diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 8c5081555fc..50e29d4a447 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -62,7 +62,7 @@ set(SRC composite/nodes/node_composite_composite.c composite/nodes/node_composite_cornerpin.c composite/nodes/node_composite_crop.c - composite/nodes/node_composite_cryptomatte.c + composite/nodes/node_composite_cryptomatte.cc composite/nodes/node_composite_curves.c composite/nodes/node_composite_defocus.c composite/nodes/node_composite_denoise.c diff --git a/source/blender/nodes/NOD_derived_node_tree.hh b/source/blender/nodes/NOD_derived_node_tree.hh index 62affe43895..ea67f23eade 100644 --- a/source/blender/nodes/NOD_derived_node_tree.hh +++ b/source/blender/nodes/NOD_derived_node_tree.hh @@ -174,8 +174,6 @@ class DParentNode : NonCopyable, NonMovable { int id() const; }; -using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>; - class DerivedNodeTree : NonCopyable, NonMovable { private: LinearAllocator<> allocator_; diff --git a/source/blender/nodes/NOD_node_tree_ref.hh b/source/blender/nodes/NOD_node_tree_ref.hh index c1ff7bfe5e0..3c898aaf0ff 100644 --- a/source/blender/nodes/NOD_node_tree_ref.hh +++ b/source/blender/nodes/NOD_node_tree_ref.hh @@ -67,6 +67,7 @@ class OutputSocketRef; class NodeRef; class NodeTreeRef; class LinkRef; +class InternalLinkRef; class SocketRef : NonCopyable, NonMovable { protected: @@ -106,16 +107,21 @@ class SocketRef : NonCopyable, NonMovable { StringRefNull idname() const; StringRefNull name() const; StringRefNull identifier() const; + bNodeSocketType *typeinfo() const; bNodeSocket *bsocket() const; bNode *bnode() const; bNodeTree *btree() const; + + bool is_available() const; }; class InputSocketRef final : public SocketRef { public: Span<const OutputSocketRef *> linked_sockets() const; Span<const OutputSocketRef *> directly_linked_sockets() const; + + bool is_multi_input_socket() const; }; class OutputSocketRef final : public SocketRef { @@ -132,6 +138,7 @@ class NodeRef : NonCopyable, NonMovable { int id_; Vector<InputSocketRef *> inputs_; Vector<OutputSocketRef *> outputs_; + Vector<InternalLinkRef *> internal_links_; friend NodeTreeRef; @@ -140,6 +147,7 @@ class NodeRef : NonCopyable, NonMovable { Span<const InputSocketRef *> inputs() const; Span<const OutputSocketRef *> outputs() const; + Span<const InternalLinkRef *> internal_links() const; const InputSocketRef &input(int index) const; const OutputSocketRef &output(int index) const; @@ -150,6 +158,7 @@ class NodeRef : NonCopyable, NonMovable { PointerRNA *rna() const; StringRefNull idname() const; StringRefNull name() const; + bNodeType *typeinfo() const; int id() const; @@ -175,6 +184,21 @@ class LinkRef : NonCopyable, NonMovable { bNodeLink *blink() const; }; +class InternalLinkRef : NonCopyable, NonMovable { + private: + InputSocketRef *from_; + OutputSocketRef *to_; + bNodeLink *blink_; + + friend NodeTreeRef; + + public: + const InputSocketRef &from() const; + const OutputSocketRef &to() const; + + bNodeLink *blink() const; +}; + class NodeTreeRef : NonCopyable, NonMovable { private: LinearAllocator<> allocator_; @@ -217,6 +241,19 @@ class NodeTreeRef : NonCopyable, NonMovable { void find_targets_skipping_reroutes(OutputSocketRef &socket_ref, Vector<SocketRef *> &r_targets); }; +using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>; + +const NodeTreeRef &get_tree_ref_from_map(NodeTreeRefMap &node_tree_refs, bNodeTree &btree); + +namespace node_tree_ref_types { +using nodes::InputSocketRef; +using nodes::NodeRef; +using nodes::NodeTreeRef; +using nodes::NodeTreeRefMap; +using nodes::OutputSocketRef; +using nodes::SocketRef; +} // namespace node_tree_ref_types + /* -------------------------------------------------------------------- * SocketRef inline methods. */ @@ -308,6 +345,11 @@ inline StringRefNull SocketRef::identifier() const return bsocket_->identifier; } +inline bNodeSocketType *SocketRef::typeinfo() const +{ + return bsocket_->typeinfo; +} + inline bNodeSocket *SocketRef::bsocket() const { return bsocket_; @@ -323,6 +365,11 @@ inline bNodeTree *SocketRef::btree() const return node_->btree(); } +inline bool SocketRef::is_available() const +{ + return (bsocket_->flag & SOCK_UNAVAIL) == 0; +} + /* -------------------------------------------------------------------- * InputSocketRef inline methods. */ @@ -337,6 +384,11 @@ inline Span<const OutputSocketRef *> InputSocketRef::directly_linked_sockets() c return directly_linked_sockets_.as_span().cast<const OutputSocketRef *>(); } +inline bool InputSocketRef::is_multi_input_socket() const +{ + return bsocket_->flag & SOCK_MULTI_INPUT; +} + /* -------------------------------------------------------------------- * OutputSocketRef inline methods. */ @@ -370,6 +422,11 @@ inline Span<const OutputSocketRef *> NodeRef::outputs() const return outputs_; } +inline Span<const InternalLinkRef *> NodeRef::internal_links() const +{ + return internal_links_; +} + inline const InputSocketRef &NodeRef::input(int index) const { return *inputs_[index]; @@ -405,6 +462,11 @@ inline StringRefNull NodeRef::name() const return bnode_->name; } +inline bNodeType *NodeRef::typeinfo() const +{ + return bnode_->typeinfo; +} + inline int NodeRef::id() const { return id_; @@ -455,6 +517,25 @@ inline bNodeLink *LinkRef::blink() const } /* -------------------------------------------------------------------- + * InternalLinkRef inline methods. + */ + +inline const InputSocketRef &InternalLinkRef::from() const +{ + return *from_; +} + +inline const OutputSocketRef &InternalLinkRef::to() const +{ + return *to_; +} + +inline bNodeLink *InternalLinkRef::blink() const +{ + return blink_; +} + +/* -------------------------------------------------------------------- * NodeTreeRef inline methods. */ diff --git a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc index f5308fe2671..84cd84e41c7 100644 --- a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc @@ -27,35 +27,36 @@ #include "BLI_utildefines.h" #include "node_composite_util.h" -static CryptomatteEntry *cryptomatte_find(NodeCryptomatte *n, float encoded_hash) +extern "C" { +static CryptomatteEntry *cryptomatte_find(const NodeCryptomatte &n, float encoded_hash) { - LISTBASE_FOREACH (CryptomatteEntry *, entry, &n->entries) { + LISTBASE_FOREACH (CryptomatteEntry *, entry, &n.entries) { if (entry->encoded_hash == encoded_hash) { return entry; } } - return NULL; + return nullptr; } -static void cryptomatte_add(NodeCryptomatte *n, float f) +static void cryptomatte_add(NodeCryptomatte &n, float f) { /* Check if entry already exist. */ - if (cryptomatte_find(n, f) != NULL) { + if (cryptomatte_find(n, f)) { return; } - CryptomatteEntry *entry = MEM_callocN(sizeof(CryptomatteEntry), __func__); + CryptomatteEntry *entry = static_cast<CryptomatteEntry *>( + MEM_callocN(sizeof(CryptomatteEntry), __func__)); entry->encoded_hash = f; - BLI_addtail(&n->entries, entry); + BLI_addtail(&n.entries, entry); } -static void cryptomatte_remove(NodeCryptomatte *n, float f) +static void cryptomatte_remove(NodeCryptomatte &n, float f) { CryptomatteEntry *entry = cryptomatte_find(n, f); - if (entry == NULL) { + if (!entry) { return; } - - BLI_remlink(&n->entries, entry); + BLI_remlink(&n.entries, entry); MEM_freeN(entry); } @@ -68,44 +69,40 @@ static bNodeSocketTemplate outputs[] = { void ntreeCompositCryptomatteSyncFromAdd(bNodeTree *UNUSED(ntree), bNode *node) { - NodeCryptomatte *n = node->storage; + NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage); if (n->add[0] != 0.0f) { - cryptomatte_add(n, n->add[0]); - n->add[0] = 0.0f; - n->add[1] = 0.0f; - n->add[2] = 0.0f; + cryptomatte_add(*n, n->add[0]); + zero_v3(n->add); } } void ntreeCompositCryptomatteSyncFromRemove(bNodeTree *UNUSED(ntree), bNode *node) { - NodeCryptomatte *n = node->storage; + NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage); if (n->remove[0] != 0.0f) { - cryptomatte_remove(n, n->remove[0]); - n->remove[0] = 0.0f; - n->remove[1] = 0.0f; - n->remove[2] = 0.0f; + cryptomatte_remove(*n, n->remove[0]); + zero_v3(n->remove); } } bNodeSocket *ntreeCompositCryptomatteAddSocket(bNodeTree *ntree, bNode *node) { - NodeCryptomatte *n = node->storage; + NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage); char sockname[32]; n->num_inputs++; BLI_snprintf(sockname, sizeof(sockname), "Crypto %.2d", n->num_inputs - 1); bNodeSocket *sock = nodeAddStaticSocket( - ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, NULL, sockname); + ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, nullptr, sockname); return sock; } int ntreeCompositCryptomatteRemoveSocket(bNodeTree *ntree, bNode *node) { - NodeCryptomatte *n = node->storage; + NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage); if (n->num_inputs < 2) { return 0; } - bNodeSocket *sock = node->inputs.last; + bNodeSocket *sock = static_cast<bNodeSocket *>(node->inputs.last); nodeRemoveSocket(ntree, node, sock); n->num_inputs--; return 1; @@ -113,7 +110,8 @@ int ntreeCompositCryptomatteRemoveSocket(bNodeTree *ntree, bNode *node) static void init(bNodeTree *ntree, bNode *node) { - NodeCryptomatte *user = MEM_callocN(sizeof(NodeCryptomatte), "cryptomatte user"); + NodeCryptomatte *user = static_cast<NodeCryptomatte *>( + MEM_callocN(sizeof(NodeCryptomatte), __func__)); node->storage = user; nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, "image", "Image"); @@ -126,7 +124,7 @@ static void init(bNodeTree *ntree, bNode *node) static void node_free_cryptomatte(bNode *node) { - NodeCryptomatte *nc = node->storage; + NodeCryptomatte *nc = static_cast<NodeCryptomatte *>(node->storage); if (nc) { BLI_freelistN(&nc->entries); @@ -138,8 +136,8 @@ static void node_copy_cryptomatte(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node) { - NodeCryptomatte *src_nc = src_node->storage; - NodeCryptomatte *dest_nc = MEM_dupallocN(src_nc); + NodeCryptomatte *src_nc = static_cast<NodeCryptomatte *>(src_node->storage); + NodeCryptomatte *dest_nc = static_cast<NodeCryptomatte *>(MEM_dupallocN(src_nc)); BLI_duplicatelist(&dest_nc->entries, &src_nc->entries); dest_node->storage = dest_nc; @@ -150,8 +148,9 @@ void register_node_type_cmp_cryptomatte(void) static bNodeType ntype; cmp_node_type_base(&ntype, CMP_NODE_CRYPTOMATTE, "Cryptomatte", NODE_CLASS_CONVERTOR, 0); - node_type_socket_templates(&ntype, NULL, outputs); + node_type_socket_templates(&ntype, nullptr, outputs); node_type_init(&ntype, init); node_type_storage(&ntype, "NodeCryptomatte", node_free_cryptomatte, node_copy_cryptomatte); nodeRegisterType(&ntype); } +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc index bb5b5073c32..27c35da7d37 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc @@ -224,7 +224,7 @@ static void randomize_attribute_on_component(GeometryComponent &component, if (operation != GEO_NODE_ATTRIBUTE_RANDOMIZE_REPLACE_CREATE) { if (!component.attribute_exists(attribute_name)) { params.error_message_add(NodeWarningType::Error, - "No attribute with name '" + attribute_name + "'."); + TIP_("No attribute with name \"") + attribute_name + "\""); return; } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc index d9878d54353..c40cb2bb0ae 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc @@ -429,7 +429,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params) params.node().custom1); if (!geometry_set.has_mesh()) { - params.error_message_add(NodeWarningType::Error, "Geometry must contain a mesh."); + params.error_message_add(NodeWarningType::Error, TIP_("Geometry must contain a mesh")); params.set_output("Geometry", std::move(geometry_set_out)); return; } @@ -446,7 +446,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params) const Mesh *mesh_in = mesh_component.get_for_read(); if (mesh_in->mpoly == nullptr) { - params.error_message_add(NodeWarningType::Error, "Mesh has no faces."); + params.error_message_add(NodeWarningType::Error, TIP_("Mesh has no faces")); params.set_output("Geometry", std::move(geometry_set_out)); return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc index 669b5ee4614..dbbb73bd36d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc @@ -103,7 +103,7 @@ static void get_instanced_data__collection( if (BLI_listbase_is_empty(&collection->children) && BLI_listbase_is_empty(&collection->gobject)) { - params.error_message_add(NodeWarningType::Info, "Collection is empty."); + params.error_message_add(NodeWarningType::Info, TIP_("Collection is empty")); return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface_simple.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface_simple.cc index 2a0cb727cd6..38560d277e3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface_simple.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface_simple.cc @@ -49,7 +49,7 @@ static void geo_node_subdivision_surface_simple_exec(GeoNodeExecParams params) #ifndef WITH_OPENSUBDIV params.error_message_add(NodeWarningType::Error, - "Disabled, Blender was built without OpenSubdiv"); + TIP_("Disabled, Blender was built without OpenSubdiv")); params.set_output("Geometry", std::move(geometry_set)); return; #endif diff --git a/source/blender/nodes/intern/derived_node_tree.cc b/source/blender/nodes/intern/derived_node_tree.cc index f5a0e14f18b..a65641bca2a 100644 --- a/source/blender/nodes/intern/derived_node_tree.cc +++ b/source/blender/nodes/intern/derived_node_tree.cc @@ -22,17 +22,11 @@ namespace blender::nodes { -static const NodeTreeRef &get_tree_ref(NodeTreeRefMap &node_tree_refs, bNodeTree *btree) -{ - return *node_tree_refs.lookup_or_add_cb(btree, - [&]() { return std::make_unique<NodeTreeRef>(btree); }); -} - DerivedNodeTree::DerivedNodeTree(bNodeTree *btree, NodeTreeRefMap &node_tree_refs) : btree_(btree) { BLI_assert(btree != nullptr); - const NodeTreeRef &main_tree_ref = get_tree_ref(node_tree_refs, btree); + const NodeTreeRef &main_tree_ref = get_tree_ref_from_map(node_tree_refs, *btree); used_node_tree_refs_.add_new(&main_tree_ref); Vector<DNode *> all_nodes; @@ -144,7 +138,7 @@ BLI_NOINLINE void DerivedNodeTree::expand_group_node(DNode &group_node, return; } - const NodeTreeRef &group_ref = get_tree_ref(node_tree_refs, btree); + const NodeTreeRef &group_ref = get_tree_ref_from_map(node_tree_refs, *btree); used_node_tree_refs_.add(&group_ref); DParentNode &parent = *allocator_.construct<DParentNode>(); @@ -187,16 +181,11 @@ BLI_NOINLINE void DerivedNodeTree::relink_group_inputs(const NodeTreeRef &group_ if (node_refs.size() == 0) { return; } - /* TODO: Pick correct group input node if there are more than one. */ - const NodeRef &input_node_ref = *node_refs[0]; - DNode &input_node = *nodes_by_id[input_node_ref.id()]; int input_amount = group_node.inputs().size(); - BLI_assert(input_amount == input_node_ref.outputs().size() - 1); for (int input_index : IndexRange(input_amount)) { DInputSocket *outside_group = group_node.inputs_[input_index]; - DOutputSocket *inside_group = input_node.outputs_[input_index]; for (DOutputSocket *outside_connected : outside_group->linked_sockets_) { outside_connected->linked_sockets_.remove_first_occurrence_and_reorder(outside_group); @@ -206,21 +195,27 @@ BLI_NOINLINE void DerivedNodeTree::relink_group_inputs(const NodeTreeRef &group_ outside_connected->linked_sockets_.remove_first_occurrence_and_reorder(outside_group); } - for (DInputSocket *inside_connected : inside_group->linked_sockets_) { - inside_connected->linked_sockets_.remove_first_occurrence_and_reorder(inside_group); + for (const NodeRef *input_node_ref : node_refs) { + DNode &input_node = *nodes_by_id[input_node_ref->id()]; + DOutputSocket *inside_group = input_node.outputs_[input_index]; - for (DOutputSocket *outside_connected : outside_group->linked_sockets_) { - inside_connected->linked_sockets_.append(outside_connected); - outside_connected->linked_sockets_.append(inside_connected); - } + for (DInputSocket *inside_connected : inside_group->linked_sockets_) { + inside_connected->linked_sockets_.remove_first_occurrence_and_reorder(inside_group); - for (DGroupInput *outside_connected : outside_group->linked_group_inputs_) { - inside_connected->linked_group_inputs_.append(outside_connected); - outside_connected->linked_sockets_.append(inside_connected); + for (DOutputSocket *outside_connected : outside_group->linked_sockets_) { + inside_connected->linked_sockets_.append(outside_connected); + outside_connected->linked_sockets_.append(inside_connected); + } + + for (DGroupInput *outside_connected : outside_group->linked_group_inputs_) { + inside_connected->linked_group_inputs_.append(outside_connected); + outside_connected->linked_sockets_.append(inside_connected); + } } + + inside_group->linked_sockets_.clear(); } - inside_group->linked_sockets_.clear(); outside_group->linked_sockets_.clear(); outside_group->linked_group_inputs_.clear(); } diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc index a2e0a4dd6a4..9e62b7d7312 100644 --- a/source/blender/nodes/intern/node_geometry_exec.cc +++ b/source/blender/nodes/intern/node_geometry_exec.cc @@ -79,7 +79,7 @@ ReadAttributePtr GeoNodeExecParams::get_input_attribute(const StringRef name, * the domain is empty and we don't expect an attribute anyway). */ if (!name.empty() && component.attribute_domain_size(domain) != 0) { this->error_message_add(NodeWarningType::Error, - std::string("No attribute with name '") + name + "'."); + TIP_("No attribute with name \"") + name + "\""); } return component.attribute_get_constant_for_read(domain, type, default_value); } diff --git a/source/blender/nodes/intern/node_tree_ref.cc b/source/blender/nodes/intern/node_tree_ref.cc index e174f096ff7..7fe21ec8582 100644 --- a/source/blender/nodes/intern/node_tree_ref.cc +++ b/source/blender/nodes/intern/node_tree_ref.cc @@ -52,6 +52,24 @@ NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree) RNA_pointer_create(&btree->id, &RNA_NodeSocket, bsocket, &socket.rna_); } + LISTBASE_FOREACH (bNodeLink *, blink, &bnode->internal_links) { + InternalLinkRef &internal_link = *allocator_.construct<InternalLinkRef>(); + internal_link.blink_ = blink; + for (InputSocketRef *socket_ref : node.inputs_) { + if (socket_ref->bsocket_ == blink->fromsock) { + internal_link.from_ = socket_ref; + break; + } + } + for (OutputSocketRef *socket_ref : node.outputs_) { + if (socket_ref->bsocket_ == blink->tosock) { + internal_link.to_ = socket_ref; + break; + } + } + node.internal_links_.append(&internal_link); + } + input_sockets_.extend(node.inputs_.as_span()); output_sockets_.extend(node.outputs_.as_span()); @@ -229,4 +247,10 @@ std::string NodeTreeRef::to_dot() const return digraph.to_dot_string(); } +const NodeTreeRef &get_tree_ref_from_map(NodeTreeRefMap &node_tree_refs, bNodeTree &btree) +{ + return *node_tree_refs.lookup_or_add_cb(&btree, + [&]() { return std::make_unique<NodeTreeRef>(&btree); }); +} + } // namespace blender::nodes diff --git a/source/blender/python/gpu/gpu_py_batch.c b/source/blender/python/gpu/gpu_py_batch.c index ef795268158..8e803350b53 100644 --- a/source/blender/python/gpu/gpu_py_batch.c +++ b/source/blender/python/gpu/gpu_py_batch.c @@ -279,8 +279,8 @@ static void pygpu_batch__tp_dealloc(BPyGPUBatch *self) GPU_batch_discard(self->batch); #ifdef USE_GPU_PY_REFERENCES + PyObject_GC_UnTrack(self); if (self->references) { - PyObject_GC_UnTrack(self); pygpu_batch__tp_clear(self); Py_XDECREF(self->references); } diff --git a/source/blender/python/gpu/gpu_py_buffer.c b/source/blender/python/gpu/gpu_py_buffer.c index b89d2c6a69f..420a7873517 100644 --- a/source/blender/python/gpu/gpu_py_buffer.c +++ b/source/blender/python/gpu/gpu_py_buffer.c @@ -202,8 +202,7 @@ static void pygpu_buffer__tp_dealloc(BPyGPUBuffer *self) { if (self->parent) { PyObject_GC_UnTrack(self); - pygpu_buffer__tp_clear(self); - Py_XDECREF(self->parent); + Py_CLEAR(self->parent); } else { MEM_freeN(self->buf.as_void); diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c index 9d5671ff702..dff4b169f9a 100644 --- a/source/blender/python/gpu/gpu_py_offscreen.c +++ b/source/blender/python/gpu/gpu_py_offscreen.c @@ -336,8 +336,8 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar region, GPU_offscreen_width(self->ofs), GPU_offscreen_height(self->ofs), - (float(*)[4])py_mat_view->matrix, - (float(*)[4])py_mat_projection->matrix, + (const float(*)[4])py_mat_view->matrix, + (const float(*)[4])py_mat_projection->matrix, true, true, "", diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index c7e195b586d..927ec11c376 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -216,7 +216,7 @@ static PyObject *make_app_info(void) #undef SetObjItem if (PyErr_Occurred()) { - Py_CLEAR(app_info); + Py_DECREF(app_info); return NULL; } return app_info; diff --git a/source/blender/python/intern/bpy_app_alembic.c b/source/blender/python/intern/bpy_app_alembic.c index d5640045977..bb218c57d06 100644 --- a/source/blender/python/intern/bpy_app_alembic.c +++ b/source/blender/python/intern/bpy_app_alembic.c @@ -79,8 +79,8 @@ static PyObject *make_alembic_info(void) SetStrItem("Unknown"); #endif - if (PyErr_Occurred()) { - Py_CLEAR(alembic_info); + if (UNLIKELY(PyErr_Occurred())) { + Py_DECREF(alembic_info); return NULL; } diff --git a/source/blender/python/intern/bpy_app_ffmpeg.c b/source/blender/python/intern/bpy_app_ffmpeg.c index 4e396668450..d2261ee7311 100644 --- a/source/blender/python/intern/bpy_app_ffmpeg.c +++ b/source/blender/python/intern/bpy_app_ffmpeg.c @@ -116,8 +116,8 @@ static PyObject *make_ffmpeg_info(void) #undef FFMPEG_LIB_VERSION - if (PyErr_Occurred()) { - Py_CLEAR(ffmpeg_info); + if (UNLIKELY(PyErr_Occurred())) { + Py_DECREF(ffmpeg_info); return NULL; } diff --git a/source/blender/python/intern/bpy_app_ocio.c b/source/blender/python/intern/bpy_app_ocio.c index 3a36e90018f..8ce87bd0150 100644 --- a/source/blender/python/intern/bpy_app_ocio.c +++ b/source/blender/python/intern/bpy_app_ocio.c @@ -81,8 +81,8 @@ static PyObject *make_ocio_info(void) SetStrItem("Unknown"); #endif - if (PyErr_Occurred()) { - Py_CLEAR(ocio_info); + if (UNLIKELY(PyErr_Occurred())) { + Py_DECREF(ocio_info); return NULL; } diff --git a/source/blender/python/intern/bpy_app_oiio.c b/source/blender/python/intern/bpy_app_oiio.c index 0038f982170..8436296680b 100644 --- a/source/blender/python/intern/bpy_app_oiio.c +++ b/source/blender/python/intern/bpy_app_oiio.c @@ -77,8 +77,8 @@ static PyObject *make_oiio_info(void) SetStrItem("Unknown"); #endif - if (PyErr_Occurred()) { - Py_CLEAR(oiio_info); + if (UNLIKELY(PyErr_Occurred())) { + Py_DECREF(oiio_info); return NULL; } diff --git a/source/blender/python/intern/bpy_app_opensubdiv.c b/source/blender/python/intern/bpy_app_opensubdiv.c index 90aab2a4500..635013a1f9e 100644 --- a/source/blender/python/intern/bpy_app_opensubdiv.c +++ b/source/blender/python/intern/bpy_app_opensubdiv.c @@ -74,8 +74,8 @@ static PyObject *make_opensubdiv_info(void) SetStrItem("Unknown"); #endif - if (PyErr_Occurred()) { - Py_CLEAR(opensubdiv_info); + if (UNLIKELY(PyErr_Occurred())) { + Py_DECREF(opensubdiv_info); return NULL; } diff --git a/source/blender/python/intern/bpy_app_openvdb.c b/source/blender/python/intern/bpy_app_openvdb.c index c98c6ec0137..20a61ba170a 100644 --- a/source/blender/python/intern/bpy_app_openvdb.c +++ b/source/blender/python/intern/bpy_app_openvdb.c @@ -81,8 +81,8 @@ static PyObject *make_openvdb_info(void) SetStrItem("Unknown"); #endif - if (PyErr_Occurred()) { - Py_CLEAR(openvdb_info); + if (UNLIKELY(PyErr_Occurred())) { + Py_DECREF(openvdb_info); return NULL; } diff --git a/source/blender/python/intern/bpy_app_sdl.c b/source/blender/python/intern/bpy_app_sdl.c index 645119c1c5d..e45e73fb4de 100644 --- a/source/blender/python/intern/bpy_app_sdl.c +++ b/source/blender/python/intern/bpy_app_sdl.c @@ -114,8 +114,8 @@ static PyObject *make_sdl_info(void) SetObjItem(PyBool_FromLong(0)); #endif - if (PyErr_Occurred()) { - Py_CLEAR(sdl_info); + if (UNLIKELY(PyErr_Occurred())) { + Py_DECREF(sdl_info); return NULL; } diff --git a/source/blender/python/intern/bpy_app_usd.c b/source/blender/python/intern/bpy_app_usd.c index 4a0ee96061a..72287d45b93 100644 --- a/source/blender/python/intern/bpy_app_usd.c +++ b/source/blender/python/intern/bpy_app_usd.c @@ -80,8 +80,8 @@ static PyObject *make_usd_info(void) SetStrItem("Unknown"); #endif - if (PyErr_Occurred()) { - Py_CLEAR(usd_info); + if (UNLIKELY(PyErr_Occurred())) { + Py_DECREF(usd_info); return NULL; } diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c index 020c8f7ea49..03771a8c294 100644 --- a/source/blender/python/intern/bpy_library_load.c +++ b/source/blender/python/intern/bpy_library_load.c @@ -34,7 +34,6 @@ #include "BLI_string.h" #include "BLI_utildefines.h" -#include "BKE_context.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" #include "BKE_main.h" @@ -68,9 +67,11 @@ typedef struct { BlendHandle *blo_handle; int flag; PyObject *dict; + /* Borrowed reference to the `bmain`, taken from the RNA instance of #RNA_BlendDataLibraries. */ + Main *bmain; } BPy_Library; -static PyObject *bpy_lib_load(PyObject *self, PyObject *args, PyObject *kwds); +static PyObject *bpy_lib_load(BPy_PropertyRNA *self, PyObject *args, PyObject *kwds); static PyObject *bpy_lib_enter(BPy_Library *self); static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *args); static PyObject *bpy_lib_dir(BPy_Library *self); @@ -182,9 +183,9 @@ PyDoc_STRVAR( " :type relative: bool\n" " :arg assets_only: If True, only list data-blocks marked as assets.\n" " :type assets_only: bool\n"); -static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *kw) +static PyObject *bpy_lib_load(BPy_PropertyRNA *self, PyObject *args, PyObject *kw) { - Main *bmain = CTX_data_main(BPY_context_get()); + Main *bmain = self->ptr.data; /* Typically #G_MAIN */ BPy_Library *ret; const char *filename = NULL; bool is_rel = false, is_link = false, use_assets_only = false; @@ -210,11 +211,13 @@ static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject * BLI_strncpy(ret->abspath, filename, sizeof(ret->abspath)); BLI_path_abs(ret->abspath, BKE_main_blendfile_path(bmain)); + ret->bmain = bmain; + ret->blo_handle = NULL; ret->flag = ((is_link ? FILE_LINK : 0) | (is_rel ? FILE_RELPATH : 0) | (use_assets_only ? FILE_ASSETS_ONLY : 0)); - ret->dict = _PyDict_NewPresized(MAX_LIBARRAY); + ret->dict = _PyDict_NewPresized(INDEX_ID_MAX); return (PyObject *)ret; } @@ -245,7 +248,7 @@ static PyObject *bpy_lib_enter(BPy_Library *self) { PyObject *ret; BPy_Library *self_from; - PyObject *from_dict = _PyDict_NewPresized(MAX_LIBARRAY); + PyObject *from_dict = _PyDict_NewPresized(INDEX_ID_MAX); ReportList reports; BKE_reports_init(&reports, RPT_STORE); @@ -333,7 +336,7 @@ static void bpy_lib_exit_warn_type(BPy_Library *self, PyObject *item) static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) { - Main *bmain = CTX_data_main(BPY_context_get()); + Main *bmain = self->bmain; Main *mainl = NULL; const int err = 0; const bool do_append = ((self->flag & FILE_LINK) == 0); @@ -477,7 +480,7 @@ static PyObject *bpy_lib_dir(BPy_Library *self) PyMethodDef BPY_library_load_method_def = { "load", (PyCFunction)bpy_lib_load, - METH_STATIC | METH_VARARGS | METH_KEYWORDS, + METH_VARARGS | METH_KEYWORDS, bpy_lib_load_doc, }; diff --git a/source/blender/python/intern/bpy_library_write.c b/source/blender/python/intern/bpy_library_write.c index 66d20dd357f..f26f305cca8 100644 --- a/source/blender/python/intern/bpy_library_write.c +++ b/source/blender/python/intern/bpy_library_write.c @@ -71,7 +71,7 @@ PyDoc_STRVAR( " :type fake_user: bool\n" " :arg compress: When True, write a compressed blend file.\n" " :type compress: bool\n"); -static PyObject *bpy_lib_write(PyObject *UNUSED(self), PyObject *args, PyObject *kw) +static PyObject *bpy_lib_write(BPy_PropertyRNA *self, PyObject *args, PyObject *kw) { /* args */ const char *filepath; @@ -114,7 +114,7 @@ static PyObject *bpy_lib_write(PyObject *UNUSED(self), PyObject *args, PyObject return NULL; } - Main *bmain_src = G_MAIN; + Main *bmain_src = self->ptr.data; /* Typically #G_MAIN */ int write_flags = 0; if (use_compress) { @@ -220,6 +220,6 @@ finally: PyMethodDef BPY_library_write_method_def = { "write", (PyCFunction)bpy_lib_write, - METH_STATIC | METH_VARARGS | METH_KEYWORDS, + METH_VARARGS | METH_KEYWORDS, bpy_lib_write_doc, }; diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index b2812e0eba7..246387486be 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -203,10 +203,8 @@ static const EnumPropertyItem property_subtype_array_items[] = { static void bpy_prop_deferred_dealloc(BPy_PropDeferred *self) { - if (self->kw) { - PyObject_GC_UnTrack(self); - Py_CLEAR(self->kw); - } + PyObject_GC_UnTrack(self); + Py_CLEAR(self->kw); PyObject_GC_Del(self); } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 555dd41b228..bad6c4b4b56 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1204,15 +1204,15 @@ static void pyrna_struct_dealloc(BPy_StructRNA *self) static void pyrna_struct_reference_set(BPy_StructRNA *self, PyObject *reference) { if (self->reference) { - // PyObject_GC_UnTrack(self); /* INITIALIZED TRACKED ? */ - pyrna_struct_clear(self); + PyObject_GC_UnTrack(self); + Py_CLEAR(self->reference); } /* Reference is now NULL. */ if (reference) { self->reference = reference; Py_INCREF(reference); - // PyObject_GC_Track(self); /* INITIALIZED TRACKED ? */ + PyObject_GC_Track(self); } } #endif /* !USE_PYRNA_STRUCT_REFERENCE */ @@ -4622,6 +4622,19 @@ static PyObject *pyrna_prop_collection_getattro(BPy_PropertyRNA *self, PyObject if (ret == NULL) { PyErr_Restore(error_type, error_value, error_traceback); } + else { + if (Py_TYPE(ret) == &PyMethodDescr_Type) { + PyMethodDef *m = ((PyMethodDescrObject *)ret)->d_method; + /* TODO: #METH_CLASS */ + if (m->ml_flags & METH_STATIC) { + /* Keep 'ret' as-is. */ + } + else { + Py_DECREF(ret); + ret = PyCMethod_New(m, (PyObject *)self, NULL, NULL); + } + } + } } } @@ -5822,6 +5835,11 @@ static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject * BPy_StructRNA *ret; if ((ret = (BPy_StructRNA *)type->tp_alloc(type, 0))) { ret->ptr = base->ptr; +#ifdef USE_PYRNA_STRUCT_REFERENCE + /* #PyType_GenericAlloc will have set tracking. + * We only want tracking when `StructRNA.reference` has been set. */ + PyObject_GC_UnTrack(ret); +#endif } /* Pass on exception & NULL if tp_alloc fails. */ return (PyObject *)ret; @@ -6525,7 +6543,11 @@ PyTypeObject pyrna_struct_Type = { NULL, /* PyBufferProcs *tp_as_buffer; */ /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* long tp_flags; */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE +#ifdef USE_PYRNA_STRUCT_REFERENCE + | Py_TPFLAGS_HAVE_GC +#endif + , /* long tp_flags; */ NULL, /* char *tp_doc; Documentation string */ /*** Assigned meaning in release 2.0 ***/ @@ -7462,13 +7484,28 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr) if (tp) { pyrna = (BPy_StructRNA *)tp->tp_alloc(tp, 0); +#ifdef USE_PYRNA_STRUCT_REFERENCE + /* #PyType_GenericAlloc will have set tracking. + * We only want tracking when `StructRNA.reference` has been set. */ + if (pyrna != NULL) { + PyObject_GC_UnTrack(pyrna); + } +#endif Py_DECREF(tp); /* srna owns, can't hold a reference. */ } else { CLOG_WARN(BPY_LOG_RNA, "could not make type '%s'", RNA_struct_identifier(ptr->type)); + +#ifdef USE_PYRNA_STRUCT_REFERENCE pyrna = (BPy_StructRNA *)PyObject_GC_New(BPy_StructRNA, &pyrna_struct_Type); +#else + pyrna = (BPy_StructRNA *)PyObject_New(BPy_StructRNA, &pyrna_struct_Type); +#endif + #ifdef USE_WEAKREFS - pyrna->in_weakreflist = NULL; + if (pyrna != NULL) { + pyrna->in_weakreflist = NULL; + } #endif } } diff --git a/source/blender/sequencer/SEQ_add.h b/source/blender/sequencer/SEQ_add.h index e262d7ed1ef..7d728b25a30 100644 --- a/source/blender/sequencer/SEQ_add.h +++ b/source/blender/sequencer/SEQ_add.h @@ -30,7 +30,6 @@ extern "C" { struct ListBase; struct Scene; struct Sequence; -struct bContext; /* SeqLoadData.flags */ typedef enum eSeqLoadFlags { diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 30d12f1322d..e03058d49f9 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -613,10 +613,6 @@ typedef struct wmEvent { /** Raw-key modifier (allow using any key as a modifier). */ short keymodifier; - /** Set in case a #KM_PRESS went by unhandled. */ - char check_click; - char check_drag; - /** Tablet info, available for mouse move and button events. */ wmTabletData tablet; diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index a9c0d1dd8fe..c5a429d7839 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -172,7 +172,7 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id) win->ime_data = NULL; #endif - BLI_listbase_clear(&win->queue); + BLI_listbase_clear(&win->event_queue); BLI_listbase_clear(&win->handlers); BLI_listbase_clear(&win->modalhandlers); BLI_listbase_clear(&win->gesture); @@ -184,6 +184,8 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id) win->modalcursor = 0; win->grabcursor = 0; win->addmousemove = true; + win->event_queue_check_click = 0; + win->event_queue_check_drag = 0; BLO_read_data_address(reader, &win->stereo3d_format); /* Multi-view always fallback to anaglyph at file opening @@ -198,7 +200,7 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id) BLI_listbase_clear(&wm->timers); BLI_listbase_clear(&wm->operators); BLI_listbase_clear(&wm->paintcursors); - BLI_listbase_clear(&wm->queue); + BLI_listbase_clear(&wm->notifier_queue); BKE_reports_init(&wm->reports, RPT_STORE); BLI_listbase_clear(&wm->keyconfigs); @@ -590,7 +592,7 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm) WM_keyconfig_free(keyconf); } - BLI_freelistN(&wm->queue); + BLI_freelistN(&wm->notifier_queue); if (wm->message_bus != NULL) { WM_msgbus_destroy(wm->message_bus); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 411ecb1cac8..fe503167f8d 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -126,12 +126,12 @@ wmEvent *wm_event_add_ex(wmWindow *win, *event = *event_to_add; if (event_to_add_after == NULL) { - BLI_addtail(&win->queue, event); + BLI_addtail(&win->event_queue, event); } else { /* Note: strictly speaking this breaks const-correctness, * however we're only changing 'next' member. */ - BLI_insertlinkafter(&win->queue, (void *)event_to_add_after, event); + BLI_insertlinkafter(&win->event_queue, (void *)event_to_add_after, event); } return event; } @@ -205,7 +205,7 @@ void wm_event_free(wmEvent *event) static void wm_event_free_last(wmWindow *win) { - wmEvent *event = BLI_poptail(&win->queue); + wmEvent *event = BLI_poptail(&win->event_queue); if (event != NULL) { wm_event_free(event); } @@ -214,7 +214,7 @@ static void wm_event_free_last(wmWindow *win) void wm_event_free_all(wmWindow *win) { wmEvent *event; - while ((event = BLI_pophead(&win->queue))) { + while ((event = BLI_pophead(&win->event_queue))) { wm_event_free(event); } } @@ -232,7 +232,7 @@ void wm_event_init_from_window(wmWindow *win, wmEvent *event) static bool wm_test_duplicate_notifier(const wmWindowManager *wm, uint type, void *reference) { - LISTBASE_FOREACH (wmNotifier *, note, &wm->queue) { + LISTBASE_FOREACH (wmNotifier *, note, &wm->notifier_queue) { if ((note->category | note->data | note->subtype | note->action) == type && note->reference == reference) { return true; @@ -250,7 +250,7 @@ void WM_event_add_notifier_ex(wmWindowManager *wm, const wmWindow *win, uint typ wmNotifier *note = MEM_callocN(sizeof(wmNotifier), "notifier"); - BLI_addtail(&wm->queue, note); + BLI_addtail(&wm->notifier_queue, note); note->window = win; @@ -279,7 +279,7 @@ void WM_main_add_notifier(unsigned int type, void *reference) wmNotifier *note = MEM_callocN(sizeof(wmNotifier), "notifier"); - BLI_addtail(&wm->queue, note); + BLI_addtail(&wm->notifier_queue, note); note->category = type & NOTE_CATEGORY; note->data = type & NOTE_DATA; @@ -298,7 +298,7 @@ void WM_main_remove_notifier_reference(const void *reference) wmWindowManager *wm = bmain->wm.first; if (wm) { - LISTBASE_FOREACH_MUTABLE (wmNotifier *, note, &wm->queue) { + LISTBASE_FOREACH_MUTABLE (wmNotifier *, note, &wm->notifier_queue) { if (note->reference == reference) { /* Don't remove because this causes problems for #wm_event_do_notifiers * which may be looping on the data (deleting screens). */ @@ -450,7 +450,7 @@ void wm_event_do_notifiers(bContext *C) CTX_wm_window_set(C, win); - LISTBASE_FOREACH_MUTABLE (wmNotifier *, note, &wm->queue) { + LISTBASE_FOREACH_MUTABLE (wmNotifier *, note, &wm->notifier_queue) { if (note->category == NC_WM) { if (ELEM(note->data, ND_FILEREAD, ND_FILESAVE)) { wm->file_saved = 1; @@ -539,7 +539,7 @@ void wm_event_do_notifiers(bContext *C) /* The notifiers are sent without context, to keep it clean. */ wmNotifier *note; - while ((note = BLI_pophead(&wm->queue))) { + while ((note = BLI_pophead(&wm->notifier_queue))) { LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { Scene *scene = WM_window_get_active_scene(win); bScreen *screen = WM_window_get_active_screen(win); @@ -2960,8 +2960,8 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) /* Test for CLICK_DRAG events. */ if (wm_action_not_handled(action)) { - if (event->check_drag) { - wmWindow *win = CTX_wm_window(C); + wmWindow *win = CTX_wm_window(C); + if (win->event_queue_check_drag) { if (WM_event_drag_test(event, &event->prevclickx)) { int x = event->x; int y = event->y; @@ -2982,15 +2982,18 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) event->x = x; event->y = y; - win->eventstate->check_click = false; - win->eventstate->check_drag = false; + win->event_queue_check_click = false; + if (!wm_action_not_handled(action)) { + /* Only disable when handled as other handlers may use this drag event. */ + win->event_queue_check_drag = false; + } } } } else { wmWindow *win = CTX_wm_window(C); if (win) { - win->eventstate->check_drag = false; + win->event_queue_check_drag = false; } } } @@ -3006,11 +3009,13 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) if (win != NULL) { if (event->val == KM_PRESS) { - win->eventstate->check_click = true; - win->eventstate->check_drag = true; + if (event->prevval != KM_PRESS) { + win->event_queue_check_click = true; + win->event_queue_check_drag = true; + } } else if (event->val == KM_RELEASE) { - win->eventstate->check_drag = false; + win->event_queue_check_drag = false; } } @@ -3018,10 +3023,10 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) if (event->val == KM_RELEASE) { if (event->prevval == KM_PRESS) { - if (win->eventstate->check_click == true) { + if (win->event_queue_check_click == true) { if (WM_event_drag_test(event, &event->prevclickx)) { - win->eventstate->check_click = 0; - win->eventstate->check_drag = 0; + win->event_queue_check_click = false; + win->event_queue_check_drag = false; } else { /* Position is where the actual click happens, for more @@ -3059,8 +3064,8 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) else { wmWindow *win = CTX_wm_window(C); if (win) { - win->eventstate->check_click = 0; - win->eventstate->check_drag = 0; + win->event_queue_check_click = false; + win->event_queue_check_drag = false; } } } @@ -3074,7 +3079,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) wmWindow *win = CTX_wm_window(C); if (win) { if (ISKEYMODIFIER(event->prevtype)) { - win->eventstate->check_click = 0; + win->event_queue_check_click = false; } } } @@ -3221,9 +3226,9 @@ static void wm_event_drag_and_drop_test(wmWindowManager *wm, wmWindow *win, wmEv /* Filter out all events of the pie that spawned the last pie unless it's a release event. */ static bool wm_event_pie_filter(wmWindow *win, const wmEvent *event) { - if (win->lock_pie_event && win->lock_pie_event == event->type) { + if (win->pie_event_type_lock && win->pie_event_type_lock == event->type) { if (event->val == KM_RELEASE) { - win->lock_pie_event = EVENT_NONE; + win->pie_event_type_lock = EVENT_NONE; return false; } return true; @@ -3234,7 +3239,7 @@ static bool wm_event_pie_filter(wmWindow *win, const wmEvent *event) /** * Account for the special case when events are being handled and a file is loaded. * In this case event handling exits early, however when "Load UI" is disabled - * the even will still be in #wmWindow.queue. + * the even will still be in #wmWindow.event_queue. * * Without this it's possible to continuously handle the same event, see: T76484. */ @@ -3242,7 +3247,7 @@ static void wm_event_free_and_remove_from_queue_if_valid(wmEvent *event) { LISTBASE_FOREACH (wmWindowManager *, wm, &G_MAIN->wm) { LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { - if (BLI_remlink_safe(&win->queue, event)) { + if (BLI_remlink_safe(&win->event_queue, event)) { wm_event_free(event); return; } @@ -3331,7 +3336,7 @@ void wm_event_do_handlers(bContext *C) } wmEvent *event; - while ((event = win->queue.first)) { + while ((event = win->event_queue.first)) { int action = WM_HANDLER_CONTINUE; /* Active screen might change during handlers, update pointer. */ @@ -3348,7 +3353,7 @@ void wm_event_do_handlers(bContext *C) if (!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { CLOG_INFO(WM_LOG_HANDLERS, 1, "event filtered due to pie button pressed"); } - BLI_remlink(&win->queue, event); + BLI_remlink(&win->event_queue, event); wm_event_free(event); continue; } @@ -3497,7 +3502,7 @@ void wm_event_do_handlers(bContext *C) * press in tool keymap can override click in editor keymap.*/ if (ISMOUSE_BUTTON(event->type) && event->val == KM_PRESS && !wm_action_not_handled(action)) { - win->eventstate->check_click = false; + win->event_queue_check_click = false; } /* Update previous mouse position for following events to use. */ @@ -3505,11 +3510,11 @@ void wm_event_do_handlers(bContext *C) win->eventstate->prevy = event->y; /* Unlink and free here, blender-quit then frees all. */ - BLI_remlink(&win->queue, event); + BLI_remlink(&win->event_queue, event); wm_event_free(event); } - /* Only add mousemove when queue was read entirely. */ + /* Only add mouse-move when the event queue was read entirely. */ if (win->addmousemove && win->eventstate) { wmEvent tevent = *(win->eventstate); // printf("adding MOUSEMOVE %d %d\n", tevent.x, tevent.y); @@ -4350,11 +4355,11 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi } } - wmWindow *owin; - if (WM_window_find_under_cursor(wm, win, win, mval, &owin, mval)) { + wmWindow *win_other; + if (WM_window_find_under_cursor(wm, win, win, mval, &win_other, mval)) { event->x = mval[0]; event->y = mval[1]; - return owin; + return win_other; } } return NULL; @@ -4395,7 +4400,7 @@ static void wm_event_prev_click_set(wmEvent *event, wmEvent *event_state) static wmEvent *wm_event_add_mousemove(wmWindow *win, const wmEvent *event) { - wmEvent *event_last = win->queue.last; + wmEvent *event_last = win->event_queue.last; /* Some painting operators want accurate mouse events, they can * handle in between mouse move moves, others can happily ignore @@ -4417,7 +4422,7 @@ static wmEvent *wm_event_add_trackpad(wmWindow *win, const wmEvent *event, int d { /* Ignore in between trackpad events for performance, we only need high accuracy * for painting with mouse moves, for navigation using the accumulated value is ok. */ - wmEvent *event_last = win->queue.last; + wmEvent *event_last = win->event_queue.last; if (event_last && event_last->type == event->type) { deltax += event_last->x - event_last->prevx; deltay += event_last->y - event_last->prevy; @@ -4434,7 +4439,7 @@ static wmEvent *wm_event_add_trackpad(wmWindow *win, const wmEvent *event, int d } /** - * Windows store own event queues #wmWindow.queue (no #bContext here). + * Windows store own event queues #wmWindow.event_queue (no #bContext here). */ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void *customdata) { @@ -4443,19 +4448,19 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void } /** - * Having both, \a event and \a evt, can be highly confusing to work with, + * Having both, \a event and \a event_state, can be highly confusing to work with, * but is necessary for our current event system, so let's clear things up a bit: * * - Data added to event only will be handled immediately, * but will not be copied to the next event. - * - Data added to \a evt only stays, + * - Data added to \a event_state only stays, * but is handled with the next event -> execution delay. - * - Data added to event and \a evt stays and is handled immediately. + * - Data added to event and \a event_state stays and is handled immediately. */ - wmEvent event, *evt = win->eventstate; + wmEvent event, *event_state = win->eventstate; /* Initialize and copy state (only mouse x y and modifiers). */ - event = *evt; + event = *event_state; event.is_repeat = false; /** @@ -4473,17 +4478,17 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void /* Ensure the event state is correct, any deviation from this may cause bugs. */ #ifndef NDEBUG - if ((evt->type || evt->val) && /* Ignore cleared event state. */ - !(ISMOUSE_BUTTON(evt->type) || ISKEYBOARD(evt->type))) { + if ((event_state->type || event_state->val) && /* Ignore cleared event state. */ + !(ISMOUSE_BUTTON(event_state->type) || ISKEYBOARD(event_state->type))) { CLOG_WARN(WM_LOG_HANDLERS, "Non-keyboard/mouse button found in 'win->eventstate->type = %d'", - evt->type); + event_state->type); } - if ((evt->prevtype || evt->prevval) && /* Ignore cleared event state. */ - !(ISMOUSE_BUTTON(evt->prevtype) || ISKEYBOARD(evt->prevtype))) { + if ((event_state->prevtype || event_state->prevval) && /* Ignore cleared event state. */ + !(ISMOUSE_BUTTON(event_state->prevtype) || ISKEYBOARD(event_state->prevtype))) { CLOG_WARN(WM_LOG_HANDLERS, "Non-keyboard/mouse button found in 'win->eventstate->prevtype = %d'", - evt->prevtype); + event_state->prevtype); } #endif @@ -4499,28 +4504,26 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void event.type = MOUSEMOVE; { wmEvent *event_new = wm_event_add_mousemove(win, &event); - copy_v2_v2_int(&evt->x, &event_new->x); - evt->tablet.is_motion_absolute = event_new->tablet.is_motion_absolute; + copy_v2_v2_int(&event_state->x, &event_new->x); + event_state->tablet.is_motion_absolute = event_new->tablet.is_motion_absolute; } /* Also add to other window if event is there, this makes overdraws disappear nicely. */ /* It remaps mousecoord to other window in event. */ - wmWindow *owin = wm_event_cursor_other_windows(wm, win, &event); - if (owin) { - wmEvent oevent, *oevt = owin->eventstate; - - oevent = *oevt; + wmWindow *win_other = wm_event_cursor_other_windows(wm, win, &event); + if (win_other) { + wmEvent event_other = *win_other->eventstate; /* See comment for this operation on `event` for details. */ - oevent.prevtype = oevent.type; - oevent.prevval = oevent.val; + event_other.prevtype = event_other.type; + event_other.prevval = event_other.val; - copy_v2_v2_int(&oevent.x, &event.x); - oevent.type = MOUSEMOVE; + copy_v2_v2_int(&event_other.x, &event.x); + event_other.type = MOUSEMOVE; { - wmEvent *event_new = wm_event_add_mousemove(owin, &oevent); - copy_v2_v2_int(&oevt->x, &event_new->x); - oevt->tablet.is_motion_absolute = event_new->tablet.is_motion_absolute; + wmEvent *event_new = wm_event_add_mousemove(win_other, &event_other); + copy_v2_v2_int(&win_other->eventstate->x, &event_new->x); + win_other->eventstate->tablet.is_motion_absolute = event_new->tablet.is_motion_absolute; } } @@ -4546,8 +4549,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void break; } - event.x = evt->x = pd->x; - event.y = evt->y = pd->y; + event.x = event_state->x = pd->x; + event.y = event_state->y = pd->y; event.val = KM_NOTHING; /* The direction is inverted from the device due to system preferences. */ @@ -4590,11 +4593,11 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void wm_tablet_data_from_ghost(&bd->tablet, &event.tablet); wm_eventemulation(&event, false); - wm_event_prev_values_set(&event, evt); + wm_event_prev_values_set(&event, event_state); /* Copy to event state. */ - evt->val = event.val; - evt->type = event.type; + event_state->val = event.val; + event_state->type = event.type; /* Double click test. */ if (wm_event_is_double_click(&event)) { @@ -4602,25 +4605,25 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void event.val = KM_DBL_CLICK; } if (event.val == KM_PRESS) { - wm_event_prev_click_set(&event, evt); + wm_event_prev_click_set(&event, event_state); } /* Add to other window if event is there (not to both!). */ - wmWindow *owin = wm_event_cursor_other_windows(wm, win, &event); - if (owin) { - wmEvent oevent = *(owin->eventstate); + wmWindow *win_other = wm_event_cursor_other_windows(wm, win, &event); + if (win_other) { + wmEvent event_other = *win_other->eventstate; /* See comment for this operation on `event` for details. */ - oevent.prevtype = oevent.type; - oevent.prevval = oevent.val; + event_other.prevtype = event_other.type; + event_other.prevval = event_other.val; - copy_v2_v2_int(&oevent.x, &event.x); + copy_v2_v2_int(&event_other.x, &event.x); - oevent.type = event.type; - oevent.val = event.val; - oevent.tablet = event.tablet; + event_other.type = event.type; + event_other.val = event.val; + event_other.tablet = event.tablet; - wm_event_add(owin, &oevent); + wm_event_add(win_other, &event_other); } else { wm_event_add(win, &event); @@ -4641,12 +4644,12 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE; wm_eventemulation(&event, false); - wm_event_prev_values_set(&event, evt); + wm_event_prev_values_set(&event, event_state); /* Copy to event state. */ - evt->val = event.val; - evt->type = event.type; - evt->is_repeat = event.is_repeat; + event_state->val = event.val; + event_state->type = event.type; + event_state->is_repeat = event.is_repeat; /* Exclude arrow keys, esc, etc from text input. */ if (type == GHOST_kEventKeyUp) { @@ -4682,57 +4685,57 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void case EVT_LEFTSHIFTKEY: case EVT_RIGHTSHIFTKEY: if (event.val == KM_PRESS) { - if (evt->ctrl || evt->alt || evt->oskey) { + if (event_state->ctrl || event_state->alt || event_state->oskey) { keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND); } else { keymodifier = KM_MOD_FIRST; } } - event.shift = evt->shift = keymodifier; + event.shift = event_state->shift = keymodifier; break; case EVT_LEFTCTRLKEY: case EVT_RIGHTCTRLKEY: if (event.val == KM_PRESS) { - if (evt->shift || evt->alt || evt->oskey) { + if (event_state->shift || event_state->alt || event_state->oskey) { keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND); } else { keymodifier = KM_MOD_FIRST; } } - event.ctrl = evt->ctrl = keymodifier; + event.ctrl = event_state->ctrl = keymodifier; break; case EVT_LEFTALTKEY: case EVT_RIGHTALTKEY: if (event.val == KM_PRESS) { - if (evt->ctrl || evt->shift || evt->oskey) { + if (event_state->ctrl || event_state->shift || event_state->oskey) { keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND); } else { keymodifier = KM_MOD_FIRST; } } - event.alt = evt->alt = keymodifier; + event.alt = event_state->alt = keymodifier; break; case EVT_OSKEY: if (event.val == KM_PRESS) { - if (evt->ctrl || evt->alt || evt->shift) { + if (event_state->ctrl || event_state->alt || event_state->shift) { keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND); } else { keymodifier = KM_MOD_FIRST; } } - event.oskey = evt->oskey = keymodifier; + event.oskey = event_state->oskey = keymodifier; break; default: if (event.val == KM_PRESS && event.keymodifier == 0) { /* Only set in eventstate, for next event. */ - evt->keymodifier = event.type; + event_state->keymodifier = event.type; } else if (event.val == KM_RELEASE && event.keymodifier == event.type) { - event.keymodifier = evt->keymodifier = 0; + event.keymodifier = event_state->keymodifier = 0; } break; } @@ -4755,7 +4758,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void * Since it's impossible to map a key modifier to an unknown key, * it shouldn't harm to clear it. */ if (event.keymodifier == EVT_UNKNOWNKEY) { - evt->keymodifier = event.keymodifier = 0; + event_state->keymodifier = event.keymodifier = 0; } /* If test_break set, it catches this. Do not set with modifier presses. @@ -4770,7 +4773,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void if (event.val == KM_PRESS) { /* Don't reset timer & location when holding the key generates repeat events. */ if (event.is_repeat == false) { - wm_event_prev_click_set(&event, evt); + wm_event_prev_click_set(&event, event_state); } } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index d2d080a9a68..d7b33d20c0f 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -1776,7 +1776,12 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op) filepath, fileflags, &(const struct BlendFileWriteParams){ - .remap_mode = BLO_WRITE_PATH_REMAP_RELATIVE, + /* Make all paths absolute when saving the startup file. + * On load the `G.relbase_valid` will be false so the paths + * wont 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. */ + .use_save_as_copy = true, }, op->reports) == 0) { printf("fail\n"); diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index d4495821672..6a1fc84774c 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -804,7 +804,7 @@ static void lib_relocate_do(Main *bmain, ReportList *reports, const bool do_reload) { - ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray[INDEX_ID_MAX]; int lba_idx; LinkNode *itemlink; diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index aeab1ee6fca..ba236988c1d 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -291,7 +291,7 @@ void WM_operator_properties_select_random(wmOperatorType *ot) 1.0f, "Ratio", "Portion of items to select randomly", - 0.f, + 0.0f, 1.0f); RNA_def_int(ot->srna, "seed", diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index ada4093080c..f09a9aecb1d 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1691,7 +1691,7 @@ void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer * /* there might be events in queue with this timer as customdata */ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { - LISTBASE_FOREACH (wmEvent *, event, &win->queue) { + LISTBASE_FOREACH (wmEvent *, event, &win->event_queue) { if (event->customdata == wt) { event->customdata = NULL; event->type = EVENT_NONE; /* timer users customdata, dont want NULL == NULL */ diff --git a/source/creator/creator.c b/source/creator/creator.c index fbc97028d35..b40718d1f7c 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -47,7 +47,7 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" -/* Mostly init functions. */ +/* Mostly initialization functions. */ #include "BKE_appdir.h" #include "BKE_blender.h" #include "BKE_brush.h" @@ -109,8 +109,6 @@ #include "creator_intern.h" /* Own include. */ -/* Local Function prototypes. */ - /* -------------------------------------------------------------------- */ /** \name Local Application State * \{ */ @@ -264,7 +262,7 @@ int main(int argc, # endif /* Win32 Unicode Arguments. */ - /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized + /* NOTE: cannot use `guardedalloc` allocation here, as it's not yet initialized * (it depends on the arguments passed in, which is what we're getting here!) */ { @@ -453,8 +451,8 @@ int main(int argc, /* Background render uses this font too. */ BKE_vfont_builtin_register(datatoc_bfont_pfb, datatoc_bfont_pfb_size); - /* Initialize ffmpeg if built in, also needed for background-mode if videos are - * rendered via ffmpeg. */ + /* Initialize FFMPEG if built in, also needed for background-mode if videos are + * rendered via FFMPEG. */ BKE_sound_init_once(); BKE_materials_init(); @@ -524,7 +522,7 @@ int main(int argc, #endif /* WITH_PYTHON_MODULE */ return 0; -} /* End of int main(...) function. */ +} /* End of `int main(...)` function. */ #ifdef WITH_PYTHON_MODULE void main_python_exit(void) diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index 9133b259a13..e35fce3160f 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -610,6 +610,7 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo printf("\n"); printf("Misc Options:\n"); + BLI_args_print_arg_doc(ba, "--open-last"); BLI_args_print_arg_doc(ba, "--app-template"); BLI_args_print_arg_doc(ba, "--factory-startup"); BLI_args_print_arg_doc(ba, "--enable-event-simulate"); @@ -2008,7 +2009,7 @@ static int arg_handle_load_last_file(int UNUSED(argc), const char **UNUSED(argv) const RecentFile *recent_file = G.recent_files.first; const char *fake_argv[] = {recent_file->filepath}; - return arg_handle_load_file(1, fake_argv, data); + return arg_handle_load_file(ARRAY_SIZE(fake_argv), fake_argv, data); } void main_args_setup(bContext *C, bArgs *ba) diff --git a/tests/gtests/runner/CMakeLists.txt b/tests/gtests/runner/CMakeLists.txt index 1fe8cf21810..b18eff59016 100644 --- a/tests/gtests/runner/CMakeLists.txt +++ b/tests/gtests/runner/CMakeLists.txt @@ -82,6 +82,7 @@ elseif(APPLE) # are used as dependencies of other test libraries. foreach(_lib ${_test_libs}) list(REMOVE_ITEM _test_libs_dependencies ${_lib}) + add_dependencies(blender_test ${_lib}) target_link_options(blender_test PRIVATE "LINKER:-force_load,$<TARGET_FILE:${_lib}>") endforeach() diff --git a/tests/python/bl_blendfile_io.py b/tests/python/bl_blendfile_io.py index 2c27b60f34e..38b3a93bbbc 100644 --- a/tests/python/bl_blendfile_io.py +++ b/tests/python/bl_blendfile_io.py @@ -15,7 +15,8 @@ class TestBlendFileSaveLoadBasic(TestHelper): self.args = args def test_save_load(self): - bpy.ops.wm.read_factory_settings() + bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True) + bpy.data.meshes.new("OrphanedMesh") output_dir = self.args.output_dir @@ -71,6 +72,9 @@ def argparse_create(): def main(): args = argparse_create().parse_args() + # Don't write thumbnails into the home directory. + bpy.context.preferences.filepaths.use_save_preview_images = False + for Test in TESTS: Test(args).run_all_tests() diff --git a/tests/python/bl_blendfile_liblink.py b/tests/python/bl_blendfile_liblink.py index fc618314216..a5f2571c902 100644 --- a/tests/python/bl_blendfile_liblink.py +++ b/tests/python/bl_blendfile_liblink.py @@ -15,7 +15,9 @@ class TestBlendLibLinkSaveLoadBasic(TestHelper): self.args = args def test_link_save_load(self): - bpy.ops.wm.read_factory_settings() + + bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True) + me = bpy.data.meshes.new("LibMesh") me.use_fake_user = True @@ -26,7 +28,7 @@ class TestBlendLibLinkSaveLoadBasic(TestHelper): bpy.ops.wm.save_as_mainfile(filepath=output_path, check_existing=False, compress=False) - bpy.ops.wm.read_factory_settings() + bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True) bpy.data.orphans_purge() link_dir = os.path.join(output_path, "Mesh") @@ -68,6 +70,9 @@ def argparse_create(): def main(): args = argparse_create().parse_args() + # Don't write thumbnails into the home directory. + bpy.context.preferences.filepaths.use_save_preview_images = False + for Test in TESTS: Test(args).run_all_tests() |