diff options
58 files changed, 1003 insertions, 344 deletions
diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 00000000000..9c563f2dee0 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,22 @@ +# Configuration for probot-stale - https://github.com/probot/stale +# This file is used on Blender's GitHub mirror to automatically close any pull request +# and invite contributors to join the official development platform on blender.org + +# Number of days of inactivity before an Issue or Pull Request becomes stale +daysUntilStale: 1 + +# Number of days of inactivity before an Issue or Pull Request with the stale label is closed. +# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. +daysUntilClose: 1 + +# Label to use when marking as stale +staleLabel: stale + +# Comment to post when closing a stale Issue or Pull Request. +closeComment: > + This issue has been automatically closed, because this repository is only + used as a mirror of git.blender.org. Blender development happens on + developer.blender.org. + + To get started contributing code, please read: + https://wiki.blender.org/wiki/Process/Contributing_Code diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 366d0b1b507..4380b94890a 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = Blender # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "V2.81" +PROJECT_NUMBER = "V2.82" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 00dd37f089c..b5e10b0c2cb 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -454,6 +454,12 @@ class CUDADevice : public Device { VLOG(1) << "Using precompiled kernel."; return cubin; } + const string ptx = path_get(string_printf("lib/%s_compute_%d%d.ptx", name, major, minor)); + VLOG(1) << "Testing for pre-compiled kernel " << ptx << "."; + if (path_exists(ptx)) { + VLOG(1) << "Using precompiled kernel."; + return ptx; + } } const string common_cflags = compile_kernel_get_common_cflags( diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index ea8aa197b6f..78da584e132 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -389,11 +389,20 @@ if(WITH_CYCLES_CUDA_BINARIES) set(cuda_cubins) macro(CYCLES_CUDA_KERNEL_ADD arch prev_arch name flags sources experimental) - set(cuda_cubin ${name}_${arch}.cubin) + if(${arch} MATCHES "compute_.*") + set(format "ptx") + else() + set(format "cubin") + endif() + set(cuda_file ${name}_${arch}.${format}) set(kernel_sources ${sources}) if(NOT ${prev_arch} STREQUAL "none") - set(kernel_sources ${kernel_sources} ${name}_${prev_arch}.cubin) + if(${prev_arch} MATCHES "compute_.*") + set(kernel_sources ${kernel_sources} ${name}_${prev_arch}.ptx) + else() + set(kernel_sources ${kernel_sources} ${name}_${prev_arch}.cubin) + endif() endif() set(cuda_kernel_src "/kernels/cuda/${name}.cu") @@ -406,7 +415,7 @@ if(WITH_CYCLES_CUDA_BINARIES) -I ${CMAKE_CURRENT_SOURCE_DIR}/.. -I ${CMAKE_CURRENT_SOURCE_DIR}/kernels/cuda --use_fast_math - -o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_cubin}) + -o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_file}) if(${experimental}) set(cuda_flags ${cuda_flags} -D __KERNEL_EXPERIMENTAL__) @@ -440,20 +449,21 @@ if(WITH_CYCLES_CUDA_BINARIES) -v -cuda-toolkit-dir "${CUDA_TOOLKIT_ROOT_DIR}" DEPENDS ${kernel_sources} cycles_cubin_cc) + set(cuda_file ${cuda_cubin}) else() add_custom_command( - OUTPUT ${cuda_cubin} + OUTPUT ${cuda_file} COMMAND ${CUDA_NVCC_EXECUTABLE} -arch=${arch} ${CUDA_NVCC_FLAGS} - --cubin + --${format} ${CMAKE_CURRENT_SOURCE_DIR}${cuda_kernel_src} --ptxas-options="-v" ${cuda_flags} DEPENDS ${kernel_sources}) endif() - delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${cuda_cubin}" ${CYCLES_INSTALL_PATH}/lib) - list(APPEND cuda_cubins ${cuda_cubin}) + delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${cuda_file}" ${CYCLES_INSTALL_PATH}/lib) + list(APPEND cuda_cubins ${cuda_file}) unset(cuda_debug_flags) endmacro() diff --git a/intern/cycles/kernel/filter/filter_transform_gpu.h b/intern/cycles/kernel/filter/filter_transform_gpu.h index 41bbadb621d..adc85881fe5 100644 --- a/intern/cycles/kernel/filter/filter_transform_gpu.h +++ b/intern/cycles/kernel/filter/filter_transform_gpu.h @@ -76,9 +76,9 @@ ccl_device void kernel_filter_construct_transform(const ccl_global float *ccl_re filter_calculate_scale(feature_scale, use_time); /* === Generate the feature transformation. === - * This transformation maps the num_features-dimentional feature space to a reduced feature - * (r-feature) space which generally has fewer dimensions. This mainly helps to prevent - * overfitting. */ + * This transformation maps the num_features-dimensional feature space to a reduced feature + * (r-feature) space which generally has fewer dimensions. + * This mainly helps to prevent overfitting. */ float feature_matrix[DENOISE_FEATURES * DENOISE_FEATURES]; math_matrix_zero(feature_matrix, num_features); FOR_PIXEL_WINDOW diff --git a/intern/cycles/kernel/filter/filter_transform_sse.h b/intern/cycles/kernel/filter/filter_transform_sse.h index 830444645d7..5a124b5d73b 100644 --- a/intern/cycles/kernel/filter/filter_transform_sse.h +++ b/intern/cycles/kernel/filter/filter_transform_sse.h @@ -73,9 +73,9 @@ ccl_device void kernel_filter_construct_transform(const float *ccl_restrict buff filter_calculate_scale_sse(feature_scale, use_time); /* === Generate the feature transformation. === - * This transformation maps the num_features-dimentional feature space to a reduced feature - * (r-feature) space which generally has fewer dimensions. This mainly helps to prevent - * overfitting. */ + * This transformation maps the num_features-dimensional feature space to a reduced feature + * (r-feature) space which generally has fewer dimensions. + * This mainly helps to prevent over-fitting. */ float4 feature_matrix_sse[DENOISE_FEATURES * DENOISE_FEATURES]; math_matrix_zero_sse(feature_matrix_sse, num_features); FOR_PIXEL_WINDOW_SSE diff --git a/intern/cycles/util/util_defines.h b/intern/cycles/util/util_defines.h index 2778cffba3a..b29d4163133 100644 --- a/intern/cycles/util/util_defines.h +++ b/intern/cycles/util/util_defines.h @@ -16,127 +16,127 @@ */ #ifndef __UTIL_DEFINES_H__ -# define __UTIL_DEFINES_H__ +#define __UTIL_DEFINES_H__ /* Bitness */ -# if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || \ - defined(_M_X64) -# define __KERNEL_64_BIT__ -# endif +#if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || \ + defined(_M_X64) +# define __KERNEL_64_BIT__ +#endif /* Qualifiers for kernel code shared by CPU and GPU */ -# ifndef __KERNEL_GPU__ -# define ccl_device static inline -# define ccl_device_noinline static -# define ccl_device_noinline_cpu ccl_device_noinline -# define ccl_global -# define ccl_static_constant static const -# define ccl_constant const -# define ccl_local -# define ccl_local_param -# define ccl_private -# define ccl_restrict __restrict -# define ccl_ref & -# define ccl_optional_struct_init -# define __KERNEL_WITH_SSE_ALIGN__ - -# if defined(_WIN32) && !defined(FREE_WINDOWS) -# define ccl_device_inline static __forceinline -# define ccl_device_forceinline static __forceinline -# define ccl_align(...) __declspec(align(__VA_ARGS__)) -# ifdef __KERNEL_64_BIT__ -# define ccl_try_align(...) __declspec(align(__VA_ARGS__)) -# else /* __KERNEL_64_BIT__ */ -# undef __KERNEL_WITH_SSE_ALIGN__ +#ifndef __KERNEL_GPU__ +# define ccl_device static inline +# define ccl_device_noinline static +# define ccl_device_noinline_cpu ccl_device_noinline +# define ccl_global +# define ccl_static_constant static const +# define ccl_constant const +# define ccl_local +# define ccl_local_param +# define ccl_private +# define ccl_restrict __restrict +# define ccl_ref & +# define ccl_optional_struct_init +# define __KERNEL_WITH_SSE_ALIGN__ + +# if defined(_WIN32) && !defined(FREE_WINDOWS) +# define ccl_device_inline static __forceinline +# define ccl_device_forceinline static __forceinline +# define ccl_align(...) __declspec(align(__VA_ARGS__)) +# ifdef __KERNEL_64_BIT__ +# define ccl_try_align(...) __declspec(align(__VA_ARGS__)) +# else /* __KERNEL_64_BIT__ */ +# undef __KERNEL_WITH_SSE_ALIGN__ /* No support for function arguments (error C2719). */ -# define ccl_try_align(...) -# endif /* __KERNEL_64_BIT__ */ -# define ccl_may_alias -# define ccl_always_inline __forceinline -# define ccl_never_inline __declspec(noinline) -# define ccl_maybe_unused -# else /* _WIN32 && !FREE_WINDOWS */ -# define ccl_device_inline static inline __attribute__((always_inline)) -# define ccl_device_forceinline static inline __attribute__((always_inline)) -# define ccl_align(...) __attribute__((aligned(__VA_ARGS__))) -# ifndef FREE_WINDOWS64 -# define __forceinline inline __attribute__((always_inline)) -# endif -# define ccl_try_align(...) __attribute__((aligned(__VA_ARGS__))) -# define ccl_may_alias __attribute__((__may_alias__)) -# define ccl_always_inline __attribute__((always_inline)) -# define ccl_never_inline __attribute__((noinline)) -# define ccl_maybe_unused __attribute__((used)) -# endif /* _WIN32 && !FREE_WINDOWS */ +# define ccl_try_align(...) +# endif /* __KERNEL_64_BIT__ */ +# define ccl_may_alias +# define ccl_always_inline __forceinline +# define ccl_never_inline __declspec(noinline) +# define ccl_maybe_unused +# else /* _WIN32 && !FREE_WINDOWS */ +# define ccl_device_inline static inline __attribute__((always_inline)) +# define ccl_device_forceinline static inline __attribute__((always_inline)) +# define ccl_align(...) __attribute__((aligned(__VA_ARGS__))) +# ifndef FREE_WINDOWS64 +# define __forceinline inline __attribute__((always_inline)) +# endif +# define ccl_try_align(...) __attribute__((aligned(__VA_ARGS__))) +# define ccl_may_alias __attribute__((__may_alias__)) +# define ccl_always_inline __attribute__((always_inline)) +# define ccl_never_inline __attribute__((noinline)) +# define ccl_maybe_unused __attribute__((used)) +# endif /* _WIN32 && !FREE_WINDOWS */ /* Use to suppress '-Wimplicit-fallthrough' (in place of 'break'). */ -# ifndef ATTR_FALLTHROUGH -# if defined(__GNUC__) && (__GNUC__ >= 7) /* gcc7.0+ only */ -# define ATTR_FALLTHROUGH __attribute__((fallthrough)) -# else -# define ATTR_FALLTHROUGH ((void)0) -# endif +# ifndef ATTR_FALLTHROUGH +# if defined(__GNUC__) && (__GNUC__ >= 7) /* gcc7.0+ only */ +# define ATTR_FALLTHROUGH __attribute__((fallthrough)) +# else +# define ATTR_FALLTHROUGH ((void)0) # endif -# endif /* __KERNEL_GPU__ */ +# endif +#endif /* __KERNEL_GPU__ */ /* macros */ /* hints for branch prediction, only use in code that runs a _lot_ */ -# if defined(__GNUC__) && defined(__KERNEL_CPU__) -# define LIKELY(x) __builtin_expect(!!(x), 1) -# define UNLIKELY(x) __builtin_expect(!!(x), 0) -# else -# define LIKELY(x) (x) -# define UNLIKELY(x) (x) -# endif - -# if defined(__GNUC__) || defined(__clang__) -# if defined(__cplusplus) +#if defined(__GNUC__) && defined(__KERNEL_CPU__) +# define LIKELY(x) __builtin_expect(!!(x), 1) +# define UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +# define LIKELY(x) (x) +# define UNLIKELY(x) (x) +#endif + +#if defined(__GNUC__) || defined(__clang__) +# if defined(__cplusplus) /* Some magic to be sure we don't have reference in the type. */ template<typename T> static inline T decltype_helper(T x) { return x; } -# define TYPEOF(x) decltype(decltype_helper(x)) -# else -# define TYPEOF(x) typeof(x) -# endif +# define TYPEOF(x) decltype(decltype_helper(x)) +# else +# define TYPEOF(x) typeof(x) # endif +#endif /* Causes warning: * incompatible types when assigning to type 'Foo' from type 'Bar' * ... the compiler optimizes away the temp var */ -# ifdef __GNUC__ -# define CHECK_TYPE(var, type) \ - { \ - TYPEOF(var) * __tmp; \ - __tmp = (type *)NULL; \ - (void)__tmp; \ - } \ - (void)0 - -# define CHECK_TYPE_PAIR(var_a, var_b) \ - { \ - TYPEOF(var_a) * __tmp; \ - __tmp = (typeof(var_b) *)NULL; \ - (void)__tmp; \ - } \ - (void)0 -# else -# define CHECK_TYPE(var, type) -# define CHECK_TYPE_PAIR(var_a, var_b) -# endif +#ifdef __GNUC__ +# define CHECK_TYPE(var, type) \ + { \ + TYPEOF(var) * __tmp; \ + __tmp = (type *)NULL; \ + (void)__tmp; \ + } \ + (void)0 + +# define CHECK_TYPE_PAIR(var_a, var_b) \ + { \ + TYPEOF(var_a) * __tmp; \ + __tmp = (typeof(var_b) *)NULL; \ + (void)__tmp; \ + } \ + (void)0 +#else +# define CHECK_TYPE(var, type) +# define CHECK_TYPE_PAIR(var_a, var_b) +#endif /* can be used in simple macros */ -# define CHECK_TYPE_INLINE(val, type) ((void)(((type)0) != (val))) - -# ifndef __KERNEL_GPU__ -# include <cassert> -# define util_assert(statement) assert(statement) -# else -# define util_assert(statement) -# endif +#define CHECK_TYPE_INLINE(val, type) ((void)(((type)0) != (val))) + +#ifndef __KERNEL_GPU__ +# include <cassert> +# define util_assert(statement) assert(statement) +#else +# define util_assert(statement) +#endif #endif /* __UTIL_DEFINES_H__ */ diff --git a/intern/cycles/util/util_static_assert.h b/intern/cycles/util/util_static_assert.h index b4b972a4036..ceb52830319 100644 --- a/intern/cycles/util/util_static_assert.h +++ b/intern/cycles/util/util_static_assert.h @@ -15,18 +15,18 @@ */ #ifndef __UTIL_STATIC_ASSERT_H__ -# define __UTIL_STATIC_ASSERT_H__ +#define __UTIL_STATIC_ASSERT_H__ CCL_NAMESPACE_BEGIN /* TODO(sergey): In theory CUDA might work with own static assert * implementation since it's just pure C++. */ -# ifdef __KERNEL_GPU__ -# ifndef static_assert -# define static_assert(statement, message) -# endif -# endif /* __KERNEL_GPU__ */ +#ifdef __KERNEL_GPU__ +# ifndef static_assert +# define static_assert(statement, message) +# endif +#endif /* __KERNEL_GPU__ */ /* TODO(sergey): For until C++11 is a bare minimum for us, * we do a bit of a trickery to show meaningful message so @@ -42,8 +42,8 @@ CCL_NAMESPACE_BEGIN * After C++11 bump it should be possible to glue structure * name to the error message, */ -# define static_assert_align(st, align) \ - static_assert((sizeof(st) % (align) == 0), "Structure must be strictly aligned") // NOLINT +#define static_assert_align(st, align) \ + static_assert((sizeof(st) % (align) == 0), "Structure must be strictly aligned") // NOLINT CCL_NAMESPACE_END diff --git a/release/datafiles/locale b/release/datafiles/locale -Subproject 88497d7507e76281fbdd0cc1f8451f81ae7e378 +Subproject 6a6b84fd50538a65276c729b5d396be615bc79f diff --git a/release/datafiles/userdef/userdef_default.c b/release/datafiles/userdef/userdef_default.c index dc35187ab7e..d8b87480f29 100644 --- a/release/datafiles/userdef/userdef_default.c +++ b/release/datafiles/userdef/userdef_default.c @@ -213,6 +213,7 @@ const UserDef U_default = { .sort_type = FILE_SORT_ALPHA, .details_flags = FILE_DETAILS_SIZE | FILE_DETAILS_DATETIME, .flag = FILE_HIDE_DOT, + .filter_id = FILTER_ID_ALL, .temp_win_sizex = 1020, .temp_win_sizey = 600, diff --git a/release/scripts/addons b/release/scripts/addons -Subproject 120d31a17c0eb571420b828425fc1fe6ef13db2 +Subproject 46b1ada7f5f2d396f712e9a1376922ca8947548 diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib -Subproject 69bcc72f1ec4df73265ce35851658ef184b9d0f +Subproject b5e801446c820e7f5725e2e09f8c2a12a4449f4 diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 0728cbf8f9f..25359510de2 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -1793,6 +1793,7 @@ def km_file_browser(params): {"properties": [("data_path", 'space_data.params.show_hidden')]}), ("file.directory_new", {"type": 'I', "value": 'PRESS'}, {"properties": [("confirm", False)]}), + ("file.rename", {"type": 'F2', "value": 'PRESS'}, None), ("file.delete", {"type": 'X', "value": 'PRESS'}, None), ("file.delete", {"type": 'DEL', "value": 'PRESS'}, None), ("file.smoothscroll", {"type": 'TIMER1', "value": 'ANY', "any": True}, None), @@ -5792,6 +5793,19 @@ def km_3d_view_tool_paint_gpencil_line(params): ]}, ) +def km_3d_view_tool_paint_gpencil_polyline(params): + return ( + "3D View Tool: Paint Gpencil, Polyline", + {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, + {"items": [ + ("gpencil.primitive", {"type": params.tool_tweak, "value": 'ANY'}, + {"properties": [("type", 'POLYLINE'), ("wait_for_input", False)]}), + ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, + {"properties": [("type", 'POLYLINE'), ("wait_for_input", False)]}), + # Lasso select + ("gpencil.select_lasso", {"type": params.action_tweak, "value": 'ANY', "ctrl": True, "alt": True}, None), + ]}, + ) def km_3d_view_tool_paint_gpencil_box(params): return ( @@ -5869,6 +5883,18 @@ def km_3d_view_tool_paint_gpencil_cutter(params): ) +def km_3d_view_tool_paint_gpencil_eyedropper(params): + return ( + "3D View Tool: Paint Gpencil, Eyedropper", + {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, + {"items": [ + ("ui.eyedropper_gpencil_color", {"type": params.tool_mouse, "value": 'PRESS'}, None), + ("ui.eyedropper_gpencil_color", {"type": params.tool_mouse, "value": 'PRESS', "shift": True}, None), + ("ui.eyedropper_gpencil_color", {"type": params.tool_mouse, "value": 'PRESS', "shift": True, "ctrl": True}, None), + ]}, + ) + + def km_3d_view_tool_edit_gpencil_select(params): return ( "3D View Tool: Edit Gpencil, Tweak", @@ -6201,11 +6227,13 @@ def generate_keymaps(params=None): km_3d_view_tool_paint_weight_sample_vertex_group(params), km_3d_view_tool_paint_weight_gradient(params), km_3d_view_tool_paint_gpencil_line(params), + km_3d_view_tool_paint_gpencil_polyline(params), km_3d_view_tool_paint_gpencil_box(params), km_3d_view_tool_paint_gpencil_circle(params), km_3d_view_tool_paint_gpencil_arc(params), km_3d_view_tool_paint_gpencil_curve(params), km_3d_view_tool_paint_gpencil_cutter(params), + km_3d_view_tool_paint_gpencil_eyedropper(params), km_3d_view_tool_edit_gpencil_select(params), km_3d_view_tool_edit_gpencil_select_box(params), km_3d_view_tool_edit_gpencil_select_circle(params), diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index c5c1bfa7f7b..49a394b478d 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -1183,6 +1183,7 @@ def km_file_browser(params): {"properties": [("data_path", 'space_data.params.show_hidden')]}), ("file.directory_new", {"type": 'I', "value": 'PRESS'}, {"properties": [("confirm", False)]}), + ("file.rename", {"type": 'F2', "value": 'PRESS'}, None), ("file.delete", {"type": 'DEL', "value": 'PRESS'}, None), ("file.smoothscroll", {"type": 'TIMER1', "value": 'ANY', "any": True}, None), ("wm.context_toggle", {"type": 'T', "value": 'PRESS'}, diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py index 2b20754a995..2befb7c73e2 100644 --- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py +++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py @@ -565,7 +565,12 @@ def unwrap(operator, context, **kwargs): bpy.ops.object.mode_set(mode='OBJECT', toggle=False) # define list of meshes - meshes = list({me for obj in context.selected_objects if obj.type == 'MESH' for me in (obj.data,) if me.polygons and me.library is None}) + meshes = list({ + me for obj in context.selected_objects + if obj.type == 'MESH' + for me in (obj.data,) + if me.polygons and me.library is None + }) if not meshes: operator.report({'ERROR'}, "No mesh object") diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 726afda571d..0dad29ce683 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -1995,7 +1995,6 @@ class WM_OT_batch_rename(Operator): descr, ) - return data @staticmethod diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index b7c566f23da..d1975919d7e 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -348,7 +348,6 @@ class DATA_PT_font(CurveButtonsPanelText, Panel): row.label(text="Bold & Italic") row.template_ID(text, "font_bold_italic", open="font.open", unlink="font.unlink") - if mode == 'EDIT_TEXT': layout.separator() diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index 51f24007271..72e9f710e9d 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -485,6 +485,7 @@ class DATA_PT_remesh(MeshButtonsPanel, Panel): else: col.operator("object.quadriflow_remesh", text="QuadriFlow Remesh") + class DATA_PT_customdata(MeshButtonsPanel, Panel): bl_label = "Geometry Data" bl_options = {'DEFAULT_CLOSED'} diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index ca9c518f443..e545ee971d8 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -950,6 +950,7 @@ class GPENCIL_UL_layer(UIList): icon_value=icon, ) + class GreasePencilSimplifyPanel: def draw_header(self, context): @@ -977,6 +978,7 @@ class GreasePencilSimplifyPanel: sub.active = rd.simplify_gpencil_view_fill sub.prop(rd, "simplify_gpencil_remove_lines", text="Lines") + classes = ( GPENCIL_MT_pie_tool_palette, GPENCIL_MT_pie_settings_palette, diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 23b2556eddb..dc0ad1dcac3 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -367,7 +367,7 @@ def brush_basic_sculpt_settings(layout, context, brush, *, compact=False): layout.row().prop(brush, "direction", expand=True, **({"text": ""} if compact else {})) -def brush_basic_gpencil_paint_settings(layout, _context, brush, *, compact=True): +def brush_basic_gpencil_paint_settings(layout, _context, brush, tool, *, compact=True, is_toolbar=False): gp_settings = brush.gpencil_settings # Brush details @@ -395,6 +395,23 @@ def brush_basic_gpencil_paint_settings(layout, _context, brush, *, compact=True) row = layout.row(align=True) row.prop(gp_settings, "fill_draw_mode", text="Boundary") row.prop(gp_settings, "show_fill_boundary", text="", icon='GRID') + # Fill options + if is_toolbar: + settings = _context.tool_settings.gpencil_sculpt + row = layout.row(align=True) + sub = row.row(align=True) + sub.popover( + panel="TOPBAR_PT_gpencil_fill", + text="Fill Options", + ) + else: + row = layout.row(align=True) + row.prop(gp_settings, "fill_factor", text="Resolution") + if gp_settings.fill_draw_mode != 'STROKE': + row = layout.row(align=True) + row.prop(gp_settings, "show_fill", text="Ignore Transparent Strokes") + row = layout.row(align=True) + row.prop(gp_settings, "fill_threshold", text="Threshold") else: # brush.gpencil_tool == 'DRAW': row = layout.row(align=True) row.prop(brush, "size", text="Radius") @@ -403,6 +420,25 @@ def brush_basic_gpencil_paint_settings(layout, _context, brush, *, compact=True) row.prop(gp_settings, "pen_strength", slider=True) row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE') + if tool.idname in {"builtin.arc", "builtin.curve", "builtin.line", "builtin.box", "builtin.circle", "builtin.polyline"}: + settings = _context.tool_settings.gpencil_sculpt + if is_toolbar: + row = layout.row(align=True) + row.prop(settings, "use_thickness_curve", text="", icon='CURVE_DATA') + sub = row.row(align=True) + sub.active = settings.use_thickness_curve + sub.popover( + panel="TOPBAR_PT_gpencil_primitive", + text="Thickness Profile", + ) + else: + row = layout.row(align=True) + row.prop(settings, "use_thickness_curve", text="Use Thickness Profile") + sub = row.row(align=True) + if settings.use_thickness_curve: + # Curve + layout.template_curve_mapping(settings, "thickness_primitive_curve", brush=True) + def brush_basic_gpencil_sculpt_settings(layout, context, brush, *, compact=False): tool_settings = context.tool_settings diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index e1097e8d512..181032e4d96 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -158,7 +158,8 @@ class FILEBROWSER_PT_filter(Panel): def panel_poll_is_upper_region(region): - # The upper region is left-aligned, the lower is split into it then. Note that after "Flip Regions" it's right-aligned. + # The upper region is left-aligned, the lower is split into it then. + # Note that after "Flip Regions" it's right-aligned. return region.alignment in {'LEFT', 'RIGHT'} diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 35197b2c7dd..2ce81ba8359 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -418,6 +418,9 @@ class NODE_MT_context_menu(Menu): # If something is selected layout.operator_context = 'INVOKE_DEFAULT' layout.operator("node.duplicate_move") + props = layout.operator("wm.call_panel", text="Rename...") + props.name = "TOPBAR_PT_name" + props.keep_open = False layout.operator("node.delete") layout.operator("node.clipboard_copy", text="Copy") layout.operator("node.clipboard_paste", text="Paste") diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index a942b8769cf..cdac91b8014 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -741,6 +741,9 @@ class SEQUENCER_MT_context_menu(Menu): layout.operator("sequencer.copy", text="Copy", icon='COPYDOWN') layout.operator("sequencer.paste", text="Paste", icon='PASTEDOWN') layout.operator("sequencer.duplicate_move") + props = layout.operator("wm.call_panel", text="Rename...") + props.name = "TOPBAR_PT_name" + props.keep_open = False layout.operator("sequencer.delete", text="Delete...") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index 4bce8a95528..ff5d2565c26 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -1349,6 +1349,17 @@ class _defs_gpencil_paint: ) @ToolDef.from_fn + def polyline(): + return dict( + idname="builtin.polyline", + label="Polyline", + icon="ops.gpencil.primitive_polyline", + cursor='CROSSHAIR', + widget=None, + keymap=(), + ) + + @ToolDef.from_fn def box(): return dict( idname="builtin.box", @@ -1390,6 +1401,17 @@ class _defs_gpencil_paint: cursor='CROSSHAIR', widget=None, keymap=(), + ) + + @ToolDef.from_fn + def eyedropper(): + return dict( + idname="builtin.eyedropper", + label="Eyedropper", + icon="ops.paint.weight_sample", + cursor='EYEDROPPER', + widget=None, + keymap=(), ) @@ -2044,7 +2066,10 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_gpencil_paint.generate_from_brushes, _defs_gpencil_paint.cutter, None, + _defs_gpencil_paint.eyedropper, + None, _defs_gpencil_paint.line, + _defs_gpencil_paint.polyline, _defs_gpencil_paint.arc, _defs_gpencil_paint.curve, _defs_gpencil_paint.box, diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 137691c10ba..06d85be94e4 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -298,7 +298,7 @@ class _draw_tool_settings_context_mode: # is_paint = True # FIXME: tools must use their own UI drawing! - if tool.idname in {"builtin.line", "builtin.box", "builtin.circle", "builtin.arc", "builtin.curve"}: + if tool.idname in {"builtin.line", "builtin.box", "builtin.circle", "builtin.arc", "builtin.curve","builtin.polyline"}: # is_paint = False pass elif tool.idname == "Cutter": @@ -351,28 +351,7 @@ class _draw_tool_settings_context_mode: from bl_ui.properties_paint_common import ( brush_basic_gpencil_paint_settings, ) - brush_basic_gpencil_paint_settings(layout, context, brush, compact=True) - - # FIXME: tools must use their own UI drawing! - if tool.idname in {"builtin.arc", "builtin.curve", "builtin.line", "builtin.box", "builtin.circle"}: - settings = context.tool_settings.gpencil_sculpt - row = layout.row(align=True) - row.prop(settings, "use_thickness_curve", text="", icon='CURVE_DATA') - sub = row.row(align=True) - sub.active = settings.use_thickness_curve - sub.popover( - panel="TOPBAR_PT_gpencil_primitive", - text="Thickness Profile", - ) - - if brush.gpencil_tool == 'FILL': - settings = context.tool_settings.gpencil_sculpt - row = layout.row(align=True) - sub = row.row(align=True) - sub.popover( - panel="TOPBAR_PT_gpencil_fill", - text="Fill Options", - ) + brush_basic_gpencil_paint_settings(layout, context, brush, tool, compact=True, is_toolbar=True) @staticmethod def SCULPT_GPENCIL(context, layout, tool): @@ -5087,7 +5066,7 @@ class VIEW3D_PT_collections(Panel): subrow.active = collection.is_visible # Parent collection runtime visibility subrow.prop(child, "hide_viewport", text="", emboss=False) else: - subrow.active = collection.visible_get() # Parent collection runtime visibility + subrow.active = collection.visible_get() # Parent collection runtime visibility icon = 'HIDE_OFF' if child.visible_get() else 'HIDE_ON' props = subrow.operator("object.hide_collection", text="", icon=icon, emboss=False) props.collection_index = index diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 3aee14e0239..8da5ba67187 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1873,7 +1873,8 @@ class VIEW3D_PT_tools_grease_pencil_brush(View3DPanel, Panel): from bl_ui.properties_paint_common import ( brush_basic_gpencil_paint_settings, ) - brush_basic_gpencil_paint_settings(layout, context, brush, compact=True) + tool = context.workspace.tools.from_space_view3d_mode(context.mode, create=False) + brush_basic_gpencil_paint_settings(layout, context, brush, tool, compact=True, is_toolbar=False) # Grease Pencil drawing brushes options diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 0294a6219b9..45086de0f61 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -80,9 +80,8 @@ typedef struct GlyphCacheBLF { /* and the last texture, aka. the current texture. */ unsigned int texture_current; - /* like bftgl, we draw every glyph in a big texture, so this is the - * current position inside the texture. - */ + /* We draw every glyph in a big texture, so this is the + * current position inside the texture. */ int offset_x; int offset_y; diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index a1900c1af94..dfa1b311eb0 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -26,8 +26,8 @@ * * \note Use #STRINGIFY() rather than defining with quotes. */ -#define BLENDER_VERSION 281 -#define BLENDER_SUBVERSION 15 +#define BLENDER_VERSION 282 +#define BLENDER_SUBVERSION 1 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 @@ -36,7 +36,7 @@ /** Can be left blank, otherwise a,b,c... etc with no quotes. */ #define BLENDER_VERSION_CHAR /** alpha/beta/rc/release, docs use this. */ -#define BLENDER_VERSION_CYCLE beta +#define BLENDER_VERSION_CYCLE alpha /** Optionally set to 1,2,... for example to to get alpha1 or rc2. */ #define BLENDER_VERSION_CYCLE_NUMBER diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.c b/source/blender/blenkernel/intern/mesh_remesh_voxel.c index b93fe157f2a..ba8ed5facad 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.c +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.c @@ -311,7 +311,7 @@ Mesh *BKE_mesh_remesh_voxel_to_mesh_nomain(Mesh *mesh, OpenVDBLevelSet_free(level_set); OpenVDBTransform_free(xform); #else - UNUSED_VARS(mesh, voxel_size, adaptivity); + UNUSED_VARS(mesh, voxel_size, adaptivity, isovalue); #endif return new_mesh; } diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index c2fff7aa0e4..6d38ae13994 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -1978,7 +1978,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, if (mode & PBVH_Collapse) { EdgeQueue q; - BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert * [2]), 0, 128, BLI_MEMPOOL_NOP); + BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]), 0, 128, BLI_MEMPOOL_NOP); EdgeQueueContext eq_ctx = { &q, queue_pool, @@ -1997,7 +1997,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, if (mode & PBVH_Subdivide) { EdgeQueue q; - BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert * [2]), 0, 128, BLI_MEMPOOL_NOP); + BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]), 0, 128, BLI_MEMPOOL_NOP); EdgeQueueContext eq_ctx = { &q, queue_pool, diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 28f552cec2e..6f755aa6460 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -866,9 +866,9 @@ static bool target_project_solve_point_tri(const float *vtri_co[3], { float x[3], tmp[3]; float dist = sqrtf(hit_dist_sq); - float epsilon = dist * 1.0e-5f; - - CLAMP_MIN(epsilon, 1.0e-5f); + float magnitude_estimate = dist + len_manhattan_v3(vtri_co[0]) + len_manhattan_v3(vtri_co[1]) + + len_manhattan_v3(vtri_co[2]); + float epsilon = magnitude_estimate * 1.0e-6f; /* Initial solution vector: barycentric weights plus distance along normal. */ interp_weights_tri_v3(x, UNPACK3(vtri_co), hit_co); @@ -929,7 +929,7 @@ static bool update_hit(BVHTreeNearest *nearest, if (dist_sq < nearest->dist_sq) { #ifdef TRACE_TARGET_PROJECT printf( - "===> %d (%.3f,%.3f,%.3f) %g < %g\n", index, UNPACK3(hit_co), dist_sq, nearest->dist_sq); + "#=#=#> %d (%.3f,%.3f,%.3f) %g < %g\n", index, UNPACK3(hit_co), dist_sq, nearest->dist_sq); #endif nearest->index = index; nearest->dist_sq = dist_sq; @@ -1088,14 +1088,14 @@ void BKE_shrinkwrap_find_nearest_surface(struct ShrinkwrapTreeData *tree, if (type == MOD_SHRINKWRAP_TARGET_PROJECT) { #ifdef TRACE_TARGET_PROJECT - printf("====== TARGET PROJECT START ======\n"); + printf("\n====== TARGET PROJECT START ======\n"); #endif BLI_bvhtree_find_nearest_ex( tree->bvh, co, nearest, mesh_looptri_target_project, tree, BVH_NEAREST_OPTIMAL_ORDER); #ifdef TRACE_TARGET_PROJECT - printf("====== TARGET PROJECT END: %d %g ======\n", nearest->index, nearest->dist_sq); + printf("====== TARGET PROJECT END: %d %g ======\n\n", nearest->index, nearest->dist_sq); #endif if (nearest->index < 0) { @@ -1260,7 +1260,10 @@ static void shrinkwrap_snap_with_side(float r_point_co[3], float forcesign, bool forcesnap) { - float dist = len_v3v3(point_co, hit_co); + float delta[3]; + sub_v3_v3v3(delta, point_co, hit_co); + + float dist = len_v3(delta); /* If exactly on the surface, push out along normal */ if (dist < FLT_EPSILON) { @@ -1273,13 +1276,28 @@ static void shrinkwrap_snap_with_side(float r_point_co[3], } /* Move to the correct side if needed */ else { - float delta[3]; - sub_v3_v3v3(delta, point_co, hit_co); - float dsign = signf(dot_v3v3(delta, hit_no) * forcesign); + float dsign = signf(dot_v3v3(delta, hit_no)); + + if (forcesign == 0.0f) { + forcesign = dsign; + } /* If on the wrong side or too close, move to correct */ - if (forcesnap || dsign * dist < goal_dist) { - interp_v3_v3v3(r_point_co, point_co, hit_co, (dist - goal_dist * dsign) / dist); + if (forcesnap || dsign * dist * forcesign < goal_dist) { + mul_v3_fl(delta, dsign / dist); + + /* At very small distance, blend in the hit normal to stabilize math. */ + float dist_epsilon = (fabsf(goal_dist) + len_manhattan_v3(hit_co)) * 1e-4f; + + if (dist < dist_epsilon) { +#ifdef TRACE_TARGET_PROJECT + printf("zero_factor %g = %g / %g\n", dist / dist_epsilon, dist, dist_epsilon); +#endif + + interp_v3_v3v3(delta, hit_no, delta, dist / dist_epsilon); + } + + madd_v3_v3v3fl(r_point_co, hit_co, delta, goal_dist * forcesign); } else { copy_v3_v3(r_point_co, point_co); @@ -1304,13 +1322,13 @@ void BKE_shrinkwrap_snap_point_to_surface(const struct ShrinkwrapTreeData *tree, const float point_co[3], float r_point_co[3]) { - float dist, tmp[3]; + float tmp[3]; switch (mode) { /* Offsets along the line between point_co and hit_co. */ case MOD_SHRINKWRAP_ON_SURFACE: - if (goal_dist != 0 && (dist = len_v3v3(point_co, hit_co)) > FLT_EPSILON) { - interp_v3_v3v3(r_point_co, point_co, hit_co, (dist - goal_dist) / dist); + if (goal_dist != 0) { + shrinkwrap_snap_with_side(r_point_co, point_co, hit_co, hit_no, goal_dist, 0, true); } else { copy_v3_v3(r_point_co, hit_co); diff --git a/source/blender/blenlib/BLI_compiler_compat.h b/source/blender/blenlib/BLI_compiler_compat.h index bd1cd327d3c..312991e7f15 100644 --- a/source/blender/blenlib/BLI_compiler_compat.h +++ b/source/blender/blenlib/BLI_compiler_compat.h @@ -15,7 +15,7 @@ */ #ifndef __BLI_COMPILER_COMPAT_H__ -# define __BLI_COMPILER_COMPAT_H__ +#define __BLI_COMPILER_COMPAT_H__ /** \file * \ingroup bli @@ -23,32 +23,32 @@ * Use to help with cross platform portability. */ -# if defined(_MSC_VER) -# define alloca _alloca -# endif +#if defined(_MSC_VER) +# define alloca _alloca +#endif -# if (defined(__GNUC__) || defined(__clang__)) && defined(__cplusplus) +#if (defined(__GNUC__) || defined(__clang__)) && defined(__cplusplus) extern "C++" { /* Some magic to be sure we don't have reference in the type. */ template<typename T> static inline T decltype_helper(T x) { return x; } -# define typeof(x) decltype(decltype_helper(x)) +# define typeof(x) decltype(decltype_helper(x)) } -# endif +#endif /* little macro so inline keyword works */ -# if defined(_MSC_VER) -# define BLI_INLINE static __forceinline -# else -# define BLI_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__)) -# endif +#if defined(_MSC_VER) +# define BLI_INLINE static __forceinline +#else +# define BLI_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__)) +#endif -# if defined(__GNUC__) -# define BLI_NOINLINE __attribute__((noinline)) -# else -# define BLI_NOINLINE -# endif +#if defined(__GNUC__) +# define BLI_NOINLINE __attribute__((noinline)) +#else +# define BLI_NOINLINE +#endif #endif /* __BLI_COMPILER_COMPAT_H__ */ diff --git a/source/blender/blenlib/intern/BLI_temporary_allocator.cc b/source/blender/blenlib/intern/BLI_temporary_allocator.cc index e41cf36f66d..b145e65530d 100644 --- a/source/blender/blenlib/intern/BLI_temporary_allocator.cc +++ b/source/blender/blenlib/intern/BLI_temporary_allocator.cc @@ -73,7 +73,7 @@ struct ThreadLocalBuffers { } }; -thread_local ThreadLocalBuffers local_storage; +static thread_local ThreadLocalBuffers local_storage; void *BLI_temporary_allocate(uint size) { diff --git a/source/blender/blenlib/intern/math_solvers.c b/source/blender/blenlib/intern/math_solvers.c index a1c3d16a404..235589abdab 100644 --- a/source/blender/blenlib/intern/math_solvers.c +++ b/source/blender/blenlib/intern/math_solvers.c @@ -215,10 +215,10 @@ bool BLI_newton3d_solve(Newton3D_DeltaFunc func_delta, fdeltav = len_squared_v3(fdelta); if (trace) { - printf("START (%g, %g, %g) %g\n", x[0], x[1], x[2], fdeltav); + printf("START (%g, %g, %g) %g %g\n", x[0], x[1], x[2], fdeltav, epsilon); } - for (int i = 0; i < max_iterations && fdeltav > epsilon; i++) { + for (int i = 0; i == 0 || (i < max_iterations && fdeltav > epsilon); i++) { /* Newton's method step. */ func_jacobian(userdata, x, jacobian); @@ -248,7 +248,7 @@ bool BLI_newton3d_solve(Newton3D_DeltaFunc func_delta, } /* Line search correction. */ - while (next_fdeltav > fdeltav) { + while (next_fdeltav > fdeltav && next_fdeltav > epsilon) { float g0 = sqrtf(fdeltav), g1 = sqrtf(next_fdeltav); float g01 = -g0 / len_v3(step); float det = 2.0f * (g1 - g0 - g01); diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index d2192f1e22a..e1ee020940e 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -637,6 +637,10 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef) } } + if (!USER_VERSION_ATLEAST(282, 1)) { + userdef->file_space_data.filter_id = U_default.file_space_data.filter_id; + } + /** * Include next version bump. */ diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 68624540d08..af315597e68 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -139,14 +139,9 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl, } Object *ob = cache_ob->ob; - const DRWContextState *draw_ctx = DRW_context_state_get(); - const bool main_onion = draw_ctx->v3d != NULL ? - (draw_ctx->v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : - true; + const bool main_onion = stl->storage->is_main_onion; const bool playing = stl->storage->is_playing; - const bool overlay = draw_ctx->v3d != NULL ? - (bool)((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : - true; + const bool overlay = stl->storage->is_main_overlay; const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && overlay && main_onion && !playing && gpencil_onion_active(gpd); @@ -1802,8 +1797,8 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data, const bool overlay = draw_ctx->v3d != NULL ? (bool)((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true; - const bool main_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true; - const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && main_onion && + const bool screen_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true; + const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && screen_onion && overlay && gpencil_onion_active(gpd); int start_stroke = 0; @@ -2083,13 +2078,9 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data, bGPdata *gpd_eval = (bGPdata *)ob->data; bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id); - const bool main_onion = draw_ctx->v3d != NULL ? - (draw_ctx->v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : - true; + const bool main_onion = stl->storage->is_main_onion; const bool playing = stl->storage->is_playing; - const bool overlay = draw_ctx->v3d != NULL ? - (bool)((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : - true; + const bool overlay = stl->storage->is_main_overlay; const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && overlay && main_onion && !playing && gpencil_onion_active(gpd); diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index aaadf680955..9554e9c0275 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -24,11 +24,13 @@ #include "BKE_gpencil.h" #include "BKE_library.h" +#include "BKE_main.h" #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_shader_fx.h" #include "DNA_gpencil_types.h" +#include "DNA_screen_types.h" #include "DNA_view3d_types.h" #include "draw_mode_engines.h" @@ -305,6 +307,43 @@ static void GPENCIL_engine_free(void) GPENCIL_delete_fx_shaders(&e_data); } +/* Helper: Check if the main overlay and onion switches are enabled in any screen. + * + * This is required to generate the onion skin and limit the times the cache is updated because the + * cache is generated only in the first screen and if the first screen has the onion disabled the + * cache for onion skin is not generated. The loop adds time, but always is faster than regenerate + * the cache all the times. + */ +static void gpencil_check_screen_switches(const DRWContextState *draw_ctx, + GPENCIL_StorageList *stl) +{ + stl->storage->is_main_overlay = false; + stl->storage->is_main_onion = false; + /* Check if main onion switch is enabled in any screen. */ + Main *bmain = CTX_data_main(draw_ctx->evil_C); + + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa && sa->spacetype == SPACE_VIEW3D) { + View3D *v3d = sa->spacedata.first; + if (v3d == NULL) { + continue; + } + if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) { + stl->storage->is_main_overlay = true; + } + if (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) { + stl->storage->is_main_onion = true; + } + } + /* If found, don't need loop more. */ + if ((stl->storage->is_main_overlay) && (stl->storage->is_main_onion)) { + return; + } + } + } +} + void GPENCIL_cache_init(void *vedata) { GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; @@ -391,10 +430,15 @@ void GPENCIL_cache_init(void *vedata) stl->storage->reset_cache = true; } stl->storage->is_playing = playing; + + /* Found if main overlay and onion switches are enabled in any screen. */ + gpencil_check_screen_switches(draw_ctx, stl); } else { stl->storage->is_playing = false; stl->storage->reset_cache = false; + stl->storage->is_main_overlay = false; + stl->storage->is_main_onion = false; } /* save render state */ stl->storage->is_render = DRW_state_is_image_render(); diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 10cab248317..36bc205f41a 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -143,6 +143,8 @@ typedef struct GPENCIL_Storage { bool is_playing; bool is_render; bool is_mat_preview; + bool is_main_overlay; + bool is_main_onion; bool background_ready; int is_xray; bool is_ontop; diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index f28cf12405e..595b92d19d0 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -407,7 +407,8 @@ BLI_INLINE eGPUTextureFormat workbench_color_texture_format(const WORKBENCH_Priv return result; } -BLI_INLINE bool workbench_background_dither_factor(const WORKBENCH_PrivateData *wpd) { +BLI_INLINE bool workbench_background_dither_factor(const WORKBENCH_PrivateData *wpd) +{ /* Only apply dithering when rendering on a RGBA8 texture. * The dithering will remove banding when using a gradient as background */ return workbench_color_texture_format(wpd) == GPU_RGBA8; diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index 623a4a52aed..9957dbae3fb 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -688,7 +688,7 @@ static void edit_mesh_add_ob_to_pass(Scene *scene, skin_roots = DRW_mesh_batch_cache_get_edit_skin_roots(ob->data); /* NOTE(fclem) We cannot use ob here since it would offset the instance attribs with - * baseinstance offset. */ + * base instance offset. */ DRW_shgroup_call(grp, skin_roots, NULL); } } diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 29d06d5b297..36583ecf060 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -1181,7 +1181,7 @@ static int select_timeline_marker_frame(ListBase *markers, LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_selected) { /* this way a not-extend select will always give 1 selected marker */ - if ((marker->frame == frame)) { + if (marker->frame == frame) { marker->flag ^= SELECT; break; } diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index a8f8ec0e8c5..1af641e5c84 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -214,6 +214,8 @@ typedef struct tGPDprimitive { int sel_cp; /** flag to determine operations in progress */ int flag; + /** flag to determine operations previous mode */ + int prev_flag; /** recorded mouse-position */ float mval[2]; /** previous recorded mouse-position */ @@ -465,6 +467,7 @@ enum { GP_STROKE_CIRCLE = 2, GP_STROKE_ARC = 3, GP_STROKE_CURVE = 4, + GP_STROKE_POLYLINE = 5, }; enum { diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index c42c1c4d4c0..bf7b2edb025 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -90,6 +90,7 @@ #define IN_MOVE 3 #define IN_BRUSH_SIZE 4 #define IN_BRUSH_STRENGTH 5 +#define IN_POLYLINE 6 #define SELECT_NONE 0 #define SELECT_START 1 @@ -184,6 +185,29 @@ static void gpencil_primitive_to_square(tGPDprimitive *tgpi, const float x, cons } } +/* Helper to constrain a primitive */ +static void gpencil_primitive_constrain(tGPDprimitive *tgpi, bool line_mode) +{ + float x = tgpi->end[0] - tgpi->origin[0]; + float y = tgpi->end[1] - tgpi->origin[1]; + + if (line_mode) { + float angle = fabsf(atan2f(y, x)); + if (angle < 0.4f || angle > (M_PI - 0.4f)) { + tgpi->end[1] = tgpi->origin[1]; + } + else if (angle > (M_PI_2 - 0.4f) && angle < (M_PI_2 + 0.4f)) { + tgpi->end[0] = tgpi->origin[0]; + } + else { + gpencil_primitive_to_square(tgpi, x, y); + } + } + else { + gpencil_primitive_to_square(tgpi, x, y); + } + } + /* Helper to rotate point around origin */ static void gp_rotate_v2_v2v2fl(float v[2], const float p[2], @@ -404,6 +428,11 @@ static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi "adjust subdivision number, Shift to align, Alt to center, E: extrude"), UI_MAX_DRAW_STR); } + else if (tgpi->type == GP_STROKE_POLYLINE) { + BLI_strncpy(msg_str, + TIP_("Line: ESC to cancel, LMB to set, Enter/MMB to confirm, Shift to align"), + UI_MAX_DRAW_STR); + } else if (tgpi->type == GP_STROKE_BOX) { BLI_strncpy(msg_str, TIP_("Rectangle: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- " @@ -429,7 +458,7 @@ static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi UI_MAX_DRAW_STR); } - if (ELEM(tgpi->type, GP_STROKE_CIRCLE, GP_STROKE_ARC, GP_STROKE_LINE, GP_STROKE_BOX)) { + if (ELEM(tgpi->type, GP_STROKE_CIRCLE, GP_STROKE_ARC, GP_STROKE_LINE, GP_STROKE_BOX, GP_STROKE_POLYLINE)) { if (hasNumInput(&tgpi->num)) { char str_offs[NUM_STR_REP_LEN]; @@ -528,7 +557,7 @@ static void gp_primitive_rectangle(tGPDprimitive *tgpi, tGPspoint *points2D) } /* create a line */ -static void gp_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D) +static void gp_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D, bool editable) { const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges); const float step = 1.0f / (float)(tgpi->tot_edges - 1); @@ -540,15 +569,22 @@ static void gp_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D) a += step; } - float color[4]; - UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color); - gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL); - if (tgpi->tot_stored_edges) { - UI_GetThemeColor4fv(TH_REDALERT, color); - gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); + if (editable) { + float color[4]; + UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color); + gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL); + if (tgpi->tot_stored_edges) { + UI_GetThemeColor4fv(TH_REDALERT, color); + gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); + } + else { + gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL); + } } else { - gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL); + float color[4]; + UI_GetThemeColor4fv(TH_REDALERT, color); + gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); } } @@ -693,7 +729,10 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) gp_primitive_rectangle(tgpi, points2D); break; case GP_STROKE_LINE: - gp_primitive_line(tgpi, points2D); + gp_primitive_line(tgpi, points2D, true); + break; + case GP_STROKE_POLYLINE: + gp_primitive_line(tgpi, points2D, false); break; case GP_STROKE_CIRCLE: gp_primitive_circle(tgpi, points2D); @@ -1041,6 +1080,7 @@ static void gpencil_primitive_update(bContext *C, wmOperator *op, tGPDprimitive gp_primitive_update_strokes(C, tgpi); } +/* Initialise mouse points */ static void gpencil_primitive_interaction_begin(tGPDprimitive *tgpi, const wmEvent *event) { copy_v2fl_v2i(tgpi->mval, event->mval); @@ -1164,6 +1204,10 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op) /* set default edge count */ switch (tgpi->type) { + case GP_STROKE_POLYLINE: { + RNA_int_set(op->ptr, "edges", 8); + break; + } case GP_STROKE_LINE: { RNA_int_set(op->ptr, "edges", 8); break; @@ -1334,6 +1378,42 @@ static void gpencil_primitive_edit_event_handling( } switch (event->type) { + case LEFTMOUSE: { + if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS)) { + /* set control points and enter edit mode */ + if ((ELEM(tgpi->type, GP_STROKE_POLYLINE))) { + gpencil_primitive_add_segment(tgpi); + copy_v2_v2(tgpi->start, tgpi->end); + copy_v2_v2(tgpi->origin, tgpi->start); + gp_primitive_update_cps(tgpi); + + tgpi->flag = IN_POLYLINE; + WM_cursor_modal_set(win, WM_CURSOR_CROSS); + } + else { + tgpi->flag = IN_CURVE_EDIT; + gp_primitive_update_cps(tgpi); + gpencil_primitive_update(C, op, tgpi); + } + } + else if ((event->val == KM_PRESS) && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) { + /* find nearest cp based on stroke end points */ + if (move == MOVE_ENDS) { + tgpi->sel_cp = (a < b) ? SELECT_START : SELECT_END; + } + else if (move == MOVE_CP) { + tgpi->sel_cp = (c < d) ? SELECT_CP1 : SELECT_CP2; + } + else { + tgpi->sel_cp = SELECT_NONE; + } + break; + } + else { + tgpi->sel_cp = SELECT_NONE; + } + break; + } case MOUSEMOVE: { if ((event->val == KM_PRESS) && tgpi->sel_cp != SELECT_NONE) { if (tgpi->sel_cp == SELECT_START && tgpi->tot_stored_edges == 0) { @@ -1366,31 +1446,6 @@ static void gpencil_primitive_edit_event_handling( } break; } - case LEFTMOUSE: { - if ((event->val == KM_PRESS)) { - /* find nearest cp based on stroke end points */ - if (move == MOVE_ENDS) { - tgpi->sel_cp = (a < b) ? SELECT_START : SELECT_END; - } - else if (move == MOVE_CP) { - tgpi->sel_cp = (c < d) ? SELECT_CP1 : SELECT_CP2; - } - else { - tgpi->sel_cp = SELECT_NONE; - } - break; - } - else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS)) { - /* set control points and enter edit mode */ - tgpi->flag = IN_CURVE_EDIT; - gp_primitive_update_cps(tgpi); - gpencil_primitive_update(C, op, tgpi); - } - else { - tgpi->sel_cp = SELECT_NONE; - } - break; - } case MKEY: { if ((event->val == KM_PRESS) && (tgpi->curve) && (ELEM(tgpi->orign_type, GP_STROKE_ARC))) { tgpi->flip ^= 1; @@ -1524,6 +1579,96 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e copy_v2_v2(tgpi->mvalo, tgpi->mval); return OPERATOR_RUNNING_MODAL; } + else if (tgpi->flag == IN_POLYLINE) { + + switch (event->type) { + + case ESCKEY: { + /* return to normal cursor and header status */ + ED_workspace_status_text(C, NULL); + WM_cursor_modal_restore(win); + + /* clean up temp data */ + gpencil_primitive_exit(C, op); + + /* canceled! */ + return OPERATOR_CANCELLED; + } + case LEFTMOUSE: { + if (event->val == KM_PRESS) { + WM_cursor_modal_set(win, WM_CURSOR_CROSS); + gpencil_primitive_add_segment(tgpi); + + gpencil_primitive_update(C, op, tgpi); + copy_v2_v2(tgpi->start, tgpi->end); + copy_v2_v2(tgpi->origin, tgpi->end); + } + break; + } + case SPACEKEY: /* confirm */ + case MIDDLEMOUSE: + case RETKEY: + case RIGHTMOUSE: { + if (event->val == KM_PRESS) { + tgpi->flag = IDLE; + tgpi->tot_edges = tgpi->tot_stored_edges ? 1 : 0; + gp_primitive_update_strokes(C, tgpi); + gpencil_primitive_interaction_end(C, op, win, tgpi); + return OPERATOR_FINISHED; + } + break; + } + case MOUSEMOVE: { + WM_cursor_modal_set(win, WM_CURSOR_NSEW_SCROLL); + copy_v2_v2(tgpi->end, tgpi->mval); + + if (event->shift) { + gpencil_primitive_constrain(tgpi, true); + } + + gpencil_primitive_update(C, op, tgpi); + break; + } + case PADPLUSKEY: + case WHEELUPMOUSE: { + if ((event->val != KM_RELEASE)) { + tgpi->tot_edges = tgpi->tot_edges + 1; + CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES); + RNA_int_set(op->ptr, "edges", tgpi->tot_edges); + gpencil_primitive_update(C, op, tgpi); + } + break; + } + case PADMINUS: + case WHEELDOWNMOUSE: { + if ((event->val != KM_RELEASE)) { + tgpi->tot_edges = tgpi->tot_edges - 1; + CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES); + RNA_int_set(op->ptr, "edges", tgpi->tot_edges); + gpencil_primitive_update(C, op, tgpi); + } + break; + } + case FKEY: /* brush thickness/ brush strength */ + { + if ((event->val == KM_PRESS)) { + if (event->shift) { + tgpi->prev_flag = tgpi->flag; + tgpi->flag = IN_BRUSH_STRENGTH; + } + else { + tgpi->prev_flag = tgpi->flag; + tgpi->flag = IN_BRUSH_SIZE; + } + WM_cursor_modal_set(win, WM_CURSOR_NS_SCROLL); + } + break; + } + } + + copy_v2_v2(tgpi->mvalo, tgpi->mval); + return OPERATOR_RUNNING_MODAL; + } else if (tgpi->flag == IN_BRUSH_SIZE) { switch (event->type) { case MOUSEMOVE: @@ -1534,11 +1679,11 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e case MIDDLEMOUSE: case LEFTMOUSE: tgpi->brush_size = 0; - tgpi->flag = IN_CURVE_EDIT; + tgpi->flag = tgpi->prev_flag; break; case RIGHTMOUSE: if (event->val == KM_RELEASE) { - tgpi->flag = IN_CURVE_EDIT; + tgpi->flag = tgpi->prev_flag; gpencil_primitive_size(tgpi, true); gpencil_primitive_update(C, op, tgpi); } @@ -1557,11 +1702,11 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e case MIDDLEMOUSE: case LEFTMOUSE: tgpi->brush_strength = 0.0f; - tgpi->flag = IN_CURVE_EDIT; + tgpi->flag = tgpi->prev_flag; break; case RIGHTMOUSE: if (event->val == KM_RELEASE) { - tgpi->flag = IN_CURVE_EDIT; + tgpi->flag = tgpi->prev_flag; gpencil_primitive_strength(tgpi, true); gpencil_primitive_update(C, op, tgpi); } @@ -1570,7 +1715,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e copy_v2_v2(tgpi->mvalo, tgpi->mval); return OPERATOR_RUNNING_MODAL; } - else if (tgpi->flag != IDLE) { + else if (!ELEM(tgpi->flag, IDLE) && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) { gpencil_primitive_edit_event_handling(C, op, win, event, tgpi); } @@ -1581,24 +1726,38 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e /* TODO: Ignore if not in main region yet */ tgpi->flag = IN_PROGRESS; gpencil_primitive_interaction_begin(tgpi, event); + if (ELEM(tgpi->type, GP_STROKE_POLYLINE)) { + tgpi->flag = IN_POLYLINE; + gpencil_primitive_update(C, op, tgpi); + return OPERATOR_RUNNING_MODAL; + } } - else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_MOVE)) { - tgpi->flag = IN_CURVE_EDIT; - } - else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS)) { + else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS) && + (!ELEM(tgpi->type, GP_STROKE_POLYLINE))) { /* set control points and enter edit mode */ tgpi->flag = IN_CURVE_EDIT; gp_primitive_update_cps(tgpi); gpencil_primitive_update(C, op, tgpi); } else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS) && - (tgpi->type != GP_STROKE_CURVE)) { + (!ELEM(tgpi->type, GP_STROKE_CURVE, GP_STROKE_POLYLINE))) { /* stop drawing primitive */ tgpi->flag = IDLE; gpencil_primitive_interaction_end(C, op, win, tgpi); /* done! */ return OPERATOR_FINISHED; } + else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS) && + (ELEM(tgpi->type, GP_STROKE_POLYLINE))) { + /* set control points and enter edit mode */ + tgpi->flag = IN_POLYLINE; + gpencil_primitive_update(C, op, tgpi); + copy_v2_v2(tgpi->mvalo, tgpi->mval); + return OPERATOR_RUNNING_MODAL; + } + else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_MOVE)) { + tgpi->flag = IN_CURVE_EDIT; + } else { if (G.debug & G_DEBUG) { printf("GP Add Primitive Modal: LEFTMOUSE %d, Status = %d\n", event->val, tgpi->flag); @@ -1618,7 +1777,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e /* exception to cancel current stroke when we have previous strokes in buffer */ if (tgpi->tot_stored_edges > 0) { tgpi->flag = IDLE; - tgpi->tot_edges = 0; + tgpi->tot_edges = tgpi->tot_stored_edges ? 1 : 0; gp_primitive_update_strokes(C, tgpi); gpencil_primitive_interaction_end(C, op, win, tgpi); /* done! */ @@ -1673,9 +1832,11 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e { if ((event->val == KM_PRESS)) { if (event->shift) { + tgpi->prev_flag = tgpi->flag; tgpi->flag = IN_BRUSH_STRENGTH; } else { + tgpi->prev_flag = tgpi->flag; tgpi->flag = IN_BRUSH_SIZE; } WM_cursor_modal_set(win, WM_CURSOR_NS_SCROLL); @@ -1712,7 +1873,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e } case MOUSEMOVE: /* calculate new position */ { - if (tgpi->flag == IN_CURVE_EDIT) { + if (ELEM(tgpi->flag, IN_CURVE_EDIT)) { break; } /* only handle mousemove if not doing numinput */ @@ -1725,26 +1886,11 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e } /* Keep square if shift key */ if (event->shift) { - float x = tgpi->end[0] - tgpi->origin[0]; - float y = tgpi->end[1] - tgpi->origin[1]; - if (tgpi->type == GP_STROKE_LINE || tgpi->curve) { - float angle = fabsf(atan2f(y, x)); - if (angle < 0.4f || angle > (M_PI - 0.4f)) { - tgpi->end[1] = tgpi->origin[1]; - } - else if (angle > (M_PI_2 - 0.4f) && angle < (M_PI_2 + 0.4f)) { - tgpi->end[0] = tgpi->origin[0]; - } - else { - gpencil_primitive_to_square(tgpi, x, y); - } - } - else { - gpencil_primitive_to_square(tgpi, x, y); - } + gpencil_primitive_constrain( + tgpi, (ELEM(tgpi->type, GP_STROKE_LINE, GP_STROKE_POLYLINE) || tgpi->curve)); } /* Center primitive if alt key */ - if (event->alt) { + if (event->alt && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) { tgpi->start[0] = tgpi->origin[0] - (tgpi->end[0] - tgpi->origin[0]); tgpi->start[1] = tgpi->origin[1] - (tgpi->end[1] - tgpi->origin[1]); } @@ -1796,6 +1942,7 @@ void GPENCIL_OT_primitive(wmOperatorType *ot) static EnumPropertyItem primitive_type[] = { {GP_STROKE_BOX, "BOX", 0, "Box", ""}, {GP_STROKE_LINE, "LINE", 0, "Line", ""}, + {GP_STROKE_POLYLINE, "POLYLINE", 0, "Polyline", ""}, {GP_STROKE_CIRCLE, "CIRCLE", 0, "Circle", ""}, {GP_STROKE_ARC, "ARC", 0, "Arc", ""}, {GP_STROKE_CURVE, "CURVE", 0, "Curve", ""}, diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index bc8d25e8d9e..d33023c69a1 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -50,6 +50,7 @@ set(SRC interface_eyedropper_datablock.c interface_eyedropper_depth.c interface_eyedropper_driver.c + interface_eyedropper_gpencil_color.c interface_handlers.c interface_icons.c interface_icons_event.c diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index 3c26c37b610..988dea270f5 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -69,6 +69,7 @@ wmKeyMap *eyedropper_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_id"); WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_depth"); WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_driver"); + WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_gpencil_color"); return keymap; } diff --git a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c new file mode 100644 index 00000000000..02d4596e93c --- /dev/null +++ b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c @@ -0,0 +1,324 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup edinterface + * + * Eyedropper (RGB Color) + * + * Defines: + * - #UI_OT_eyedropper_gpencil_color + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_string.h" + +#include "BLT_translation.h" + +#include "DNA_gpencil_types.h" +#include "DNA_space_types.h" + +#include "BKE_context.h" +#include "BKE_gpencil.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_report.h" + +#include "UI_interface.h" + +#include "IMB_colormanagement.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "ED_gpencil.h" +#include "ED_screen.h" +#include "ED_undo.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + +#include "interface_intern.h" +#include "interface_eyedropper_intern.h" + +typedef struct EyedropperGPencil { + struct ColorManagedDisplay *display; + /** color under cursor RGB */ + float color[3]; +} EyedropperGPencil; + +/* Helper: Draw status message while the user is running the operator */ +static void eyedropper_gpencil_status_indicators(bContext *C) +{ + char msg_str[UI_MAX_DRAW_STR]; + BLI_strncpy( + msg_str, TIP_("LMB: Stroke - Shift: Fill - Shift+Ctrl: Stroke + Fill"), UI_MAX_DRAW_STR); + + ED_workspace_status_text(C, msg_str); +} + +/* Initialize. */ +static bool eyedropper_gpencil_init(bContext *C, wmOperator *op) +{ + EyedropperGPencil *eye = MEM_callocN(sizeof(EyedropperGPencil), __func__); + + op->customdata = eye; + Scene *scene = CTX_data_scene(C); + + const char *display_device; + display_device = scene->display_settings.display_device; + eye->display = IMB_colormanagement_display_get_named(display_device); + + return true; +} + +/* Exit and free memory. */ +static void eyedropper_gpencil_exit(bContext *C, wmOperator *op) +{ + /* Clear status message area. */ + ED_workspace_status_text(C, NULL); + + MEM_SAFE_FREE(op->customdata); +} + +/* Set the material. */ +static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, EyedropperGPencil *eye) +{ + Main *bmain = CTX_data_main(C); + Object *ob = CTX_data_active_object(C); + Material *ma = NULL; + + const bool only_stroke = ((!event->ctrl) && (!event->shift)); + const bool only_fill = ((!event->ctrl) && (event->shift)); + const bool both = ((event->ctrl) && (event->shift)); + + float col_conv[4]; + bool found = false; + + /* Convert from linear rgb space to display space because grease pencil colors are in display + * space, and this conversion is needed to undo the conversion to linear performed by + * eyedropper_color_sample_fl. */ + if (eye->display) { + copy_v3_v3(col_conv, eye->color); + IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display); + } + else { + copy_v3_v3(col_conv, eye->color); + } + + /* Look for a similar material in grease pencil slots. */ + short *totcol = give_totcolp(ob); + for (short i = 0; i < *totcol; i++) { + ma = give_current_material(ob, i + 1); + if (ma == NULL) { + continue; + } + + MaterialGPencilStyle *gp_style = ma->gp_style; + if (gp_style != NULL) { + /* Check stroke color. */ + bool found_stroke = compare_v3v3(gp_style->stroke_rgba, col_conv, 0.01f) && + (gp_style->flag & GP_STYLE_STROKE_SHOW); + /* Check fill color. */ + bool found_fill = compare_v3v3(gp_style->fill_rgba, col_conv, 0.01f) && + (gp_style->flag & GP_STYLE_FILL_SHOW); + + if ((only_stroke) && (found_stroke) && ((gp_style->flag & GP_STYLE_FILL_SHOW) == 0)) { + found = true; + } + else if ((only_fill) && (found_fill) && ((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0)) { + found = true; + } + else if ((both) && (found_stroke) && (found_fill)) { + found = true; + } + + /* Found existing material. */ + if (found) { + ob->actcol = i + 1; + WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL); + WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL); + return; + } + } + } + + /* If material was not found add a new material with stroke and/or fill color + * depending of the secondary key (LMB: Stroke, Shift: Fill, Shift+Ctrl: Stroke/Fill) + */ + int idx; + Material *ma_new = BKE_gpencil_object_material_new(bmain, ob, "Material", &idx); + WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, &ob->id); + WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL); + DEG_relations_tag_update(bmain); + + BLI_assert(ma_new != NULL); + + MaterialGPencilStyle *gp_style_new = ma_new->gp_style; + BLI_assert(gp_style_new != NULL); + + /* Only create Stroke (default option). */ + if (only_stroke) { + /* Stroke color. */ + gp_style_new->flag |= GP_STYLE_STROKE_SHOW; + gp_style_new->flag &= ~GP_STYLE_FILL_SHOW; + copy_v3_v3(gp_style_new->stroke_rgba, col_conv); + zero_v4(gp_style_new->fill_rgba); + } + /* Fill Only. */ + else if (only_fill) { + /* Fill color. */ + gp_style_new->flag &= ~GP_STYLE_STROKE_SHOW; + gp_style_new->flag |= GP_STYLE_FILL_SHOW; + zero_v4(gp_style_new->stroke_rgba); + copy_v3_v3(gp_style_new->fill_rgba, col_conv); + } + /* Stroke and Fill. */ + else if (both) { + gp_style_new->flag |= GP_STYLE_STROKE_SHOW | GP_STYLE_FILL_SHOW; + copy_v3_v3(gp_style_new->stroke_rgba, col_conv); + copy_v3_v3(gp_style_new->fill_rgba, col_conv); + } + /* Push undo for new created material. */ + ED_undo_push(C, "Add Grease Pencil Material"); +} + +/* Sample the color below cursor. */ +static void eyedropper_gpencil_color_sample(bContext *C, EyedropperGPencil *eye, int mx, int my) +{ + eyedropper_color_sample_fl(C, mx, my, eye->color); +} + +/* Cancel operator. */ +static void eyedropper_gpencil_cancel(bContext *C, wmOperator *op) +{ + eyedropper_gpencil_exit(C, op); +} + +/* Main modal status check. */ +static int eyedropper_gpencil_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + EyedropperGPencil *eye = (EyedropperGPencil *)op->customdata; + /* Handle modal keymap */ + switch (event->type) { + case EVT_MODAL_MAP: { + switch (event->val) { + case EYE_MODAL_SAMPLE_BEGIN: { + return OPERATOR_RUNNING_MODAL; + } + case EYE_MODAL_CANCEL: { + eyedropper_gpencil_cancel(C, op); + return OPERATOR_CANCELLED; + } + case EYE_MODAL_SAMPLE_CONFIRM: { + eyedropper_gpencil_color_sample(C, eye, event->x, event->y); + + /* Create material. */ + eyedropper_gpencil_color_set(C, event, eye); + WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + eyedropper_gpencil_exit(C, op); + return OPERATOR_FINISHED; + break; + } + default: { + break; + } + } + break; + } + case MOUSEMOVE: + case INBETWEEN_MOUSEMOVE: { + eyedropper_gpencil_color_sample(C, eye, event->x, event->y); + break; + } + default: { + break; + } + } + + return OPERATOR_RUNNING_MODAL; +} + +/* Modal Operator init */ +static int eyedropper_gpencil_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + /* Init. */ + if (eyedropper_gpencil_init(C, op)) { + /* Add modal temp handler. */ + WM_event_add_modal_handler(C, op); + /* Status message. */ + eyedropper_gpencil_status_indicators(C); + + return OPERATOR_RUNNING_MODAL; + } + else { + return OPERATOR_PASS_THROUGH; + } +} + +/* Repeat operator */ +static int eyedropper_gpencil_exec(bContext *C, wmOperator *op) +{ + /* init */ + if (eyedropper_gpencil_init(C, op)) { + + /* cleanup */ + eyedropper_gpencil_exit(C, op); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_PASS_THROUGH; + } +} + +static bool eyedropper_gpencil_poll(bContext *C) +{ + /* Only valid if the current active object is grease pencil. */ + Object *obact = CTX_data_active_object(C); + if ((obact == NULL) || (obact->type != OB_GPENCIL)) { + return false; + } + + /* Test we have a window below. */ + return (CTX_wm_window(C) != NULL); +} + +void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Grease Pencil Eyedropper"; + ot->idname = "UI_OT_eyedropper_gpencil_color"; + ot->description = "Sample a color from the Blender Window and create Grease Pencil material"; + + /* api callbacks */ + ot->invoke = eyedropper_gpencil_invoke; + ot->modal = eyedropper_gpencil_modal; + ot->cancel = eyedropper_gpencil_cancel; + ot->exec = eyedropper_gpencil_exec; + ot->poll = eyedropper_gpencil_poll; + + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; +} diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 4351b75eb86..81979b1fc8f 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -971,6 +971,9 @@ void UI_OT_eyedropper_depth(struct wmOperatorType *ot); /* interface_eyedropper_driver.c */ void UI_OT_eyedropper_driver(struct wmOperatorType *ot); +/* interface_eyedropper_gpencil_color.c */ +void UI_OT_eyedropper_gpencil_color(struct wmOperatorType *ot); + /* interface_util.c */ /** diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 4e56a02997b..7ce4242c697 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1751,6 +1751,7 @@ void ED_operatortypes_ui(void) WM_operatortype_append(UI_OT_eyedropper_id); WM_operatortype_append(UI_OT_eyedropper_depth); WM_operatortype_append(UI_OT_eyedropper_driver); + WM_operatortype_append(UI_OT_eyedropper_gpencil_color); } /** diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index c068fbdf7cb..9957fe0515c 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2869,7 +2869,7 @@ void ED_region_info_draw(ARegion *ar, float fill_color[4], const bool full_redraw) { - ED_region_info_draw_multiline(ar, (const char * [2]){text, NULL}, fill_color, full_redraw); + ED_region_info_draw_multiline(ar, (const char *[2]){text, NULL}, fill_color, full_redraw); } #define MAX_METADATA_STR 1024 diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 5ea95383892..3cdcc07f081 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -2395,60 +2395,49 @@ void FILE_OT_filenum(struct wmOperatorType *ot) RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100, 100); } -static int file_rename_exec(bContext *C, wmOperator *UNUSED(op)) +static void file_rename_state_activate(SpaceFile *sfile, int file_idx, bool require_selected) { - ScrArea *sa = CTX_wm_area(C); - SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); + const int numfiles = filelist_files_ensure(sfile->files); - if (sfile->params) { - int idx = sfile->params->highlight_file; - int numfiles = filelist_files_ensure(sfile->files); - if ((0 <= idx) && (idx < numfiles)) { - FileDirEntry *file = filelist_file(sfile->files, idx); + if ((file_idx >= 0) && (file_idx < numfiles)) { + FileDirEntry *file = filelist_file(sfile->files, file_idx); + + if ((require_selected == false) || + (filelist_entry_select_get(sfile->files, file, CHECK_ALL) & FILE_SEL_SELECTED)) { filelist_entry_select_index_set( - sfile->files, idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL); + sfile->files, file_idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL); BLI_strncpy(sfile->params->renamefile, file->relpath, FILE_MAXFILE); /* We can skip the pending state, * as we can directly set FILE_SEL_EDITING on the expected entry here. */ sfile->params->rename_flag = FILE_PARAMS_RENAME_ACTIVE; } + } +} + +static int file_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) +{ + ScrArea *sa = CTX_wm_area(C); + SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); + + if (sfile->params) { + file_rename_state_activate(sfile, sfile->params->active_file, true); ED_area_tag_redraw(sa); } return OPERATOR_FINISHED; } -static bool file_rename_poll(bContext *C) +static int file_rename_exec(bContext *C, wmOperator *UNUSED(op)) { - bool poll = ED_operator_file_active(C); - SpaceFile *sfile = CTX_wm_space_file(C); - - if (sfile && sfile->params) { - int idx = sfile->params->highlight_file; - int numfiles = filelist_files_ensure(sfile->files); - - if ((0 <= idx) && (idx < numfiles)) { - FileDirEntry *file = filelist_file(sfile->files, idx); - if (FILENAME_IS_CURRPAR(file->relpath)) { - poll = false; - } - } + ScrArea *sa = CTX_wm_area(C); + SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); - if (sfile->params->highlight_file < 0) { - poll = false; - } - else { - char dir[FILE_MAX_LIBEXTRA]; - if (filelist_islibrary(sfile->files, dir, NULL)) { - poll = false; - } - } - } - else { - poll = false; + if (sfile->params) { + file_rename_state_activate(sfile, sfile->params->highlight_file, false); + ED_area_tag_redraw(sa); } - return poll; + return OPERATOR_FINISHED; } void FILE_OT_rename(struct wmOperatorType *ot) @@ -2459,8 +2448,9 @@ void FILE_OT_rename(struct wmOperatorType *ot) ot->idname = "FILE_OT_rename"; /* api callbacks */ + ot->invoke = file_rename_invoke; ot->exec = file_rename_exec; - ot->poll = file_rename_poll; + ot->poll = ED_operator_file_active; } static bool file_delete_poll(bContext *C) diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index ba4ccb4fba9..bb3906a961b 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -103,10 +103,9 @@ short ED_fileselect_set_params(SpaceFile *sfile) sizeof(sfile->params->dir), sizeof(sfile->params->file)); sfile->params->filter_glob[0] = '\0'; - /* set the default thumbnails size */ sfile->params->thumbnail_size = U_default.file_space_data.thumbnail_size; - /* Show size column by default. */ sfile->params->details_flags = U_default.file_space_data.details_flags; + sfile->params->filter_id = U_default.file_space_data.filter_id; } params = sfile->params; @@ -246,9 +245,6 @@ short ED_fileselect_set_params(SpaceFile *sfile) } } - /* For now, always init filterid to 'all true' */ - params->filter_id = FILTER_ID_ALL; - if (U.uiflag & USER_HIDE_DOT) { params->flag |= FILE_HIDE_DOT; } @@ -348,6 +344,7 @@ void ED_fileselect_set_params_from_userdef(SpaceFile *sfile) } sfile->params->thumbnail_size = sfile_udata->thumbnail_size; sfile->params->details_flags = sfile_udata->details_flags; + sfile->params->filter_id = sfile_udata->filter_id; /* Combine flags we take from params with the flags we take from userdef. */ sfile->params->flag = (sfile->params->flag & ~PARAMS_FLAGS_REMEMBERED) | @@ -371,6 +368,7 @@ void ED_fileselect_params_to_userdef(SpaceFile *sfile, int temp_win_size[2]) sfile_udata_new->sort_type = sfile->params->sort; sfile_udata_new->details_flags = sfile->params->details_flags; sfile_udata_new->flag = sfile->params->flag & PARAMS_FLAGS_REMEMBERED; + sfile_udata_new->filter_id = sfile->params->filter_id; if (temp_win_size) { sfile_udata_new->temp_win_sizex = temp_win_size[0]; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index aafd36a5bb8..3ee9755cb06 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1422,18 +1422,24 @@ static void draw_grid_unit_name( { if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) { const char *grid_unit = NULL; + int font_id = BLF_default(); ED_view3d_grid_view_scale(scene, v3d, rv3d, &grid_unit); if (grid_unit) { char numstr[32] = ""; - UI_FontThemeColor(BLF_default(), TH_TEXT_HI); + UI_FontThemeColor(font_id, TH_TEXT_HI); if (v3d->grid != 1.0f) { BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); } *yoffset -= U.widget_unit; + BLF_enable(font_id, BLF_SHADOW); + BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); + BLF_shadow_offset(font_id, 1, -1); BLF_draw_default_ascii( xoffset, *yoffset, 0.0f, numstr[0] ? numstr : grid_unit, sizeof(numstr)); + + BLF_disable(font_id, BLF_SHADOW); } } } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 47bf49294b6..f303f7720c3 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -699,10 +699,11 @@ enum { #define FILTER_ID_ALL \ (FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU | FILTER_ID_GD | \ - FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA | FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | \ - FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | \ - FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO | FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | \ - FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS | FILTER_ID_LP) + FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA | \ + FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | \ + FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO | \ + FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS | \ + FILTER_ID_LP) /* IMPORTANT: this enum matches the order currently use in set_listbasepointers, * keep them in sync! */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index b9f43c0e579..c726c5e132e 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -588,8 +588,7 @@ typedef struct UserDef_FileSpaceData { int sort_type; /* FileSelectParams.sort */ int details_flags; /* FileSelectParams.details_flags */ int flag; /* FileSelectParams.flag */ - - char _pad[4]; + int filter_id; /* FileSelectParams.filter_id */ /** Info used when creating the file browser in a temporary window. */ int temp_win_sizex; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index fad9ec761aa..f9fa6e78163 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -787,13 +787,18 @@ static void rna_Space_view2d_sync_update(Main *UNUSED(bmain), static void rna_GPencil_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) { + bool changed = false; /* need set all caches as dirty to recalculate onion skinning */ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { if (ob->type == OB_GPENCIL) { - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + bGPdata *gpd = (bGPdata *)ob->data; + DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY); + changed = true; } } - WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); + if (changed) { + WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); + } } /* Space 3D View */ @@ -5290,7 +5295,11 @@ static void rna_def_fileselect_params(BlenderRNA *brna) {FILTER_ID_TXT, "TEXT", ICON_TEXT, "Texts", "Show/hide Text data-blocks"}, {FILTER_ID_VF, "FONT", ICON_FONT_DATA, "Fonts", "Show/hide Font data-blocks"}, {FILTER_ID_WO, "WORLD", ICON_WORLD_DATA, "Worlds", "Show/hide World data-blocks"}, - {FILTER_ID_WS, "WORK_SPACE", ICON_NONE, "Workspaces", "Show/hide workspace data-blocks"}, + {FILTER_ID_WS, + "WORK_SPACE", + ICON_WORKSPACE, + "Workspaces", + "Show/hide workspace data-blocks"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index c85a1d9ba05..c4a363e25e5 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -31,12 +31,6 @@ #include <Python.h> #include <frameobject.h> -/* Needed for 'PyInterpreterState', we should remove this dependency. */ -#if PY_VERSION_HEX >= 0x03080000 -# define Py_BUILD_CORE -# include <internal/pycore_pystate.h> -#endif - #include "BLI_utildefines.h" /* for bool */ #include "py_capi_utils.h" @@ -757,9 +751,10 @@ PyObject *PyC_UnicodeFromByte(const char *str) ****************************************************************************/ PyObject *PyC_DefaultNameSpace(const char *filename) { - PyInterpreterState *interp = PyThreadState_GET()->interp; + PyObject *modules = PyImport_GetModuleDict(); + PyObject *builtins = PyEval_GetBuiltins(); PyObject *mod_main = PyModule_New("__main__"); - PyDict_SetItemString(interp->modules, "__main__", mod_main); + PyDict_SetItemString(modules, "__main__", mod_main); Py_DECREF(mod_main); /* sys.modules owns now */ PyModule_AddStringConstant(mod_main, "__name__", "__main__"); if (filename) { @@ -767,8 +762,8 @@ PyObject *PyC_DefaultNameSpace(const char *filename) * note: this wont map to a real file when executing text-blocks and buttons. */ PyModule_AddObject(mod_main, "__file__", PyC_UnicodeFromByte(filename)); } - PyModule_AddObject(mod_main, "__builtins__", interp->builtins); - Py_INCREF(interp->builtins); /* AddObject steals a reference */ + PyModule_AddObject(mod_main, "__builtins__", builtins); + Py_INCREF(builtins); /* AddObject steals a reference */ return PyModule_GetDict(mod_main); } @@ -795,15 +790,15 @@ bool PyC_NameSpace_ImportArray(PyObject *py_dict, const char *imports[]) /* restore MUST be called after this */ void PyC_MainModule_Backup(PyObject **main_mod) { - PyInterpreterState *interp = PyThreadState_GET()->interp; - *main_mod = PyDict_GetItemString(interp->modules, "__main__"); + PyObject *modules = PyImport_GetModuleDict(); + *main_mod = PyDict_GetItemString(modules, "__main__"); Py_XINCREF(*main_mod); /* don't free */ } void PyC_MainModule_Restore(PyObject *main_mod) { - PyInterpreterState *interp = PyThreadState_GET()->interp; - PyDict_SetItemString(interp->modules, "__main__", main_mod); + PyObject *modules = PyImport_GetModuleDict(); + PyDict_SetItemString(modules, "__main__", main_mod); Py_XDECREF(main_mod); } diff --git a/source/blender/python/mathutils/mathutils_kdtree.c b/source/blender/python/mathutils/mathutils_kdtree.c index 65eac901df5..e3f2cd9bd14 100644 --- a/source/blender/python/mathutils/mathutils_kdtree.c +++ b/source/blender/python/mathutils/mathutils_kdtree.c @@ -436,7 +436,7 @@ PyTypeObject PyKDTree_Type = { (destructor)NULL, /* tp_del */ }; -PyDoc_STRVAR(py_kdtree_doc, "Generic 3-dimentional kd-tree to perform spatial searches."); +PyDoc_STRVAR(py_kdtree_doc, "Generic 3-dimensional kd-tree to perform spatial searches."); static struct PyModuleDef kdtree_moduledef = { PyModuleDef_HEAD_INIT, "mathutils.kdtree", /* m_name */ diff --git a/source/tools b/source/tools -Subproject 4ad446dbddd1b23acc185b8c056474d27b69278 +Subproject 8598818108ddaf35e30d2a2dbd408ad371e41eb |