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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2021-03-05 12:22:39 +0300
committerJacques Lucke <jacques@blender.org>2021-03-05 12:22:39 +0300
commit381e2d4dc2b2773e348bfb481ab22bb9d553986c (patch)
tree6f41b98209a8203391c40a19c3d7fb41b8ea3fa2
parentcf6208382eb6142085e7ce3052b177344ea156cc (diff)
parentb5d154f400e46ba322f0e08a231bb2557bf51a1e (diff)
Merge branch 'master' into temp-spreadsheet-editortemp-spreadsheet-editor
-rw-r--r--intern/clog/clog.c38
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm2
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm5
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h6
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm5
-rw-r--r--intern/ghost/intern/GHOST_WindowViewCocoa.h4
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp11
-rw-r--r--release/scripts/modules/bpy_types.py7
-rw-r--r--release/scripts/presets/framerate/120.py3
-rw-r--r--release/scripts/presets/framerate/240.py3
-rw-r--r--release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_output.py2
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_cryptomatte.h2
-rw-r--r--source/blender/blenkernel/BKE_main.h16
-rw-r--r--source/blender/blenkernel/BKE_volume_to_mesh.hh1
-rw-r--r--source/blender/blenkernel/intern/blendfile.c2
-rw-r--r--source/blender/blenkernel/intern/bpath.c2
-rw-r--r--source/blender/blenkernel/intern/idtype.c2
-rw-r--r--source/blender/blenkernel/intern/lib_id.c6
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c2
-rw-r--r--source/blender/blenkernel/intern/lib_query.c8
-rw-r--r--source/blender/blenkernel/intern/main.c23
-rw-r--r--source/blender/blenkernel/intern/main_idmap.c10
-rw-r--r--source/blender/blenkernel/intern/studiolight.c2
-rw-r--r--source/blender/blenlib/BLI_multi_value_map.hh16
-rw-r--r--source/blender/blenlib/intern/storage.c2
-rw-r--r--source/blender/blenlib/intern/string_search.cc17
-rw-r--r--source/blender/blenlib/tests/BLI_multi_value_map_test.cc21
-rw-r--r--source/blender/blenloader/intern/blend_validate.c2
-rw-r--r--source/blender/blenloader/intern/readfile.c22
-rw-r--r--source/blender/blenloader/intern/versioning_270.c2
-rw-r--r--source/blender/blenloader/intern/versioning_290.c25
-rw-r--r--source/blender/blenloader/intern/writefile.c4
-rw-r--r--source/blender/compositor/intern/COM_MetaData.h1
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h8
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c12
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl54
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl5
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl17
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl18
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl3
-rw-r--r--source/blender/draw/intern/draw_cache.c9
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c4
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c5
-rw-r--r--source/blender/editors/armature/pose_edit.c4
-rw-r--r--source/blender/editors/armature/pose_lib.c4
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_edit_curve.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c43
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c33
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c21
-rw-r--r--source/blender/editors/gpencil/gpencil_sculpt_paint.c13
-rw-r--r--source/blender/editors/include/ED_anim_api.h1
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/interface/interface_draw.c4
-rw-r--r--source/blender/editors/interface/interface_handlers.c18
-rw-r--r--source/blender/editors/interface/interface_intern.h4
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.c14
-rw-r--r--source/blender/editors/interface/interface_widgets.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c2
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c10
-rw-r--r--source/blender/editors/object/object_edit.c4
-rw-r--r--source/blender/editors/space_action/action_data.c4
-rw-r--r--source/blender/editors/space_nla/nla_channels.c4
-rw-r--r--source/blender/editors/space_node/node_draw.cc9
-rw-r--r--source/blender/editors/space_node/node_edit.c5
-rw-r--r--source/blender/editors/space_node/node_geometry_attribute_search.cc6
-rw-r--r--source/blender/editors/space_node/node_intern.h2
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c2
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_libraries.cc2
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_orphaned.cc2
-rw-r--r--source/blender/editors/transform/transform_constraints.c4
-rw-r--r--source/blender/editors/transform/transform_convert_gpencil.c11
-rw-r--r--source/blender/editors/util/ed_draw.c2
-rw-r--r--source/blender/gpu/intern/gpu_immediate.cc2
-rw-r--r--source/blender/imbuf/intern/IMB_colormanagement_intern.h1
-rw-r--r--source/blender/makesdna/DNA_ID.h34
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h25
-rw-r--r--source/blender/makesrna/intern/rna_scene.c2
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c7
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c7
-rw-r--r--source/blender/nodes/CMakeLists.txt2
-rw-r--r--source/blender/nodes/NOD_derived_node_tree.hh2
-rw-r--r--source/blender/nodes/NOD_node_tree_ref.hh81
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc (renamed from source/blender/nodes/composite/nodes/node_composite_cryptomatte.c)59
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_instance.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_subdivision_surface_simple.cc2
-rw-r--r--source/blender/nodes/intern/derived_node_tree.cc41
-rw-r--r--source/blender/nodes/intern/node_geometry_exec.cc2
-rw-r--r--source/blender/nodes/intern/node_tree_ref.cc24
-rw-r--r--source/blender/python/gpu/gpu_py_batch.c2
-rw-r--r--source/blender/python/gpu/gpu_py_buffer.c3
-rw-r--r--source/blender/python/gpu/gpu_py_offscreen.c4
-rw-r--r--source/blender/python/intern/bpy_app.c2
-rw-r--r--source/blender/python/intern/bpy_app_alembic.c4
-rw-r--r--source/blender/python/intern/bpy_app_ffmpeg.c4
-rw-r--r--source/blender/python/intern/bpy_app_ocio.c4
-rw-r--r--source/blender/python/intern/bpy_app_oiio.c4
-rw-r--r--source/blender/python/intern/bpy_app_opensubdiv.c4
-rw-r--r--source/blender/python/intern/bpy_app_openvdb.c4
-rw-r--r--source/blender/python/intern/bpy_app_sdl.c4
-rw-r--r--source/blender/python/intern/bpy_app_usd.c4
-rw-r--r--source/blender/python/intern/bpy_library_load.c19
-rw-r--r--source/blender/python/intern/bpy_library_write.c6
-rw-r--r--source/blender/python/intern/bpy_props.c6
-rw-r--r--source/blender/python/intern/bpy_rna.c47
-rw-r--r--source/blender/sequencer/SEQ_add.h1
-rw-r--r--source/blender/windowmanager/WM_types.h4
-rw-r--r--source/blender/windowmanager/intern/wm.c8
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c195
-rw-r--r--source/blender/windowmanager/intern/wm_files.c7
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operator_props.c2
-rw-r--r--source/blender/windowmanager/intern/wm_window.c2
-rw-r--r--source/creator/creator.c12
-rw-r--r--source/creator/creator_args.c3
-rw-r--r--tests/gtests/runner/CMakeLists.txt1
-rw-r--r--tests/python/bl_blendfile_io.py6
-rw-r--r--tests/python/bl_blendfile_liblink.py9
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()