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>2020-09-28 13:30:39 +0300
committerJacques Lucke <jacques@blender.org>2020-09-28 13:30:39 +0300
commitd525a541a2bf8913fce43e2f9bef3e37dba00d30 (patch)
treef2758c9fd14a2234c29d7130d1f776c3b88f4bbb
parente204f67cf0f570a69e46cf3eb731f2705c21ee46 (diff)
parentf808f2a4950a99f74780ea87e9d62ee36bc4ff35 (diff)
Merge branch 'master' into mesh-to-volume-modifier
-rw-r--r--CMakeLists.txt16
-rw-r--r--build_files/cmake/config/blender_full.cmake13
-rw-r--r--build_files/cmake/config/blender_lite.cmake13
-rw-r--r--build_files/cmake/config/blender_release.cmake11
-rw-r--r--build_files/cmake/platform/platform_apple_xcode.cmake8
-rw-r--r--intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc2
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py12
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py24
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py3
-rw-r--r--source/blender/blenkernel/BKE_anim_data.h6
-rw-r--r--source/blender/blenkernel/intern/action.c2
-rw-r--r--source/blender/blenkernel/intern/anim_data.c100
-rw-r--r--source/blender/blenkernel/intern/mesh.c1
-rw-r--r--source/blender/blenloader/intern/versioning_280.c7
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c206
-rw-r--r--source/blender/editors/animation/keyframing.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c13
-rw-r--r--source/blender/editors/include/UI_interface.h1
-rw-r--r--source/blender/editors/interface/interface.c805
-rw-r--r--source/blender/editors/interface/interface_panel.c5
-rw-r--r--source/blender/editors/screen/area.c19
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h1
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c117
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c1
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c204
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c4
-rw-r--r--source/blender/editors/transform/transform.c20
-rw-r--r--source/blender/editors/transform/transform_constraints.c14
-rw-r--r--source/blender/editors/transform/transform_constraints.h2
-rw-r--r--source/blender/editors/transform/transform_generics.c110
-rw-r--r--source/blender/editors/transform/transform_mode_rotate.c24
-rw-r--r--source/blender/editors/transform/transform_orientations.c5
-rw-r--r--source/blender/gpu/opengl/gl_texture.hh12
-rw-r--r--source/blender/makesdna/DNA_anim_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_access_compare_override.c10
-rw-r--r--source/blender/makesrna/intern/rna_animation.c9
-rw-r--r--source/blender/makesrna/intern/rna_curve.c28
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c7
-rw-r--r--source/blender/makesrna/intern/rna_rna.c33
-rw-r--r--source/blender/makesrna/intern/rna_space.c119
-rw-r--r--source/blender/modifiers/intern/MOD_weld.c16
-rw-r--r--source/blender/windowmanager/WM_api.h4
-rw-r--r--source/blender/windowmanager/intern/wm_gesture_ops.c72
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c1
m---------source/tools0
-rw-r--r--tests/python/modifiers.py2
46 files changed, 1162 insertions, 928 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cf8af6a17b7..a7353d0b914 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -223,8 +223,6 @@ if(WITH_GHOST_X11)
option(WITH_GHOST_XDND "Enable drag'n'drop support on X11 using XDND protocol" ON)
endif()
-option(WITH_GMP "Use the gmp library for more accurate booleans" OFF)
-
# Misc...
option(WITH_HEADLESS "Build without graphical support (renderfarm, server mode only)" OFF)
mark_as_advanced(WITH_HEADLESS)
@@ -859,13 +857,13 @@ if(NOT CMAKE_BUILD_TYPE MATCHES "Release")
if(MSVC)
set(COMPILER_ASAN_LINKER_FLAGS "/FUNCTIONPADMIN:6")
endif()
- if(APPLE)
- # COMPILER_ASAN_CFLAGS and COMPILER_ASAN_CXXFLAGS are the same as of
- # now, so use either for PLATFORM_CFLAGS.
- set(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} ${COMPILER_ASAN_CFLAGS}")
- set(COMPILER_ASAN_LINKER_FLAGS "-fno-omit-frame-pointer -fsanitize=address")
- endif(APPLE)
- if(COMPILER_ASAN_LIBRARY)
+
+ if(APPLE AND COMPILER_ASAN_LIBRARY)
+ string(REPLACE " " ";" _list_COMPILER_ASAN_CFLAGS ${COMPILER_ASAN_CFLAGS})
+ add_compile_options("$<$<NOT:$<CONFIG:Release>>:${_list_COMPILER_ASAN_CFLAGS}>")
+ add_link_options("$<$<NOT:$<CONFIG:Release>>:-fno-omit-frame-pointer;-fsanitize=address>")
+ unset(_list_COMPILER_ASAN_CFLAGS)
+ elseif(COMPILER_ASAN_LIBRARY)
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS};${COMPILER_ASAN_LIBRARY}")
set(PLATFORM_LINKFLAGS "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")
set(PLATFORM_LINKFLAGS_DEBUG "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")
diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake
index 97846452f33..c5ed59dfaa5 100644
--- a/build_files/cmake/config/blender_full.cmake
+++ b/build_files/cmake/config/blender_full.cmake
@@ -5,24 +5,22 @@
#
set(WITH_ALEMBIC ON CACHE BOOL "" FORCE)
+set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
set(WITH_BUILDINFO ON CACHE BOOL "" FORCE)
set(WITH_BULLET ON CACHE BOOL "" FORCE)
set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
set(WITH_CODEC_FFMPEG ON CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE ON CACHE BOOL "" FORCE)
+set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE)
set(WITH_CYCLES ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_EMBREE ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
set(WITH_DRACO ON CACHE BOOL "" FORCE)
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
-set(WITH_GMP ON CACHE BOOL "" FORCE)
-set(WITH_LIBMV ON CACHE BOOL "" FORCE)
-set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
-set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE)
set(WITH_FREESTYLE ON CACHE BOOL "" FORCE)
set(WITH_GMP ON CACHE BOOL "" FORCE)
-set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
set(WITH_IK_ITASC ON CACHE BOOL "" FORCE)
+set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_DDS ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_HDR ON CACHE BOOL "" FORCE)
@@ -31,12 +29,13 @@ set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE)
set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE)
set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE)
+set(WITH_LIBMV ON CACHE BOOL "" FORCE)
+set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
set(WITH_LZMA ON CACHE BOOL "" FORCE)
set(WITH_LZO ON CACHE BOOL "" FORCE)
-set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE)
set(WITH_MOD_OCEANSIM ON CACHE BOOL "" FORCE)
-set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
+set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
set(WITH_OPENAL ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index 7a664bbc008..f53bdaac41e 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -7,6 +7,7 @@
set(WITH_INSTALL_PORTABLE ON CACHE BOOL "" FORCE)
+set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE)
set(WITH_ALEMBIC OFF CACHE BOOL "" FORCE)
set(WITH_BOOST OFF CACHE BOOL "" FORCE)
set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE)
@@ -14,20 +15,17 @@ set(WITH_BULLET OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_AVI OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_FFMPEG OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
+set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_EMBREE OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_OSL OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_DEVICE_OPTIX OFF CACHE BOOL "" FORCE)
set(WITH_DRACO OFF CACHE BOOL "" FORCE)
set(WITH_FFTW3 OFF CACHE BOOL "" FORCE)
-set(WITH_GMP OFF CACHE BOOL "" FORCE)
-set(WITH_LIBMV OFF CACHE BOOL "" FORCE)
-set(WITH_LLVM OFF CACHE BOOL "" FORCE)
-set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE)
set(WITH_FREESTYLE OFF CACHE BOOL "" FORCE)
set(WITH_GMP OFF CACHE BOOL "" FORCE)
-set(WITH_IK_SOLVER OFF CACHE BOOL "" FORCE)
set(WITH_IK_ITASC OFF CACHE BOOL "" FORCE)
+set(WITH_IK_SOLVER OFF CACHE BOOL "" FORCE)
set(WITH_IMAGE_CINEON OFF CACHE BOOL "" FORCE)
set(WITH_IMAGE_DDS OFF CACHE BOOL "" FORCE)
set(WITH_IMAGE_HDR OFF CACHE BOOL "" FORCE)
@@ -37,12 +35,13 @@ set(WITH_IMAGE_TIFF OFF CACHE BOOL "" FORCE)
set(WITH_INPUT_NDOF OFF CACHE BOOL "" FORCE)
set(WITH_INTERNATIONAL OFF CACHE BOOL "" FORCE)
set(WITH_JACK OFF CACHE BOOL "" FORCE)
+set(WITH_LIBMV OFF CACHE BOOL "" FORCE)
+set(WITH_LLVM OFF CACHE BOOL "" FORCE)
set(WITH_LZMA OFF CACHE BOOL "" FORCE)
set(WITH_LZO OFF CACHE BOOL "" FORCE)
-set(WITH_MOD_REMESH OFF CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID OFF CACHE BOOL "" FORCE)
set(WITH_MOD_OCEANSIM OFF CACHE BOOL "" FORCE)
-set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE)
+set(WITH_MOD_REMESH OFF CACHE BOOL "" FORCE)
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake
index beb706b47ef..e7e64678b40 100644
--- a/build_files/cmake/config/blender_release.cmake
+++ b/build_files/cmake/config/blender_release.cmake
@@ -4,6 +4,7 @@
# cmake -C../blender/build_files/cmake/config/blender_release.cmake ../blender
#
+set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
set(WITH_ALEMBIC ON CACHE BOOL "" FORCE)
set(WITH_ASSERT_ABORT OFF CACHE BOOL "" FORCE)
set(WITH_BUILDINFO ON CACHE BOOL "" FORCE)
@@ -11,15 +12,12 @@ set(WITH_BULLET ON CACHE BOOL "" FORCE)
set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
set(WITH_CODEC_FFMPEG ON CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE ON CACHE BOOL "" FORCE)
+set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE)
set(WITH_CYCLES ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_EMBREE ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
set(WITH_DRACO ON CACHE BOOL "" FORCE)
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
-set(WITH_GMP ON CACHE BOOL "" FORCE)
-set(WITH_LIBMV ON CACHE BOOL "" FORCE)
-set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
-set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE)
set(WITH_FREESTYLE ON CACHE BOOL "" FORCE)
set(WITH_GMP ON CACHE BOOL "" FORCE)
set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
@@ -32,12 +30,13 @@ set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE)
set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE)
set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE)
+set(WITH_LIBMV ON CACHE BOOL "" FORCE)
+set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
set(WITH_LZMA ON CACHE BOOL "" FORCE)
set(WITH_LZO ON CACHE BOOL "" FORCE)
-set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE)
set(WITH_MOD_OCEANSIM ON CACHE BOOL "" FORCE)
-set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
+set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
set(WITH_OPENAL ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/platform/platform_apple_xcode.cmake b/build_files/cmake/platform/platform_apple_xcode.cmake
index 7e6bd14ecc3..3a43ca317dd 100644
--- a/build_files/cmake/platform/platform_apple_xcode.cmake
+++ b/build_files/cmake/platform/platform_apple_xcode.cmake
@@ -154,11 +154,3 @@ if(NOT ${CMAKE_GENERATOR} MATCHES "Xcode")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
add_definitions("-DMACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
endif()
-
-if(${CMAKE_GENERATOR} MATCHES "Xcode")
- # Generate schemes in Blender.xcodeproj/xcshareddata/xcschemes/ early, at
- # configuration time, not when Xcode is opened.
- # This gets rid of "Manage schemes automatically" confirmation dialog that
- # appears whenever CMake is run.
- set(CMAKE_XCODE_GENERATE_SCHEME ON)
-endif()
diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc
index a95b394ad06..c7c827fcd66 100644
--- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc
+++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc
@@ -255,7 +255,7 @@ NukeCameraIntrinsics::NukeCameraIntrinsics()
NukeCameraIntrinsics::NukeCameraIntrinsics(
const NukeCameraIntrinsics &from)
: CameraIntrinsics(from) {
- SetDistortion(from.k1(), from.k1());
+ SetDistortion(from.k1(), from.k2());
}
void NukeCameraIntrinsics::SetDistortion(double k1, double k2) {
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index fdd654009a7..f3e4c82090e 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -6388,6 +6388,17 @@ def km_3d_view_tool_sculpt_lasso_trim(params):
]},
)
+def km_3d_view_tool_sculpt_line_mask(params):
+ return (
+ "3D View Tool: Sculpt, Line Mask",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {"items": [
+ ("paint.mask_line_gesture", {"type": params.tool_tweak, "value": 'ANY'},
+ {"properties": [("value", 1.0)]}),
+ ("paint.mask_line_gesture", {"type": params.tool_tweak, "value": 'ANY', "ctrl": True},
+ {"properties": [("value", 0.0)]}),
+ ]},
+ )
def km_3d_view_tool_sculpt_mesh_filter(params):
return (
@@ -6993,6 +7004,7 @@ def generate_keymaps(params=None):
km_3d_view_tool_sculpt_lasso_face_set(params),
km_3d_view_tool_sculpt_box_trim(params),
km_3d_view_tool_sculpt_lasso_trim(params),
+ km_3d_view_tool_sculpt_line_mask(params),
km_3d_view_tool_sculpt_mesh_filter(params),
km_3d_view_tool_sculpt_cloth_filter(params),
km_3d_view_tool_sculpt_color_filter(params),
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 75dfd60b1d4..3f7a3604741 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -1259,6 +1259,21 @@ class _defs_sculpt:
)
@ToolDef.from_fn
+ def mask_line():
+ def draw_settings(_context, layout, tool):
+ props = tool.operator_properties("paint.mask_line_gesture")
+ layout.prop(props, "use_front_faces_only", expand=False)
+
+ return dict(
+ idname="builtin.line_mask",
+ label="Line Mask",
+ icon="ops.sculpt.line_mask",
+ widget=None,
+ keymap=(),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
def face_set_box():
def draw_settings(_context, layout, tool):
props = tool.operator_properties("sculpt.face_set_box_gesture")
@@ -1273,6 +1288,7 @@ class _defs_sculpt:
draw_settings=draw_settings,
)
+
@ToolDef.from_fn
def face_set_lasso():
def draw_settings(_context, layout, tool):
@@ -1308,7 +1324,6 @@ class _defs_sculpt:
keymap=(),
)
-
@ToolDef.from_fn
def mesh_filter():
def draw_settings(_context, layout, tool):
@@ -2653,6 +2668,13 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
),
_defs_sculpt.hide_border,
lambda context: (
+ (_defs_sculpt.mask_line,)
+ if context is None or (
+ context.preferences.view.show_developer_ui and
+ context.preferences.experimental.use_tools_missing_icons)
+ else ()
+ ),
+ lambda context: (
(_defs_sculpt.face_set_box,)
if context is None or (
context.preferences.view.show_developer_ui and
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index bbe23bc8bbc..ab904aa0d99 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -7132,7 +7132,8 @@ class VIEW3D_PT_gpencil_draw_context_menu(Panel):
gp_settings = brush.gpencil_settings
layout = self.layout
- is_vertex = settings.color_mode == 'VERTEXCOLOR' or brush.gpencil_tool == 'TINT'
+ is_pin_vertex = gp_settings.brush_draw_mode == 'VERTEXCOLOR'
+ is_vertex = settings.color_mode == 'VERTEXCOLOR' or brush.gpencil_tool == 'TINT' or is_pin_vertex
if brush.gpencil_tool not in {'ERASE', 'CUTTER', 'EYEDROPPER'} and is_vertex:
split = layout.split(factor=0.1)
diff --git a/source/blender/blenkernel/BKE_anim_data.h b/source/blender/blenkernel/BKE_anim_data.h
index 8507793b1dc..5293d8dd9b0 100644
--- a/source/blender/blenkernel/BKE_anim_data.h
+++ b/source/blender/blenkernel/BKE_anim_data.h
@@ -56,6 +56,12 @@ struct AnimData *BKE_animdata_add_id(struct ID *id);
/* Set active action used by AnimData from the given ID-block */
bool BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct bAction *act);
+bool BKE_animdata_action_editable(const struct AnimData *adt);
+
+/* Ensure that the action's idroot is set correctly given the ID type of the owner.
+ * Return true if it is, false if it was already set to an incompatible type. */
+bool BKE_animdata_action_ensure_idroot(const struct ID *owner, struct bAction *action);
+
/* Free AnimData */
void BKE_animdata_free(struct ID *id, const bool do_id_user);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 64a8ae15fd3..1ce0d07a135 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -47,6 +47,7 @@
#include "BLT_translation.h"
#include "BKE_action.h"
+#include "BKE_anim_data.h"
#include "BKE_anim_visualization.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
@@ -1817,6 +1818,7 @@ void what_does_obaction(Object *ob,
workob->adt = &adt;
adt.action = act;
+ BKE_animdata_action_ensure_idroot(&workob->id, act);
/* execute effects of Action on to workob (or it's PoseChannels) */
BKE_animsys_evaluate_animdata(&workob->id, &adt, anim_eval_context, ADT_RECALC_ANIM, false);
diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c
index 4d815077e91..e7c6e00a61f 100644
--- a/source/blender/blenkernel/intern/anim_data.c
+++ b/source/blender/blenkernel/intern/anim_data.c
@@ -169,60 +169,88 @@ AnimData *BKE_animdata_add_id(ID *id)
/**
* Called when user tries to change the active action of an AnimData block
* (via RNA, Outliner, etc.)
+ *
+ * \param reports can be NULL.
+ * \param id the owner of the animation data
+ * \param act the Action to set, or NULL to clear.
+ *
+ * Return true when the action was succesfully updated, false otherwise.
*/
bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act)
{
AnimData *adt = BKE_animdata_from_id(id);
- bool ok = false;
- /* animdata validity check */
+ /* Animdata validity check. */
if (adt == NULL) {
BKE_report(reports, RPT_WARNING, "No AnimData to set action on");
- return ok;
+ return false;
}
- /* active action is only editable when it is not a tweaking strip
- * see rna_AnimData_action_editable() in rna_animation.c
- */
- if ((adt->flag & ADT_NLA_EDIT_ON) || (adt->actstrip) || (adt->tmpact)) {
- /* cannot remove, otherwise things turn to custard */
+ if (adt->action == act) {
+ /* Don't bother reducing and increasing the user count when there is nothing changing. */
+ return true;
+ }
+
+ if (!BKE_animdata_action_editable(adt)) {
+ /* Cannot remove, otherwise things turn to custard. */
BKE_report(reports, RPT_ERROR, "Cannot change action, as it is still being edited in NLA");
- return ok;
+ return false;
}
- /* manage usercount for current action */
+ /* Reduce usercount for current action. */
if (adt->action) {
id_us_min((ID *)adt->action);
}
- /* assume that AnimData's action can in fact be edited... */
- if (act) {
- /* action must have same type as owner */
- if (ELEM(act->idroot, 0, GS(id->name))) {
- /* can set */
- adt->action = act;
- id_us_plus((ID *)adt->action);
- ok = true;
- }
- else {
- /* cannot set */
- BKE_reportf(
- reports,
- RPT_ERROR,
- "Could not set action '%s' onto ID '%s', as it does not have suitably rooted paths "
- "for this purpose",
- act->id.name + 2,
- id->name);
- /* ok = false; */
- }
- }
- else {
- /* just clearing the action... */
+ if (act == NULL) {
+ /* Just clearing the action. */
adt->action = NULL;
- ok = true;
+ return true;
+ }
+
+ /* Action must have same type as owner. */
+ if (!BKE_animdata_action_ensure_idroot(id, act)) {
+ /* Cannot set to this type. */
+ BKE_reportf(
+ reports,
+ RPT_ERROR,
+ "Could not set action '%s' onto ID '%s', as it does not have suitably rooted paths "
+ "for this purpose",
+ act->id.name + 2,
+ id->name);
+ return false;
+ }
+
+ adt->action = act;
+ id_us_plus((ID *)adt->action);
+
+ return true;
+}
+
+bool BKE_animdata_action_editable(const AnimData *adt)
+{
+ /* Active action is only editable when it is not a tweaking strip. */
+ const bool is_tweaking_strip = (adt->flag & ADT_NLA_EDIT_ON) || adt->actstrip != NULL ||
+ adt->tmpact != NULL;
+ return !is_tweaking_strip;
+}
+
+bool BKE_animdata_action_ensure_idroot(const ID *owner, bAction *action)
+{
+ const int idcode = GS(owner->name);
+
+ if (action == NULL) {
+ /* A NULL action is usable by any ID type. */
+ return true;
+ }
+
+ if (action->idroot == 0) {
+ /* First time this Action is assigned, lock it to this ID type. */
+ action->idroot = idcode;
+ return true;
}
- return ok;
+ return (action->idroot == idcode);
}
/* Freeing -------------------------------------------- */
@@ -668,6 +696,7 @@ void BKE_animdata_transfer_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBa
* and name it in a similar way so that it can be easily found again. */
if (dstAdt->action == NULL) {
dstAdt->action = BKE_action_add(bmain, srcAdt->action->id.name + 2);
+ BKE_animdata_action_ensure_idroot(dstID, dstAdt->action);
}
else if (dstAdt->action == srcAdt->action) {
CLOG_WARN(&LOG,
@@ -680,6 +709,7 @@ void BKE_animdata_transfer_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBa
/* TODO: review this... */
id_us_min(&dstAdt->action->id);
dstAdt->action = BKE_action_add(bmain, dstAdt->action->id.name + 2);
+ BKE_animdata_action_ensure_idroot(dstID, dstAdt->action);
}
/* loop over base paths, trying to fix for each one... */
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 71209739238..3a33478691b 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -927,6 +927,7 @@ void BKE_mesh_copy_settings(Mesh *me_dst, const Mesh *me_src)
me_dst->remesh_mode = me_src->remesh_mode;
me_dst->face_sets_color_seed = me_src->face_sets_color_seed;
+ me_dst->face_sets_color_default = me_src->face_sets_color_default;
/* Copy texture space. */
me_dst->texflag = me_src->texflag;
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 213fbe0bde0..14a4643f760 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -1242,7 +1242,12 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
break;
}
}
- BLI_assert(collection_hidden != NULL);
+ if (collection_hidden == NULL) {
+ /* This should never happen (objects are always supposed to be instantiated in a
+ * scene), but it does sometimes, see e.g. T81168.
+ * Just put them in first hidden collection in those cases. */
+ collection_hidden = &hidden_collection_array[0];
+ }
if (*collection_hidden == NULL) {
char name[MAX_ID_NAME];
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 560b14bfd9a..80976d150c0 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -461,6 +461,115 @@ void ANIM_deselect_anim_channels(
/* ---------------------------- Graph Editor ------------------------------------- */
+/* Copy a certain channel setting to parents of the modified channel. */
+static void anim_flush_channel_setting_up(bAnimContext *ac,
+ const eAnimChannel_Settings setting,
+ const eAnimChannels_SetFlag mode,
+ bAnimListElem *const match,
+ const int matchLevel)
+{
+ /* flush up?
+ *
+ * For Visibility:
+ * - only flush up if the current state is now enabled (positive 'on' state is default)
+ * (otherwise, it's too much work to force the parents to be inactive too)
+ *
+ * For everything else:
+ * - only flush up if the current state is now disabled (negative 'off' state is default)
+ * (otherwise, it's too much work to force the parents to be active too)
+ */
+ if (setting == ACHANNEL_SETTING_VISIBLE) {
+ if (mode == ACHANNEL_SETFLAG_CLEAR) {
+ return;
+ }
+ }
+ else {
+ if (mode != ACHANNEL_SETFLAG_CLEAR) {
+ return;
+ }
+ }
+
+ /* Go backwards in the list, until the highest-ranking element
+ * (by indention has been covered). */
+ int prevLevel = matchLevel;
+ for (bAnimListElem *ale = match->prev; ale; ale = ale->prev) {
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+
+ /* if no channel info was found, skip, since this type might not have any useful info */
+ if (acf == NULL) {
+ continue;
+ }
+
+ /* Get the level of the current channel traversed
+ * - we define the level as simply being the offset for the start of the channel
+ */
+ const int level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
+
+ if (level == prevLevel) {
+ /* Don't influence siblings. */
+ continue;
+ }
+
+ if (level > prevLevel) {
+ /* If previous level was a base-level (i.e. 0 offset / root of one hierarchy), stop here. */
+ if (prevLevel == 0) {
+ return;
+ }
+
+ /* Otherwise, this level weaves into another sibling hierarchy to the previous one just
+ * finished, so skip until we get to the parent of this level. */
+ continue;
+ }
+
+ /* The level is 'less than' (i.e. more important) the level we're matching but also 'less
+ * than' the level just tried (i.e. only the 1st group above grouped F-Curves, when toggling
+ * visibility of F-Curves, gets flushed, which should happen if we don't let prevLevel get
+ * updated below once the first 1st group is found). */
+ ANIM_channel_setting_set(ac, ale, setting, mode);
+
+ /* store this level as the 'old' level now */
+ prevLevel = level;
+ }
+}
+
+/* Copy a certain channel setting to children of the modified channel. */
+static void anim_flush_channel_setting_down(bAnimContext *ac,
+ const eAnimChannel_Settings setting,
+ const eAnimChannels_SetFlag mode,
+ bAnimListElem *const match,
+ const int matchLevel)
+{
+ /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */
+ for (bAnimListElem *ale = match->next; ale; ale = ale->next) {
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+
+ /* if no channel info was found, skip, since this type might not have any useful info */
+ if (acf == NULL) {
+ continue;
+ }
+
+ /* get the level of the current channel traversed
+ * - we define the level as simply being the offset for the start of the channel
+ */
+ const int level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
+
+ /* if the level is 'greater than' (i.e. less important) the channel that was changed,
+ * flush the new status...
+ */
+ if (level > matchLevel) {
+ ANIM_channel_setting_set(ac, ale, setting, mode);
+ /* however, if the level is 'less than or equal to' the channel that was changed,
+ * (i.e. the current channel is as important if not more important than the changed
+ * channel) then we should stop, since we've found the last one of the children we should
+ * flush
+ */
+ }
+ else {
+ break;
+ }
+ }
+}
+
/* Flush visibility (for Graph Editor) changes up/down hierarchy for changes in the given setting
* - anim_data: list of the all the anim channels that can be chosen
* -> filtered using ANIMFILTER_CHANNELS only, since if we took VISIBLE too,
@@ -477,7 +586,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac,
eAnimChannels_SetFlag mode)
{
bAnimListElem *ale, *match = NULL;
- int prevLevel = 0, matchLevel = 0;
+ int matchLevel = 0;
/* sanity check */
if (ELEM(NULL, anim_data, anim_data->first)) {
@@ -517,101 +626,10 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac,
* - we define the level as simply being the offset for the start of the channel
*/
matchLevel = (acf->get_offset) ? acf->get_offset(ac, ale_setting) : 0;
- prevLevel = matchLevel;
}
- /* flush up?
- *
- * For Visibility:
- * - only flush up if the current state is now enabled (positive 'on' state is default)
- * (otherwise, it's too much work to force the parents to be inactive too)
- *
- * For everything else:
- * - only flush up if the current state is now disabled (negative 'off' state is default)
- * (otherwise, it's too much work to force the parents to be active too)
- */
- if (((setting == ACHANNEL_SETTING_VISIBLE) && (mode != ACHANNEL_SETFLAG_CLEAR)) ||
- ((setting != ACHANNEL_SETTING_VISIBLE) && (mode == ACHANNEL_SETFLAG_CLEAR))) {
- /* Go backwards in the list, until the highest-ranking element
- * (by indention has been covered). */
- for (ale = match->prev; ale; ale = ale->prev) {
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- int level;
-
- /* if no channel info was found, skip, since this type might not have any useful info */
- if (acf == NULL) {
- continue;
- }
-
- /* get the level of the current channel traversed
- * - we define the level as simply being the offset for the start of the channel
- */
- level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
-
- /* if the level is 'less than' (i.e. more important) the level we're matching
- * but also 'less than' the level just tried (i.e. only the 1st group above grouped F-Curves,
- * when toggling visibility of F-Curves, gets flushed, which should happen if we don't let
- * prevLevel get updated below once the first 1st group is found).
- */
- if (level < prevLevel) {
- /* flush the new status... */
- ANIM_channel_setting_set(ac, ale, setting, mode);
-
- /* store this level as the 'old' level now */
- prevLevel = level;
- }
- /* if the level is 'greater than' (i.e. less important) than the previous level... */
- else if (level > prevLevel) {
- /* if previous level was a base-level (i.e. 0 offset / root of one hierarchy),
- * stop here
- */
- if (prevLevel == 0) {
- break;
- /* otherwise, this level weaves into another sibling hierarchy to the previous one just
- * finished, so skip until we get to the parent of this level
- */
- }
- continue;
- }
- }
- }
-
- /* flush down (always) */
- {
- /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */
- for (ale = match->next; ale; ale = ale->next) {
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- int level;
-
- /* if no channel info was found, skip, since this type might not have any useful info */
- if (acf == NULL) {
- continue;
- }
-
- /* get the level of the current channel traversed
- * - we define the level as simply being the offset for the start of the channel
- */
- level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
-
- /* if the level is 'greater than' (i.e. less important) the channel that was changed,
- * flush the new status...
- */
- if (level > matchLevel) {
- ANIM_channel_setting_set(ac, ale, setting, mode);
- /* however, if the level is 'less than or equal to' the channel that was changed,
- * (i.e. the current channel is as important if not more important than the changed
- * channel) then we should stop, since we've found the last one of the children we should
- * flush
- */
- }
- else {
- break;
- }
-
- /* store this level as the 'old' level now */
- // prevLevel = level; // XXX: prevLevel is unused
- }
- }
+ anim_flush_channel_setting_up(ac, setting, mode, match, matchLevel);
+ anim_flush_channel_setting_down(ac, setting, mode, match, matchLevel);
}
/* -------------------------- F-Curves ------------------------------------- */
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index fb4c0ae0758..3701e9dc91c 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -162,7 +162,7 @@ bAction *ED_id_action_ensure(Main *bmain, ID *id)
* so that users can't accidentally break actions by assigning them
* to the wrong places
*/
- adt->action->idroot = GS(id->name);
+ BKE_animdata_action_ensure_idroot(id, adt->action);
/* Tag depsgraph to be rebuilt to include time dependency. */
DEG_relations_tag_update(bmain);
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index ac8085f0e53..b7bf1861ff3 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -4434,6 +4434,19 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
}
}
+ /* Remove unused slots. */
+ int actcol = ob_dst->actcol;
+ for (int slot = 1; slot <= ob_dst->totcol; slot++) {
+ while (slot <= ob_dst->totcol && !BKE_object_material_slot_used(ob_dst->data, slot)) {
+ ob_dst->actcol = slot;
+ BKE_object_material_slot_remove(bmain, ob_dst);
+ if (actcol >= slot) {
+ actcol--;
+ }
+ }
+ }
+ ob_dst->actcol = actcol;
+
DEG_id_tag_update(&gpd_src->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
DEG_id_tag_update(&gpd_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 376dcb6d811..4f656420b06 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1685,6 +1685,7 @@ struct Panel *UI_panel_begin(struct ARegion *region,
bool *r_open);
void UI_panel_end(const struct ARegion *region, uiBlock *block, int width, int height, bool open);
+bool UI_panel_is_active(const struct Panel *panel);
void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y);
int UI_panel_size_y(const struct Panel *panel);
bool UI_panel_is_dragging(const struct Panel *panel);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 433058260f7..a5b7a011e6b 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -129,43 +129,38 @@ static bool ui_but_is_unit_radians(const uiBut *but)
/* ************* window matrix ************** */
-void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *x, float *y)
+void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y)
{
- float gx, gy;
- int sx, sy, getsizex, getsizey;
+ int getsizex = BLI_rcti_size_x(&region->winrct) + 1;
+ int getsizey = BLI_rcti_size_y(&region->winrct) + 1;
+ int sx = region->winrct.xmin;
+ int sy = region->winrct.ymin;
- getsizex = BLI_rcti_size_x(&region->winrct) + 1;
- getsizey = BLI_rcti_size_y(&region->winrct) + 1;
- sx = region->winrct.xmin;
- sy = region->winrct.ymin;
-
- gx = *x;
- gy = *y;
+ float gx = *r_x;
+ float gy = *r_y;
if (block->panel) {
gx += block->panel->ofsx;
gy += block->panel->ofsy;
}
- *x = ((float)sx) +
- ((float)getsizex) * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] +
- block->winmat[3][0]));
- *y = ((float)sy) +
- ((float)getsizey) * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] +
- block->winmat[3][1]));
+ *r_x = ((float)sx) +
+ ((float)getsizex) * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] +
+ block->winmat[3][0]));
+ *r_y = ((float)sy) +
+ ((float)getsizey) * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] +
+ block->winmat[3][1]));
}
-void ui_block_to_window(const ARegion *region, uiBlock *block, int *x, int *y)
+void ui_block_to_window(const ARegion *region, uiBlock *block, int *r_x, int *r_y)
{
- float fx, fy;
-
- fx = *x;
- fy = *y;
+ float fx = *r_x;
+ float fy = *r_y;
ui_block_to_window_fl(region, block, &fx, &fy);
- *x = (int)(fx + 0.5f);
- *y = (int)(fy + 0.5f);
+ *r_x = (int)(fx + 0.5f);
+ *r_y = (int)(fy + 0.5f);
}
void ui_block_to_window_rctf(const ARegion *region,
@@ -181,9 +176,8 @@ void ui_block_to_window_rctf(const ARegion *region,
float ui_block_to_window_scale(const ARegion *region, uiBlock *block)
{
/* We could have function for this to avoid dummy arg. */
- float dummy_x;
float min_y = 0, max_y = 1;
- dummy_x = 0.0f;
+ float dummy_x = 0.0f;
ui_block_to_window_fl(region, block, &dummy_x, &min_y);
dummy_x = 0.0f;
ui_block_to_window_fl(region, block, &dummy_x, &max_y);
@@ -191,33 +185,30 @@ float ui_block_to_window_scale(const ARegion *region, uiBlock *block)
}
/* for mouse cursor */
-void ui_window_to_block_fl(const ARegion *region, uiBlock *block, float *x, float *y)
+void ui_window_to_block_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y)
{
- float a, b, c, d, e, f, px, py;
- int sx, sy, getsizex, getsizey;
-
- getsizex = BLI_rcti_size_x(&region->winrct) + 1;
- getsizey = BLI_rcti_size_y(&region->winrct) + 1;
- sx = region->winrct.xmin;
- sy = region->winrct.ymin;
+ int getsizex = BLI_rcti_size_x(&region->winrct) + 1;
+ int getsizey = BLI_rcti_size_y(&region->winrct) + 1;
+ int sx = region->winrct.xmin;
+ int sy = region->winrct.ymin;
- a = 0.5f * ((float)getsizex) * block->winmat[0][0];
- b = 0.5f * ((float)getsizex) * block->winmat[1][0];
- c = 0.5f * ((float)getsizex) * (1.0f + block->winmat[3][0]);
+ float a = 0.5f * ((float)getsizex) * block->winmat[0][0];
+ float b = 0.5f * ((float)getsizex) * block->winmat[1][0];
+ float c = 0.5f * ((float)getsizex) * (1.0f + block->winmat[3][0]);
- d = 0.5f * ((float)getsizey) * block->winmat[0][1];
- e = 0.5f * ((float)getsizey) * block->winmat[1][1];
- f = 0.5f * ((float)getsizey) * (1.0f + block->winmat[3][1]);
+ float d = 0.5f * ((float)getsizey) * block->winmat[0][1];
+ float e = 0.5f * ((float)getsizey) * block->winmat[1][1];
+ float f = 0.5f * ((float)getsizey) * (1.0f + block->winmat[3][1]);
- px = *x - sx;
- py = *y - sy;
+ float px = *r_x - sx;
+ float py = *r_y - sy;
- *y = (a * (py - f) + d * (c - px)) / (a * e - d * b);
- *x = (px - b * (*y) - c) / a;
+ *r_y = (a * (py - f) + d * (c - px)) / (a * e - d * b);
+ *r_x = (px - b * (*r_y) - c) / a;
if (block->panel) {
- *x -= block->panel->ofsx;
- *y -= block->panel->ofsy;
+ *r_x -= block->panel->ofsx;
+ *r_y -= block->panel->ofsy;
}
}
@@ -231,23 +222,21 @@ void ui_window_to_block_rctf(const struct ARegion *region,
ui_window_to_block_fl(region, block, &rct_dst->xmax, &rct_dst->ymax);
}
-void ui_window_to_block(const ARegion *region, uiBlock *block, int *x, int *y)
+void ui_window_to_block(const ARegion *region, uiBlock *block, int *r_x, int *r_y)
{
- float fx, fy;
-
- fx = *x;
- fy = *y;
+ float fx = *r_x;
+ float fy = *r_y;
ui_window_to_block_fl(region, block, &fx, &fy);
- *x = (int)(fx + 0.5f);
- *y = (int)(fy + 0.5f);
+ *r_x = (int)(fx + 0.5f);
+ *r_y = (int)(fy + 0.5f);
}
-void ui_window_to_region(const ARegion *region, int *x, int *y)
+void ui_window_to_region(const ARegion *region, int *r_x, int *r_y)
{
- *x -= region->winrct.xmin;
- *y -= region->winrct.ymin;
+ *r_x -= region->winrct.xmin;
+ *r_y -= region->winrct.ymin;
}
void ui_window_to_region_rcti(const ARegion *region, rcti *rect_dst, const rcti *rct_src)
@@ -258,10 +247,10 @@ void ui_window_to_region_rcti(const ARegion *region, rcti *rect_dst, const rcti
rect_dst->ymax = rct_src->ymax - region->winrct.ymin;
}
-void ui_region_to_window(const ARegion *region, int *x, int *y)
+void ui_region_to_window(const ARegion *region, int *r_x, int *r_y)
{
- *x += region->winrct.xmin;
- *y += region->winrct.ymin;
+ *r_x += region->winrct.xmin;
+ *r_y += region->winrct.ymin;
}
static void ui_update_flexible_spacing(const ARegion *region, uiBlock *block)
@@ -448,8 +437,6 @@ static void ui_block_bounds_calc_text(uiBlock *block, float offset)
void ui_block_bounds_calc(uiBlock *block)
{
- int xof;
-
if (BLI_listbase_is_empty(&block->buttons)) {
if (block->panel) {
block->rect.xmin = 0.0;
@@ -476,12 +463,7 @@ void ui_block_bounds_calc(uiBlock *block)
/* hardcoded exception... but that one is annoying with larger safety */
uiBut *bt = block->buttons.first;
- if (bt && STREQLEN(bt->str, "ERROR", 5)) {
- xof = 10;
- }
- else {
- xof = 40;
- }
+ int xof = (bt && STREQLEN(bt->str, "ERROR", 5)) ? 10 : 40;
block->safety.xmin = block->rect.xmin - xof;
block->safety.ymin = block->rect.ymin - xof;
@@ -491,23 +473,19 @@ void ui_block_bounds_calc(uiBlock *block)
static void ui_block_bounds_calc_centered(wmWindow *window, uiBlock *block)
{
- int xmax, ymax;
- int startx, starty;
- int width, height;
-
/* note: this is used for the splash where window bounds event has not been
* updated by ghost, get the window bounds from ghost directly */
- xmax = WM_window_pixels_x(window);
- ymax = WM_window_pixels_y(window);
+ int xmax = WM_window_pixels_x(window);
+ int ymax = WM_window_pixels_y(window);
ui_block_bounds_calc(block);
- width = BLI_rctf_size_x(&block->rect);
- height = BLI_rctf_size_y(&block->rect);
+ int width = BLI_rctf_size_x(&block->rect);
+ int height = BLI_rctf_size_y(&block->rect);
- startx = (xmax * 0.5f) - (width * 0.5f);
- starty = (ymax * 0.5f) - (height * 0.5f);
+ int startx = (xmax * 0.5f) - (width * 0.5f);
+ int starty = (ymax * 0.5f) - (height * 0.5f);
UI_block_translate(block, startx - block->rect.xmin, starty - block->rect.ymin);
@@ -531,22 +509,16 @@ static void ui_block_bounds_calc_centered_pie(uiBlock *block)
static void ui_block_bounds_calc_popup(
wmWindow *window, uiBlock *block, eBlockBoundsCalc bounds_calc, const int xy[2], int r_xy[2])
{
- int width, height, oldwidth, oldheight;
- int oldbounds, xmax, ymax, raw_x, raw_y;
- const int margin = UI_SCREEN_MARGIN;
- rcti rect, rect_bounds;
- int ofs_dummy[2];
-
- oldbounds = block->bounds;
+ int oldbounds = block->bounds;
/* compute mouse position with user defined offset */
ui_block_bounds_calc(block);
- xmax = WM_window_pixels_x(window);
- ymax = WM_window_pixels_y(window);
+ int xmax = WM_window_pixels_x(window);
+ int ymax = WM_window_pixels_y(window);
- oldwidth = BLI_rctf_size_x(&block->rect);
- oldheight = BLI_rctf_size_y(&block->rect);
+ int oldwidth = BLI_rctf_size_x(&block->rect);
+ int oldheight = BLI_rctf_size_y(&block->rect);
/* first we ensure wide enough text bounds */
if (bounds_calc == UI_BLOCK_BOUNDS_POPUP_MENU) {
@@ -561,8 +533,8 @@ static void ui_block_bounds_calc_popup(
ui_block_bounds_calc(block);
/* and we adjust the position to fit within window */
- width = BLI_rctf_size_x(&block->rect);
- height = BLI_rctf_size_y(&block->rect);
+ int width = BLI_rctf_size_x(&block->rect);
+ int height = BLI_rctf_size_y(&block->rect);
/* avoid divide by zero below, caused by calling with no UI, but better not crash */
oldwidth = oldwidth > 0 ? oldwidth : MAX2(1, width);
@@ -570,16 +542,21 @@ static void ui_block_bounds_calc_popup(
/* offset block based on mouse position, user offset is scaled
* along in case we resized the block in ui_block_bounds_calc_text */
- raw_x = rect.xmin = xy[0] + block->rect.xmin + (block->bounds_offset[0] * width) / oldwidth;
- raw_y = rect.ymin = xy[1] + block->rect.ymin + (block->bounds_offset[1] * height) / oldheight;
+ rcti rect;
+ int raw_x = rect.xmin = xy[0] + block->rect.xmin + (block->bounds_offset[0] * width) / oldwidth;
+ int raw_y = rect.ymin = xy[1] + block->rect.ymin +
+ (block->bounds_offset[1] * height) / oldheight;
rect.xmax = rect.xmin + width;
rect.ymax = rect.ymin + height;
+ rcti rect_bounds;
+ const int margin = UI_SCREEN_MARGIN;
rect_bounds.xmin = margin;
rect_bounds.ymin = margin;
rect_bounds.xmax = xmax - margin;
rect_bounds.ymax = ymax - UI_POPUP_MENU_TOP;
+ int ofs_dummy[2];
BLI_rcti_clamp(&rect, &rect_bounds, ofs_dummy);
UI_block_translate(block, rect.xmin - block->rect.xmin, rect.ymin - block->rect.ymin);
@@ -634,12 +611,10 @@ void UI_block_bounds_set_menu(uiBlock *block, int addval, const int bounds_offse
block->bounds = addval;
block->bounds_type = UI_BLOCK_BOUNDS_POPUP_MENU;
if (bounds_offset != NULL) {
- block->bounds_offset[0] = bounds_offset[0];
- block->bounds_offset[1] = bounds_offset[1];
+ copy_v2_v2_int(block->bounds_offset, bounds_offset);
}
else {
- block->bounds_offset[0] = 0;
- block->bounds_offset[1] = 0;
+ zero_v2_int(block->bounds_offset);
}
}
@@ -746,25 +721,22 @@ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new)
{
- uiBut *but_old = NULL;
LISTBASE_FOREACH (uiBut *, but, &block_old->buttons) {
if (ui_but_equals_old(but_new, but)) {
- but_old = but;
- break;
+ return but;
}
}
- return but_old;
+ return NULL;
}
+
uiBut *ui_but_find_new(uiBlock *block_new, const uiBut *but_old)
{
- uiBut *but_new = NULL;
LISTBASE_FOREACH (uiBut *, but, &block_new->buttons) {
if (ui_but_equals_old(but, but_old)) {
- but_new = but;
- break;
+ return but;
}
}
- return but_new;
+ return NULL;
}
static bool ui_but_extra_icons_equals_old(const uiButExtraOpIcon *new_extra_icon,
@@ -960,16 +932,14 @@ static bool ui_but_update_from_old_block(const bContext *C,
bool UI_but_active_only_ex(
const bContext *C, ARegion *region, uiBlock *block, uiBut *but, const bool remove_on_failure)
{
- uiBlock *oldblock;
- uiBut *oldbut;
bool activate = false, found = false, isactive = false;
- oldblock = block->oldblock;
+ uiBlock *oldblock = block->oldblock;
if (!oldblock) {
activate = true;
}
else {
- oldbut = ui_but_find_old(oldblock, but);
+ uiBut *oldbut = ui_but_find_old(oldblock, but);
if (oldbut) {
found = true;
@@ -1077,8 +1047,8 @@ static void ui_menu_block_set_keyaccels(uiBlock *block)
}
for (int pass = 0; pass < 2; pass++) {
- /* 2 Passes, on for first letter only, second for any letter if first fails
- * fun first pass on all buttons so first word chars always get first priority */
+ /* 2 Passes: One for first letter only, second for any letter if the first pass fails.
+ * Run first pass on all buttons so first word chars always get first priority. */
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
if (!ELEM(but->type,
@@ -1090,48 +1060,53 @@ static void ui_menu_block_set_keyaccels(uiBlock *block)
/* For PIE-menus. */
UI_BTYPE_ROW) ||
(but->flag & UI_HIDDEN)) {
- /* pass */
+ continue;
}
- else if (but->menu_key == '\0') {
- if (but->str && but->str[0]) {
- const char *str_pt = but->str;
- uchar menu_key;
- do {
- menu_key = tolower(*str_pt);
- if ((menu_key >= 'a' && menu_key <= 'z') && !(menu_key_mask & 1 << (menu_key - 'a'))) {
- menu_key_mask |= 1 << (menu_key - 'a');
- break;
- }
- if (pass == 0) {
- /* Skip to next delimiter on first pass (be picky) */
- while (isalpha(*str_pt)) {
- str_pt++;
- }
+ if (but->menu_key != '\0') {
+ continue;
+ }
- if (*str_pt) {
- str_pt++;
- }
- }
- else {
- /* just step over every char second pass and find first usable key */
- str_pt++;
- }
- } while (*str_pt);
+ if (but->str == NULL || but->str[0] == '\0') {
+ continue;
+ }
- if (*str_pt) {
- but->menu_key = menu_key;
- }
- else {
- /* run second pass */
- tot_missing++;
+ const char *str_pt = but->str;
+ uchar menu_key;
+ do {
+ menu_key = tolower(*str_pt);
+ if ((menu_key >= 'a' && menu_key <= 'z') && !(menu_key_mask & 1 << (menu_key - 'a'))) {
+ menu_key_mask |= 1 << (menu_key - 'a');
+ break;
+ }
+
+ if (pass == 0) {
+ /* Skip to next delimiter on first pass (be picky) */
+ while (isalpha(*str_pt)) {
+ str_pt++;
}
- /* if all keys have been used just exit, unlikely */
- if (menu_key_mask == (1 << 26) - 1) {
- return;
+ if (*str_pt) {
+ str_pt++;
}
}
+ else {
+ /* just step over every char second pass and find first usable key */
+ str_pt++;
+ }
+ } while (*str_pt);
+
+ if (*str_pt) {
+ but->menu_key = menu_key;
+ }
+ else {
+ /* run second pass */
+ tot_missing++;
+ }
+
+ /* if all keys have been used just exit, unlikely */
+ if (menu_key_mask == (1 << 26) - 1) {
+ return;
}
}
@@ -1156,23 +1131,24 @@ void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_str
}
/* without this, just allow stripping of the shortcut */
- if (shortcut_str) {
- char *butstr_orig;
+ if (shortcut_str == NULL) {
+ return;
+ }
- if (but->str != but->strdata) {
- butstr_orig = but->str; /* free after using as source buffer */
- }
- else {
- butstr_orig = BLI_strdup(but->str);
- }
- BLI_snprintf(
- but->strdata, sizeof(but->strdata), "%s" UI_SEP_CHAR_S "%s", butstr_orig, shortcut_str);
- MEM_freeN(butstr_orig);
- but->str = but->strdata;
- but->flag |= UI_BUT_HAS_SEP_CHAR;
- but->drawflag |= UI_BUT_HAS_SHORTCUT;
- ui_but_update(but);
+ char *butstr_orig;
+ if (but->str != but->strdata) {
+ butstr_orig = but->str; /* free after using as source buffer */
}
+ else {
+ butstr_orig = BLI_strdup(but->str);
+ }
+ BLI_snprintf(
+ but->strdata, sizeof(but->strdata), "%s" UI_SEP_CHAR_S "%s", butstr_orig, shortcut_str);
+ MEM_freeN(butstr_orig);
+ but->str = but->strdata;
+ but->flag |= UI_BUT_HAS_SEP_CHAR;
+ but->drawflag |= UI_BUT_HAS_SHORTCUT;
+ ui_but_update(but);
}
/* -------------------------------------------------------------------- */
@@ -1207,11 +1183,10 @@ static bool ui_but_event_operator_string_from_menu(const bContext *C,
BLI_assert(mt != NULL);
bool found = false;
- IDProperty *prop_menu;
/* annoying, create a property */
const IDPropertyTemplate val = {0};
- prop_menu = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */
+ IDProperty *prop_menu = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */
IDP_AddToGroup(prop_menu, IDP_NewString(mt->idname, "name", sizeof(mt->idname)));
if (WM_key_event_operator_string(
@@ -1233,11 +1208,10 @@ static bool ui_but_event_operator_string_from_panel(const bContext *C,
BLI_assert(pt != NULL);
bool found = false;
- IDProperty *prop_panel;
/* annoying, create a property */
const IDPropertyTemplate val = {0};
- prop_panel = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */
+ IDProperty *prop_panel = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */
IDP_AddToGroup(prop_panel, IDP_NewString(pt->idname, "name", sizeof(pt->idname)));
IDP_AddToGroup(prop_panel,
IDP_New(IDP_INT,
@@ -1354,72 +1328,75 @@ static bool ui_but_event_property_operator_string(const bContext *C,
/* Don't use the button again. */
but = NULL;
+ if (prop == NULL) {
+ return NULL;
+ }
+
/* this version is only for finding hotkeys for properties
* (which get set via context using operators) */
- if (prop) {
- /* to avoid massive slowdowns on property panels, for now, we only check the
- * hotkeys for Editor / Scene settings...
- *
- * TODO: userpref settings?
- */
- char *data_path = NULL;
+ /* to avoid massive slowdowns on property panels, for now, we only check the
+ * hotkeys for Editor / Scene settings...
+ *
+ * TODO: userpref settings?
+ */
+ char *data_path = NULL;
- if (ptr->owner_id) {
- ID *id = ptr->owner_id;
+ if (ptr->owner_id) {
+ ID *id = ptr->owner_id;
- if (GS(id->name) == ID_SCR) {
- /* screen/editor property
- * NOTE: in most cases, there is actually no info for backwards tracing
- * how to get back to ID from the editor data we may be dealing with
- */
- if (RNA_struct_is_a(ptr->type, &RNA_Space)) {
- /* data should be directly on here... */
- data_path = BLI_sprintfN("space_data.%s", RNA_property_identifier(prop));
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Area)) {
- /* data should be directly on here... */
- const char *prop_id = RNA_property_identifier(prop);
- /* Hack since keys access 'type', UI shows 'ui_type'. */
- if (STREQ(prop_id, "ui_type")) {
- prop_id = "type";
- prop_enum_value >>= 16;
- prop = RNA_struct_find_property(ptr, prop_id);
-
- opnames = ctx_enum_opnames_for_Area_ui_type;
- opnames_len = ARRAY_SIZE(ctx_enum_opnames_for_Area_ui_type);
- prop_enum_value_id = "space_type";
- prop_enum_value_is_int = true;
- }
- else {
- data_path = BLI_sprintfN("area.%s", prop_id);
- }
+ if (GS(id->name) == ID_SCR) {
+ /* screen/editor property
+ * NOTE: in most cases, there is actually no info for backwards tracing
+ * how to get back to ID from the editor data we may be dealing with
+ */
+ if (RNA_struct_is_a(ptr->type, &RNA_Space)) {
+ /* data should be directly on here... */
+ data_path = BLI_sprintfN("space_data.%s", RNA_property_identifier(prop));
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Area)) {
+ /* data should be directly on here... */
+ const char *prop_id = RNA_property_identifier(prop);
+ /* Hack since keys access 'type', UI shows 'ui_type'. */
+ if (STREQ(prop_id, "ui_type")) {
+ prop_id = "type";
+ prop_enum_value >>= 16;
+ prop = RNA_struct_find_property(ptr, prop_id);
+
+ opnames = ctx_enum_opnames_for_Area_ui_type;
+ opnames_len = ARRAY_SIZE(ctx_enum_opnames_for_Area_ui_type);
+ prop_enum_value_id = "space_type";
+ prop_enum_value_is_int = true;
}
else {
- /* special exceptions for common nested data in editors... */
- if (RNA_struct_is_a(ptr->type, &RNA_DopeSheet)) {
- /* dopesheet filtering options... */
- data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(prop));
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_FileSelectParams)) {
- /* Filebrowser options... */
- data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(prop));
- }
+ data_path = BLI_sprintfN("area.%s", prop_id);
}
}
- else if (GS(id->name) == ID_SCE) {
- if (RNA_struct_is_a(ptr->type, &RNA_ToolSettings)) {
- /* Tool-settings property:
- * NOTE: tool-settings is usually accessed directly (i.e. not through scene). */
- data_path = RNA_path_from_ID_to_property(ptr, prop);
+ else {
+ /* special exceptions for common nested data in editors... */
+ if (RNA_struct_is_a(ptr->type, &RNA_DopeSheet)) {
+ /* dopesheet filtering options... */
+ data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(prop));
}
- else {
- /* scene property */
- char *path = RNA_path_from_ID_to_property(ptr, prop);
+ else if (RNA_struct_is_a(ptr->type, &RNA_FileSelectParams)) {
+ /* Filebrowser options... */
+ data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(prop));
+ }
+ }
+ }
+ else if (GS(id->name) == ID_SCE) {
+ if (RNA_struct_is_a(ptr->type, &RNA_ToolSettings)) {
+ /* Tool-settings property:
+ * NOTE: tool-settings is usually accessed directly (i.e. not through scene). */
+ data_path = RNA_path_from_ID_to_property(ptr, prop);
+ }
+ else {
+ /* scene property */
+ char *path = RNA_path_from_ID_to_property(ptr, prop);
- if (path) {
- data_path = BLI_sprintfN("scene.%s", path);
- MEM_freeN(path);
- }
+ if (path) {
+ data_path = BLI_sprintfN("scene.%s", path);
+ MEM_freeN(path);
+ }
#if 0
else {
printf("ERROR in %s(): Couldn't get path for scene property - %s\n",
@@ -1427,69 +1404,68 @@ static bool ui_but_event_property_operator_string(const bContext *C,
RNA_property_identifier(prop));
}
#endif
- }
}
- else {
- // puts("other id");
- }
-
- // printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(prop), data_path);
- }
-
- /* we have a datapath! */
- if (data_path || (prop_enum_value_ok && prop_enum_value_id)) {
- /* create a property to host the "datapath" property we're sending to the operators */
- IDProperty *prop_path;
-
- const IDPropertyTemplate val = {0};
- prop_path = IDP_New(IDP_GROUP, &val, __func__);
- if (data_path) {
- IDP_AddToGroup(prop_path, IDP_NewString(data_path, "data_path", strlen(data_path) + 1));
- }
- if (prop_enum_value_ok) {
- const EnumPropertyItem *item;
- bool free;
- RNA_property_enum_items((bContext *)C, ptr, prop, &item, NULL, &free);
- const int index = RNA_enum_from_value(item, prop_enum_value);
- if (index != -1) {
- IDProperty *prop_value;
- if (prop_enum_value_is_int) {
- const int value = item[index].value;
- prop_value = IDP_New(IDP_INT,
- &(IDPropertyTemplate){
- .i = value,
- },
- prop_enum_value_id);
- }
- else {
- const char *id = item[index].identifier;
- prop_value = IDP_NewString(id, prop_enum_value_id, strlen(id) + 1);
- }
- IDP_AddToGroup(prop_path, prop_value);
+ }
+ else {
+ // puts("other id");
+ }
+
+ // printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(prop), data_path);
+ }
+
+ /* we have a datapath! */
+ if (data_path || (prop_enum_value_ok && prop_enum_value_id)) {
+ /* create a property to host the "datapath" property we're sending to the operators */
+ IDProperty *prop_path;
+
+ const IDPropertyTemplate val = {0};
+ prop_path = IDP_New(IDP_GROUP, &val, __func__);
+ if (data_path) {
+ IDP_AddToGroup(prop_path, IDP_NewString(data_path, "data_path", strlen(data_path) + 1));
+ }
+ if (prop_enum_value_ok) {
+ const EnumPropertyItem *item;
+ bool free;
+ RNA_property_enum_items((bContext *)C, ptr, prop, &item, NULL, &free);
+ const int index = RNA_enum_from_value(item, prop_enum_value);
+ if (index != -1) {
+ IDProperty *prop_value;
+ if (prop_enum_value_is_int) {
+ const int value = item[index].value;
+ prop_value = IDP_New(IDP_INT,
+ &(IDPropertyTemplate){
+ .i = value,
+ },
+ prop_enum_value_id);
}
else {
- opnames_len = 0; /* Do nothing. */
- }
- if (free) {
- MEM_freeN((void *)item);
+ const char *id = item[index].identifier;
+ prop_value = IDP_NewString(id, prop_enum_value_id, strlen(id) + 1);
}
+ IDP_AddToGroup(prop_path, prop_value);
}
+ else {
+ opnames_len = 0; /* Do nothing. */
+ }
+ if (free) {
+ MEM_freeN((void *)item);
+ }
+ }
- /* check each until one works... */
+ /* check each until one works... */
- for (int i = 0; (i < opnames_len) && (opnames[i]); i++) {
- if (WM_key_event_operator_string(
- C, opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false, buf, buf_len)) {
- found = true;
- break;
- }
+ for (int i = 0; (i < opnames_len) && (opnames[i]); i++) {
+ if (WM_key_event_operator_string(
+ C, opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false, buf, buf_len)) {
+ found = true;
+ break;
}
+ }
- /* cleanup */
- IDP_FreeProperty(prop_path);
- if (data_path) {
- MEM_freeN(data_path);
- }
+ /* cleanup */
+ IDP_FreeProperty(prop_path);
+ if (data_path) {
+ MEM_freeN(data_path);
}
}
@@ -1689,17 +1665,14 @@ static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but)
static bool ui_but_icon_extra_is_visible_search_eyedropper(uiBut *but)
{
- StructRNA *type;
- short idcode;
-
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_VALUE_CLEAR));
if (but->rnaprop == NULL) {
return false;
}
- type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
- idcode = RNA_type_to_ID_code(type);
+ StructRNA *type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+ short idcode = RNA_type_to_ID_code(type);
return ((but->editstr == NULL) && (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode)));
}
@@ -1786,13 +1759,11 @@ static void ui_but_predefined_extra_operator_icons_add(uiBut *but)
void UI_block_update_from_old(const bContext *C, uiBlock *block)
{
- uiBut *but_old;
-
if (!block->oldblock) {
return;
}
- but_old = block->oldblock->buttons.first;
+ uiBut *but_old = block->oldblock->buttons.first;
if (BLI_listbase_is_empty(&block->oldblock->butstore) == false) {
UI_butstore_update(block);
@@ -1977,11 +1948,9 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *region, uiBlock *bloc
void UI_block_draw(const bContext *C, uiBlock *block)
{
uiStyle style = *UI_style_get_dpi(); /* XXX pass on as arg */
- ARegion *region;
- rcti rect;
/* get menu region or area region */
- region = CTX_wm_menu(C);
+ ARegion *region = CTX_wm_menu(C);
if (!region) {
region = CTX_wm_region(C);
}
@@ -2000,6 +1969,7 @@ void UI_block_draw(const bContext *C, uiBlock *block)
ui_fontscale(&style.widget.points, block->aspect);
/* scale block min/max to rect */
+ rcti rect;
ui_but_to_pixelrect(&rect, region, block, NULL);
/* pixel space for AA widgets */
@@ -2234,15 +2204,12 @@ void UI_block_lock_clear(uiBlock *block)
/* for buttons pointing to color for example */
void ui_but_v3_get(uiBut *but, float vec[3])
{
- PropertyRNA *prop;
- int a;
-
if (but->editvec) {
copy_v3_v3(vec, but->editvec);
}
if (but->rnaprop) {
- prop = but->rnaprop;
+ PropertyRNA *prop = but->rnaprop;
zero_v3(vec);
@@ -2254,7 +2221,7 @@ void ui_but_v3_get(uiBut *but, float vec[3])
}
else {
tot = min_ii(tot, 3);
- for (a = 0; a < tot; a++) {
+ for (int a = 0; a < tot; a++) {
vec[a] = RNA_property_float_get_index(&but->rnapoin, prop, a);
}
}
@@ -2286,14 +2253,12 @@ void ui_but_v3_get(uiBut *but, float vec[3])
/* for buttons pointing to color for example */
void ui_but_v3_set(uiBut *but, const float vec[3])
{
- PropertyRNA *prop;
-
if (but->editvec) {
copy_v3_v3(but->editvec, vec);
}
if (but->rnaprop) {
- prop = but->rnaprop;
+ PropertyRNA *prop = but->rnaprop;
if (RNA_property_type(prop) == PROP_FLOAT) {
int tot;
@@ -2440,7 +2405,6 @@ bool ui_but_supports_cycling(const uiBut *but)
double ui_but_value_get(uiBut *but)
{
- PropertyRNA *prop;
double value = 0.0;
if (but->editval) {
@@ -2451,7 +2415,7 @@ double ui_but_value_get(uiBut *but)
}
if (but->rnaprop) {
- prop = but->rnaprop;
+ PropertyRNA *prop = but->rnaprop;
BLI_assert(but->rnaindex != -1);
@@ -2506,11 +2470,9 @@ double ui_but_value_get(uiBut *but)
void ui_but_value_set(uiBut *but, double value)
{
- PropertyRNA *prop;
-
/* value is a hsv value: convert to rgb */
if (but->rnaprop) {
- prop = but->rnaprop;
+ PropertyRNA *prop = but->rnaprop;
if (RNA_property_editable(&but->rnapoin, prop)) {
switch (RNA_property_type(prop)) {
@@ -2642,17 +2604,19 @@ static double ui_get_but_scale_unit(uiBut *but, double value)
/* str will be overwritten */
void ui_but_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen)
{
- if (ui_but_is_unit(but)) {
- UnitSettings *unit = but->block->unit;
- const int unit_type = UI_but_unit_type_get(but);
- char *orig_str;
+ if (!ui_but_is_unit(but)) {
+ return;
+ }
- orig_str = BLI_strdup(str);
+ UnitSettings *unit = but->block->unit;
+ const int unit_type = UI_but_unit_type_get(but);
+ char *orig_str;
- BKE_unit_name_to_alt(str, maxlen, orig_str, unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type));
+ orig_str = BLI_strdup(str);
- MEM_freeN(orig_str);
- }
+ BKE_unit_name_to_alt(str, maxlen, orig_str, unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type));
+
+ MEM_freeN(orig_str);
}
/**
@@ -2703,29 +2667,30 @@ static float ui_get_but_step_unit(uiBut *but, float step_default)
const double step = BKE_unit_closest_scalar(scale_step, but->block->unit->system, unit_type);
/* -1 is an error value */
- if (step != -1.0) {
- const double scale_unit = ui_get_but_scale_unit(but, 1.0);
- const double step_unit = BKE_unit_closest_scalar(
- scale_unit, but->block->unit->system, unit_type);
- double step_final;
-
- BLI_assert(step > 0.0);
-
- step_final = (step / scale_unit) / (double)UI_PRECISION_FLOAT_SCALE;
-
- if (step == step_unit) {
- /* Logic here is to scale by the original 'step_orig'
- * only when the unit step matches the scaled step.
- *
- * This is needed for units that don't have a wide range of scales (degrees for eg.).
- * Without this we can't select between a single degree, or a 10th of a degree.
- */
- step_final *= step_orig;
- }
+ if (step == -1.0f) {
+ return step_default;
+ }
+
+ const double scale_unit = ui_get_but_scale_unit(but, 1.0);
+ const double step_unit = BKE_unit_closest_scalar(
+ scale_unit, but->block->unit->system, unit_type);
+ double step_final;
- return (float)step_final;
+ BLI_assert(step > 0.0);
+
+ step_final = (step / scale_unit) / (double)UI_PRECISION_FLOAT_SCALE;
+
+ if (step == step_unit) {
+ /* Logic here is to scale by the original 'step_orig'
+ * only when the unit step matches the scaled step.
+ *
+ * This is needed for units that don't have a wide range of scales (degrees for eg.).
+ * Without this we can't select between a single degree, or a 10th of a degree.
+ */
+ step_final *= step_orig;
}
- return step_default;
+
+ return (float)step_final;
}
/**
@@ -2746,12 +2711,10 @@ void ui_but_string_get_ex(uiBut *but,
}
if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_TAB)) {
- PropertyType type;
- const char *buf = NULL;
- int buf_len;
-
- type = RNA_property_type(but->rnaprop);
+ PropertyType type = RNA_property_type(but->rnaprop);
+ int buf_len;
+ const char *buf = NULL;
if ((but->type == UI_BTYPE_TAB) && (but->custom_data)) {
StructRNA *ptr_type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
PointerRNA ptr;
@@ -2807,9 +2770,7 @@ void ui_but_string_get_ex(uiBut *but,
}
else {
/* number editing */
- double value;
-
- value = ui_but_value_get(but);
+ double value = ui_but_value_get(but);
PropertySubType subtype = PROP_NONE;
if (but->rnaprop) {
@@ -2875,9 +2836,7 @@ char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size)
*r_str_size = 1;
if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
- PropertyType type;
-
- type = RNA_property_type(but->rnaprop);
+ PropertyType type = RNA_property_type(but->rnaprop);
if (type == PROP_STRING) {
/* RNA string */
@@ -3044,9 +3003,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
{
if (but->rnaprop && but->rnapoin.data && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
if (RNA_property_editable(&but->rnapoin, but->rnaprop)) {
- PropertyType type;
-
- type = RNA_property_type(but->rnaprop);
+ PropertyType type = RNA_property_type(but->rnaprop);
if (type == PROP_STRING) {
/* RNA string */
@@ -3173,8 +3130,7 @@ void ui_but_default_set(bContext *C, const bool all, const bool use_afterfunc)
wmOperatorType *ot = WM_operatortype_find("UI_OT_reset_default_button", true);
if (use_afterfunc) {
- PointerRNA *ptr;
- ptr = ui_handle_afterfunc_add_operator(ot, WM_OP_EXEC_DEFAULT, true);
+ PointerRNA *ptr = ui_handle_afterfunc_add_operator(ot, WM_OP_EXEC_DEFAULT, true);
RNA_boolean_set(ptr, "all", all);
}
else {
@@ -3218,31 +3174,25 @@ static double soft_range_round_down(double value, double max)
void ui_but_range_set_hard(uiBut *but)
{
- if (but->rnaprop) {
- const PropertyType type = RNA_property_type(but->rnaprop);
- double hardmin, hardmax;
-
- /* clamp button range to something reasonable in case
- * we get -inf/inf from RNA properties */
- if (type == PROP_INT) {
- int imin, imax;
+ if (but->rnaprop == NULL) {
+ return;
+ }
- RNA_property_int_range(&but->rnapoin, but->rnaprop, &imin, &imax);
- hardmin = (imin == INT_MIN) ? -1e4 : imin;
- hardmax = (imin == INT_MAX) ? 1e4 : imax;
- }
- else if (type == PROP_FLOAT) {
- float fmin, fmax;
+ const PropertyType type = RNA_property_type(but->rnaprop);
- RNA_property_float_range(&but->rnapoin, but->rnaprop, &fmin, &fmax);
- hardmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin;
- hardmax = (fmax == FLT_MAX) ? (float)1e4 : fmax;
- }
- else {
- return;
- }
- but->hardmin = hardmin;
- but->hardmax = hardmax;
+ /* clamp button range to something reasonable in case
+ * we get -inf/inf from RNA properties */
+ if (type == PROP_INT) {
+ int imin, imax;
+ RNA_property_int_range(&but->rnapoin, but->rnaprop, &imin, &imax);
+ but->hardmin = (imin == INT_MIN) ? -1e4 : imin;
+ but->hardmax = (imin == INT_MAX) ? 1e4 : imax;
+ }
+ else if (type == PROP_FLOAT) {
+ float fmin, fmax;
+ RNA_property_float_range(&but->rnapoin, but->rnaprop, &fmin, &fmax);
+ but->hardmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin;
+ but->hardmax = (fmax == FLT_MAX) ? (float)1e4 : fmax;
}
}
@@ -3424,10 +3374,9 @@ static void ui_but_free(const bContext *C, uiBut *but)
/* can be called with C==NULL */
void UI_block_free(const bContext *C, uiBlock *block)
{
- uiBut *but;
-
UI_butstore_clear(block);
+ uiBut *but;
while ((but = BLI_pophead(&block->buttons))) {
ui_but_free(C, but);
}
@@ -3473,7 +3422,6 @@ void UI_blocklist_draw(const bContext *C, const ListBase *lb)
void UI_blocklist_free(const bContext *C, ListBase *lb)
{
uiBlock *block;
-
while ((block = BLI_pophead(lb))) {
UI_block_free(C, block);
}
@@ -3519,29 +3467,25 @@ void UI_block_region_set(uiBlock *block, ARegion *region)
uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, char emboss)
{
- uiBlock *block;
- wmWindow *window;
- Scene *scn;
-
- window = CTX_wm_window(C);
- scn = CTX_data_scene(C);
+ wmWindow *window = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
- block = MEM_callocN(sizeof(uiBlock), "uiBlock");
+ uiBlock *block = MEM_callocN(sizeof(uiBlock), "uiBlock");
block->active = 1;
block->emboss = emboss;
block->evil_C = (void *)C; /* XXX */
- if (scn) {
+ if (scene) {
/* store display device name, don't lookup for transformations yet
* block could be used for non-color displays where looking up for transformation
* would slow down redraw, so only lookup for actual transform when it's indeed
* needed
*/
- STRNCPY(block->display_device, scn->display_settings.display_device);
+ STRNCPY(block->display_device, scene->display_settings.display_device);
/* copy to avoid crash when scene gets deleted with ui still open */
- block->unit = MEM_mallocN(sizeof(scn->unit), "UI UnitSettings");
- memcpy(block->unit, &scn->unit, sizeof(scn->unit));
+ block->unit = MEM_mallocN(sizeof(scene->unit), "UI UnitSettings");
+ memcpy(block->unit, &scene->unit, sizeof(scene->unit));
}
else {
STRNCPY(block->display_device, IMB_colormanagement_display_get_default_name());
@@ -3759,9 +3703,8 @@ static void ui_but_update_ex(uiBut *but, const bool validate)
case UI_BTYPE_LABEL:
if (ui_but_is_float(but)) {
- int prec;
UI_GET_BUT_VALUE_INIT(but, value);
- prec = ui_but_calc_float_precision(but, value);
+ int prec = ui_but_calc_float_precision(but, value);
BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%.*f", but->str, prec, value);
}
else {
@@ -3952,7 +3895,6 @@ static uiBut *ui_but_alloc(const eButType type)
{
size_t alloc_size;
const char *alloc_str;
-
ui_but_alloc_info(type, &alloc_size, &alloc_str, NULL);
return MEM_callocN(alloc_size, alloc_str);
@@ -4037,9 +3979,6 @@ static uiBut *ui_def_but(uiBlock *block,
float a2,
const char *tip)
{
- uiBut *but;
- int slen;
-
BLI_assert(width >= 0 && height >= 0);
/* we could do some more error checks here */
@@ -4055,7 +3994,7 @@ static uiBut *ui_def_but(uiBlock *block,
}
}
- but = ui_but_alloc(type & BUTTYPE);
+ uiBut *but = ui_but_alloc(type & BUTTYPE);
but->type = type & BUTTYPE;
but->pointype = type & UI_BUT_POIN_TYPES;
@@ -4066,7 +4005,7 @@ static uiBut *ui_def_but(uiBlock *block,
but->retval = retval;
- slen = strlen(str);
+ int slen = strlen(str);
ui_but_string_set_internal(but, str, slen);
but->rect.xmin = x;
@@ -4212,25 +4151,20 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
uiBut *but = (uiBut *)but_p;
/* see comment in ui_item_enum_expand, re: uiname */
- const EnumPropertyItem *item, *item_array;
- bool free;
-
- uiLayout *split, *column = NULL;
-
- int totitems = 0;
- int columns, rows, a, b;
- int column_end = 0;
- int nbr_entries_nosepr = 0;
+ const EnumPropertyItem *item_array;
UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
+ bool free;
RNA_property_enum_items_gettexted(
block->evil_C, &but->rnapoin, but->rnaprop, &item_array, NULL, &free);
/* we dont want nested rows, cols in menus */
UI_block_layout_set_current(block, layout);
- for (item = item_array; item->identifier; item++, totitems++) {
+ int totitems = 0;
+ int nbr_entries_nosepr = 0;
+ for (const EnumPropertyItem *item = item_array; item->identifier; item++, totitems++) {
if (!item->identifier[0]) {
/* inconsistent, but menus with categories do not look good flipped */
if (item->name) {
@@ -4244,7 +4178,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
}
/* Columns and row estimation. Ignore simple separators here. */
- columns = (nbr_entries_nosepr + 20) / 20;
+ int columns = (nbr_entries_nosepr + 20) / 20;
if (columns < 1) {
columns = 1;
}
@@ -4252,7 +4186,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
columns = (nbr_entries_nosepr + 25) / 25;
}
- rows = totitems / columns;
+ int rows = totitems / columns;
if (rows < 1) {
rows = 1;
}
@@ -4282,16 +4216,18 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
/* note, item_array[...] is reversed on access */
/* create items */
- split = uiLayoutSplit(layout, 0.0f, false);
+ uiLayout *split = uiLayoutSplit(layout, 0.0f, false);
- for (a = 0; a < totitems; a++) {
+ int column_end = 0;
+ uiLayout *column = NULL;
+ for (int a = 0; a < totitems; a++) {
if (a == column_end) {
/* start new column, and find out where it ends in advance, so we
* can flip the order of items properly per column */
column_end = totitems;
- for (b = a + 1; b < totitems; b++) {
- item = &item_array[b];
+ for (int b = a + 1; b < totitems; b++) {
+ const EnumPropertyItem *item = &item_array[b];
/* new column on N rows or on separation label */
if (((b - a) % rows == 0) || (!item->identifier[0] && item->name)) {
@@ -4303,7 +4239,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
column = uiLayoutColumn(split, false);
}
- item = &item_array[a];
+ const EnumPropertyItem *item = &item_array[a];
if (!item->identifier[0]) {
if (item->name) {
@@ -4483,7 +4419,6 @@ static uiBut *ui_def_but_rna(uiBlock *block,
const char *tip)
{
const PropertyType proptype = RNA_property_type(prop);
- uiBut *but;
int icon = 0;
uiMenuCreateFunc func = NULL;
const bool always_set_a1_a2 = ELEM(type, UI_BTYPE_NUM);
@@ -4494,14 +4429,12 @@ static uiBut *ui_def_but_rna(uiBlock *block,
/* use rna values if parameters are not specified */
if ((proptype == PROP_ENUM) && ELEM(type, UI_BTYPE_MENU, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) {
- /* UI_BTYPE_MENU is handled a little differently here */
- const EnumPropertyItem *item;
- int value;
bool free;
- int i;
-
+ const EnumPropertyItem *item;
RNA_property_enum_items(block->evil_C, ptr, prop, &item, NULL, &free);
+ int value;
+ /* UI_BTYPE_MENU is handled a little differently here */
if (type == UI_BTYPE_MENU) {
value = RNA_property_enum_get(ptr, prop);
}
@@ -4509,7 +4442,7 @@ static uiBut *ui_def_but_rna(uiBlock *block,
value = (int)max;
}
- i = RNA_enum_from_value(item, value);
+ int i = RNA_enum_from_value(item, value);
if (i != -1) {
if (!str) {
@@ -4594,7 +4527,8 @@ static uiBut *ui_def_but_rna(uiBlock *block,
}
/* now create button */
- but = ui_def_but(block, type, retval, str, x, y, width, height, NULL, min, max, a1, a2, tip);
+ uiBut *but = ui_def_but(
+ block, type, retval, str, x, y, width, height, NULL, min, max, a1, a2, tip);
if (but->type == UI_BTYPE_NUM) {
/* Set default values, can be overriden later. */
@@ -4674,8 +4608,8 @@ static uiBut *ui_def_but_rna_propname(uiBlock *block,
const char *tip)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- uiBut *but;
+ uiBut *but;
if (prop) {
but = ui_def_but_rna(
block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
@@ -4701,8 +4635,6 @@ static uiBut *ui_def_but_operator_ptr(uiBlock *block,
short height,
const char *tip)
{
- uiBut *but;
-
if (!str) {
if (ot && ot->srna) {
str = WM_operatortype_name(ot, NULL);
@@ -4716,7 +4648,7 @@ static uiBut *ui_def_but_operator_ptr(uiBlock *block,
tip = RNA_struct_ui_description(ot->srna);
}
- but = ui_def_but(block, type, -1, str, x, y, width, height, NULL, 0, 0, 0, 0, tip);
+ uiBut *but = ui_def_but(block, type, -1, str, x, y, width, height, NULL, 0, 0, 0, 0, tip);
but->optype = ot;
but->opcontext = opcontext;
but->flag &= ~UI_BUT_UNDO; /* no need for ui_but_is_rna_undo(), we never need undo here */
@@ -4856,15 +4788,16 @@ void UI_autocomplete_update_name(AutoComplete *autocpl, const char *name)
{
char *truncate = autocpl->truncate;
const char *startname = autocpl->startname;
- int a;
-
- for (a = 0; a < autocpl->maxlen - 1; a++) {
+ int match_index = 0;
+ for (int a = 0; a < autocpl->maxlen - 1; a++) {
if (startname[a] == 0 || startname[a] != name[a]) {
+ match_index = a;
break;
}
}
+
/* found a match */
- if (startname[a] == 0) {
+ if (startname[match_index] == 0) {
autocpl->matches++;
/* first match */
if (truncate[0] == 0) {
@@ -4872,7 +4805,7 @@ void UI_autocomplete_update_name(AutoComplete *autocpl, const char *name)
}
else {
/* remove from truncate what is not in bone->name */
- for (a = 0; a < autocpl->maxlen - 1; a++) {
+ for (int a = 0; a < autocpl->maxlen - 1; a++) {
if (name[a] == 0) {
truncate[a] = 0;
break;
@@ -5217,8 +5150,7 @@ uiBut *uiDefButR(uiBlock *block,
float a2,
const char *tip)
{
- uiBut *but;
- but = ui_def_but_rna_propname(
+ uiBut *but = ui_def_but_rna_propname(
block, type, retval, str, x, y, width, height, ptr, propname, index, min, max, a1, a2, tip);
ui_but_update(but);
return but;
@@ -5240,8 +5172,7 @@ uiBut *uiDefButR_prop(uiBlock *block,
float a2,
const char *tip)
{
- uiBut *but;
- but = ui_def_but_rna(
+ uiBut *but = ui_def_but_rna(
block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
ui_but_update(but);
return but;
@@ -5258,8 +5189,7 @@ uiBut *uiDefButO_ptr(uiBlock *block,
short height,
const char *tip)
{
- uiBut *but;
- but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
+ uiBut *but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
ui_but_update(but);
return but;
}
@@ -5603,8 +5533,7 @@ uiBut *uiDefIconButR(uiBlock *block,
float a2,
const char *tip)
{
- uiBut *but;
- but = ui_def_but_rna_propname(
+ uiBut *but = ui_def_but_rna_propname(
block, type, retval, "", x, y, width, height, ptr, propname, index, min, max, a1, a2, tip);
ui_but_update_and_icon_set(but, icon);
return but;
@@ -5626,8 +5555,7 @@ uiBut *uiDefIconButR_prop(uiBlock *block,
float a2,
const char *tip)
{
- uiBut *but;
- but = ui_def_but_rna(
+ uiBut *but = ui_def_but_rna(
block, type, retval, "", x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
ui_but_update_and_icon_set(but, icon);
return but;
@@ -5644,8 +5572,7 @@ uiBut *uiDefIconButO_ptr(uiBlock *block,
short height,
const char *tip)
{
- uiBut *but;
- but = ui_def_but_operator_ptr(block, type, ot, opcontext, "", x, y, width, height, tip);
+ uiBut *but = ui_def_but_operator_ptr(block, type, ot, opcontext, "", x, y, width, height, tip);
ui_but_update_and_icon_set(but, icon);
return but;
}
@@ -6007,8 +5934,7 @@ uiBut *uiDefIconTextButR(uiBlock *block,
float a2,
const char *tip)
{
- uiBut *but;
- but = ui_def_but_rna_propname(
+ uiBut *but = ui_def_but_rna_propname(
block, type, retval, str, x, y, width, height, ptr, propname, index, min, max, a1, a2, tip);
ui_but_update_and_icon_set(but, icon);
but->drawflag |= UI_BUT_ICON_LEFT;
@@ -6032,8 +5958,7 @@ uiBut *uiDefIconTextButR_prop(uiBlock *block,
float a2,
const char *tip)
{
- uiBut *but;
- but = ui_def_but_rna(
+ uiBut *but = ui_def_but_rna(
block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
ui_but_update_and_icon_set(but, icon);
but->drawflag |= UI_BUT_ICON_LEFT;
@@ -6051,8 +5976,7 @@ uiBut *uiDefIconTextButO_ptr(uiBlock *block,
short height,
const char *tip)
{
- uiBut *but;
- but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
+ uiBut *but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
ui_but_update_and_icon_set(but, icon);
but->drawflag |= UI_BUT_ICON_LEFT;
return but;
@@ -6820,9 +6744,7 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block,
float a2,
const char *tip)
{
- uiBut *but;
-
- but = uiDefSearchBut(block, arg, retval, icon, maxlen, x, y, width, height, a1, a2, tip);
+ uiBut *but = uiDefSearchBut(block, arg, retval, icon, maxlen, x, y, width, height, a1, a2, tip);
UI_but_func_search_set(but,
ui_searchbox_create_generic,
operator_enum_search_update_fn,
@@ -6876,7 +6798,6 @@ void UI_but_number_precision_set(uiBut *but, float precision)
void UI_but_focus_on_enter_event(wmWindow *win, uiBut *but)
{
wmEvent event;
-
wm_event_init_from_window(win, &event);
event.type = EVT_BUT_OPEN;
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index b9ed1688e80..65415a750bb 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -877,6 +877,11 @@ void UI_panels_set_expansion_from_seach_filter(const bContext *C, ARegion *regio
}
}
+bool UI_panel_is_active(const Panel *panel)
+{
+ return panel->runtime_flag & PANEL_ACTIVE;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 2e9f297b705..7b41b1df0ab 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -450,8 +450,25 @@ void ED_area_do_mgs_subscribe_for_tool_ui(
struct wmMsgBus *mbus)
{
BLI_assert(region->regiontype == RGN_TYPE_UI);
+ const char *panel_category_tool = "Tool";
const char *category = UI_panel_category_active_get(region, false);
- if (category && STREQ(category, "Tool")) {
+
+ bool update_region = false;
+ if (category && STREQ(category, panel_category_tool)) {
+ update_region = true;
+ }
+ else {
+ /* Check if a tool category panel is pinned and visible in another category. */
+ LISTBASE_FOREACH (Panel *, panel, &region->panels) {
+ if (UI_panel_is_active(panel) && panel->flag & PNL_PIN &&
+ STREQ(panel->type->category, panel_category_tool)) {
+ update_region = true;
+ break;
+ }
+ }
+ }
+
+ if (update_region) {
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
.owner = region,
.user_data = region,
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index a1894e1b4c6..175d98ba9aa 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -341,6 +341,7 @@ typedef enum {
void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot);
void PAINT_OT_mask_lasso_gesture(struct wmOperatorType *ot);
void PAINT_OT_mask_box_gesture(struct wmOperatorType *ot);
+void PAINT_OT_mask_line_gesture(struct wmOperatorType *ot);
/* paint_curve.c */
void PAINTCURVE_OT_new(struct wmOperatorType *ot);
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index fc17af8d2cb..0f2ebdd28aa 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -234,6 +234,7 @@ void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot)
typedef enum eSculptGestureShapeType {
SCULPT_GESTURE_SHAPE_BOX,
SCULPT_GESTURE_SHAPE_LASSO,
+ SCULPT_GESTURE_SHAPE_LINE,
} eMaskGesturesShapeType;
typedef struct LassoGestureData {
@@ -246,6 +247,11 @@ typedef struct LassoGestureData {
BLI_bitmap *mask_px;
} LassoGestureData;
+typedef struct LineGestureData {
+ float true_plane[4];
+ float plane[4];
+} LineGestureData;
+
struct SculptGestureOperation;
typedef struct SculptGestureContext {
@@ -280,6 +286,9 @@ typedef struct SculptGestureContext {
/* Lasso Gesture. */
LassoGestureData lasso;
+ /* Line Gesture. */
+ LineGestureData line;
+
/* Task Callback Data. */
PBVHNode **nodes;
int totnode;
@@ -430,6 +439,44 @@ static SculptGestureContext *sculpt_gesture_init_from_box(bContext *C, wmOperato
return sgcontext;
}
+static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperator *op)
+{
+ SculptGestureContext *sgcontext = MEM_callocN(sizeof(SculptGestureContext),
+ "sculpt gesture context line");
+ sgcontext->shape_type = SCULPT_GESTURE_SHAPE_LINE;
+
+ sculpt_gesture_context_init_common(C, op, sgcontext);
+
+ float line_points[2][2];
+ line_points[0][0] = RNA_int_get(op->ptr, "xstart");
+ line_points[0][1] = RNA_int_get(op->ptr, "ystart");
+ line_points[1][0] = RNA_int_get(op->ptr, "xend");
+ line_points[1][1] = RNA_int_get(op->ptr, "yend");
+
+ float depth_point[3];
+ float plane_points[3][3];
+
+ /* Calculate a triangle in the line's plane. */
+ add_v3_v3v3(depth_point, sgcontext->true_view_origin, sgcontext->true_view_normal);
+ ED_view3d_win_to_3d(
+ sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[0], plane_points[0]);
+
+ madd_v3_v3v3fl(depth_point, sgcontext->true_view_origin, sgcontext->true_view_normal, 10.0f);
+ ED_view3d_win_to_3d(
+ sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[0], plane_points[1]);
+ ED_view3d_win_to_3d(
+ sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[1], plane_points[2]);
+
+ /* Calculate final line plane and normal using the triangle. */
+ float normal[3];
+ normal_tri_v3(normal, plane_points[0], plane_points[1], plane_points[2]);
+ if (!sgcontext->vc.rv3d->is_persp) {
+ mul_v3_fl(normal, -1.0f);
+ }
+ plane_from_point_normal_v3(sgcontext->line.true_plane, plane_points[0], normal);
+ return sgcontext;
+}
+
static void sculpt_gesture_context_free(SculptGestureContext *sgcontext)
{
MEM_SAFE_FREE(sgcontext->lasso.mask_px);
@@ -470,12 +517,28 @@ static void sculpt_gesture_flip_for_symmetry_pass(SculptGestureContext *sgcontex
for (int j = 0; j < 4; j++) {
flip_plane(sgcontext->clip_planes[j], sgcontext->true_clip_planes[j], symmpass);
}
+
negate_m4(sgcontext->clip_planes);
+
flip_v3_v3(sgcontext->view_normal, sgcontext->true_view_normal, symmpass);
flip_v3_v3(sgcontext->view_origin, sgcontext->true_view_origin, symmpass);
+ flip_plane(sgcontext->line.plane, sgcontext->line.true_plane, symmpass);
}
-static void sculpt_gesture_update_effected_nodes(SculptGestureContext *sgcontext)
+static void sculpt_gesture_update_effected_nodes_by_line_plane(SculptGestureContext *sgcontext)
+{
+ SculptSession *ss = sgcontext->ss;
+ float clip_planes[1][4];
+ copy_v4_v4(clip_planes[0], sgcontext->line.plane);
+ PBVHFrustumPlanes frustum = {.planes = clip_planes, .num_planes = 1};
+ BKE_pbvh_search_gather(ss->pbvh,
+ BKE_pbvh_node_frustum_contain_AABB,
+ &frustum,
+ &sgcontext->nodes,
+ &sgcontext->totnode);
+}
+
+static void sculpt_gesture_update_effected_nodes_by_clip_planes(SculptGestureContext *sgcontext)
{
SculptSession *ss = sgcontext->ss;
float clip_planes[4][4];
@@ -489,6 +552,19 @@ static void sculpt_gesture_update_effected_nodes(SculptGestureContext *sgcontext
&sgcontext->totnode);
}
+static void sculpt_gesture_update_effected_nodes(SculptGestureContext *sgcontext)
+{
+ switch (sgcontext->shape_type) {
+ case SCULPT_GESTURE_SHAPE_BOX:
+ case SCULPT_GESTURE_SHAPE_LASSO:
+ sculpt_gesture_update_effected_nodes_by_clip_planes(sgcontext);
+ break;
+ case SCULPT_GESTURE_SHAPE_LINE:
+ sculpt_gesture_update_effected_nodes_by_line_plane(sgcontext);
+ break;
+ }
+}
+
static bool sculpt_gesture_is_effected_lasso(SculptGestureContext *sgcontext, const float co[3])
{
float scr_co_f[2];
@@ -532,6 +608,8 @@ static bool sculpt_gesture_is_vertex_effected(SculptGestureContext *sgcontext, P
return isect_point_planes_v3(sgcontext->clip_planes, 4, vd->co);
case SCULPT_GESTURE_SHAPE_LASSO:
return sculpt_gesture_is_effected_lasso(sgcontext, vd->co);
+ case SCULPT_GESTURE_SHAPE_LINE:
+ return plane_point_side_v3(sgcontext->line.plane, vd->co) > 0.0f;
}
return false;
}
@@ -1117,6 +1195,18 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static int paint_mask_gesture_line_exec(bContext *C, wmOperator *op)
+{
+ SculptGestureContext *sgcontext = sculpt_gesture_init_from_line(C, op);
+ if (!sgcontext) {
+ return OPERATOR_CANCELLED;
+ }
+ sculpt_gesture_init_mask_properties(sgcontext, op);
+ sculpt_gesture_apply(C, sgcontext);
+ sculpt_gesture_context_free(sgcontext);
+ return OPERATOR_FINISHED;
+}
+
static int face_set_gesture_box_exec(bContext *C, wmOperator *op)
{
SculptGestureContext *sgcontext = sculpt_gesture_init_from_box(C, op);
@@ -1222,6 +1312,27 @@ void PAINT_OT_mask_box_gesture(wmOperatorType *ot)
paint_mask_gesture_operator_properties(ot);
}
+void PAINT_OT_mask_line_gesture(wmOperatorType *ot)
+{
+ ot->name = "Mask Line Gesture";
+ ot->idname = "PAINT_OT_mask_line_gesture";
+ ot->description = "Add mask to the right of a line as you move the brush";
+
+ ot->invoke = WM_gesture_straightline_invoke;
+ ot->modal = WM_gesture_straightline_oneshot_modal;
+ ot->exec = paint_mask_gesture_line_exec;
+
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER;
+
+ /* Properties. */
+ WM_operator_properties_gesture_straightline(ot, WM_CURSOR_EDIT);
+ sculpt_gesture_operator_properties(ot);
+
+ paint_mask_gesture_operator_properties(ot);
+}
+
void SCULPT_OT_face_set_lasso_gesture(wmOperatorType *ot)
{
ot->name = "Face Set Lasso Gesture";
@@ -1232,10 +1343,6 @@ void SCULPT_OT_face_set_lasso_gesture(wmOperatorType *ot)
ot->modal = WM_gesture_lasso_modal;
ot->exec = face_set_gesture_lasso_exec;
- ot->poll = SCULPT_mode_poll;
-
- ot->flag = OPTYPE_REGISTER;
-
/* Properties. */
WM_operator_properties_gesture_lasso(ot);
sculpt_gesture_operator_properties(ot);
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 43ff03ea7e2..e239b9619ec 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -1357,6 +1357,7 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_mask_flood_fill);
WM_operatortype_append(PAINT_OT_mask_lasso_gesture);
WM_operatortype_append(PAINT_OT_mask_box_gesture);
+ WM_operatortype_append(PAINT_OT_mask_line_gesture);
}
void ED_keymap_paint(wmKeyConfig *keyconf)
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 2e10cc94004..410197da5da 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -68,11 +68,8 @@
static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type)
{
- PointerRNA *ptr;
- int a;
-
- for (a = 0; a < path->len; a++) {
- ptr = &path->ptr[a];
+ for (int i = 0; i < path->len; i++) {
+ PointerRNA *ptr = &path->ptr[i];
if (RNA_struct_is_a(ptr->type, type)) {
CTX_data_pointer_set(result, ptr->owner_id, ptr->type, ptr->data);
@@ -85,11 +82,8 @@ static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, S
static PointerRNA *get_pointer_type(ButsContextPath *path, StructRNA *type)
{
- PointerRNA *ptr;
- int a;
-
- for (a = 0; a < path->len; a++) {
- ptr = &path->ptr[a];
+ for (int i = 0; i < path->len; i++) {
+ PointerRNA *ptr = &path->ptr[i];
if (RNA_struct_is_a(ptr->type, type)) {
return ptr;
@@ -109,14 +103,14 @@ static bool buttons_context_path_scene(ButsContextPath *path)
return RNA_struct_is_a(ptr->type, &RNA_Scene);
}
-static int buttons_context_path_view_layer(ButsContextPath *path, wmWindow *win)
+static bool buttons_context_path_view_layer(ButsContextPath *path, wmWindow *win)
{
PointerRNA *ptr = &path->ptr[path->len - 1];
/* View Layer may have already been resolved in a previous call
* (e.g. in buttons_context_path_linestyle). */
if (RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) {
- return 1;
+ return true;
}
if (buttons_context_path_scene(path)) {
@@ -126,45 +120,42 @@ static int buttons_context_path_view_layer(ButsContextPath *path, wmWindow *win)
RNA_pointer_create(&scene->id, &RNA_ViewLayer, view_layer, &path->ptr[path->len]);
path->len++;
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-/* note: this function can return 1 without adding a world to the path
+/* note: this function can return true without adding a world to the path
* so the buttons stay visible, but be sure to check the ID type if a ID_WO */
-static int buttons_context_path_world(ButsContextPath *path)
+static bool buttons_context_path_world(ButsContextPath *path)
{
- Scene *scene;
- World *world;
PointerRNA *ptr = &path->ptr[path->len - 1];
/* if we already have a (pinned) world, we're done */
if (RNA_struct_is_a(ptr->type, &RNA_World)) {
- return 1;
+ return true;
}
/* if we have a scene, use the scene's world */
if (buttons_context_path_scene(path)) {
- scene = path->ptr[path->len - 1].data;
- world = scene->world;
+ Scene *scene = path->ptr[path->len - 1].data;
+ World *world = scene->world;
if (world) {
RNA_id_pointer_create(&scene->world->id, &path->ptr[path->len]);
path->len++;
- return 1;
+ return true;
}
- return 1;
+ return true;
}
/* no path to a world possible */
- return 0;
+ return false;
}
static bool buttons_context_path_linestyle(ButsContextPath *path, wmWindow *window)
{
- FreestyleLineStyle *linestyle;
PointerRNA *ptr = &path->ptr[path->len - 1];
/* if we already have a (pinned) linestyle, we're done */
@@ -174,7 +165,7 @@ static bool buttons_context_path_linestyle(ButsContextPath *path, wmWindow *wind
/* if we have a view layer, use the lineset's linestyle */
if (buttons_context_path_view_layer(path, window)) {
ViewLayer *view_layer = path->ptr[path->len - 1].data;
- linestyle = BKE_linestyle_active_from_view_layer(view_layer);
+ FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer);
if (linestyle) {
RNA_id_pointer_create(&linestyle->id, &path->ptr[path->len]);
path->len++;
@@ -214,7 +205,6 @@ static bool buttons_context_path_object(ButsContextPath *path)
static bool buttons_context_path_data(ButsContextPath *path, int type)
{
- Object *ob;
PointerRNA *ptr = &path->ptr[path->len - 1];
/* if we already have a data, we're done */
@@ -264,7 +254,7 @@ static bool buttons_context_path_data(ButsContextPath *path, int type)
}
/* try to get an object in the path, no pinning supported here */
if (buttons_context_path_object(path)) {
- ob = path->ptr[path->len - 1].data;
+ Object *ob = path->ptr[path->len - 1].data;
if (ob && (type == -1 || type == ob->type)) {
RNA_id_pointer_create(ob->data, &path->ptr[path->len]);
@@ -280,10 +270,8 @@ static bool buttons_context_path_data(ButsContextPath *path, int type)
static bool buttons_context_path_modifier(ButsContextPath *path)
{
- Object *ob;
-
if (buttons_context_path_object(path)) {
- ob = path->ptr[path->len - 1].data;
+ Object *ob = path->ptr[path->len - 1].data;
if (ob && ELEM(ob->type,
OB_MESH,
@@ -304,10 +292,8 @@ static bool buttons_context_path_modifier(ButsContextPath *path)
static bool buttons_context_path_shaderfx(ButsContextPath *path)
{
- Object *ob;
-
if (buttons_context_path_object(path)) {
- ob = path->ptr[path->len - 1].data;
+ Object *ob = path->ptr[path->len - 1].data;
if (ob && ELEM(ob->type, OB_GPENCIL)) {
return true;
@@ -319,9 +305,7 @@ static bool buttons_context_path_shaderfx(ButsContextPath *path)
static bool buttons_context_path_material(ButsContextPath *path)
{
- Object *ob;
PointerRNA *ptr = &path->ptr[path->len - 1];
- Material *ma;
/* if we already have a (pinned) material, we're done */
if (RNA_struct_is_a(ptr->type, &RNA_Material)) {
@@ -329,10 +313,10 @@ static bool buttons_context_path_material(ButsContextPath *path)
}
/* if we have an object, use the object material slot */
if (buttons_context_path_object(path)) {
- ob = path->ptr[path->len - 1].data;
+ Object *ob = path->ptr[path->len - 1].data;
if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
- ma = BKE_object_material_get(ob, ob->actcol);
+ Material *ma = BKE_object_material_get(ob, ob->actcol);
if (ma != NULL) {
RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
path->len++;
@@ -347,16 +331,13 @@ static bool buttons_context_path_material(ButsContextPath *path)
static bool buttons_context_path_bone(ButsContextPath *path)
{
- bArmature *arm;
- EditBone *edbo;
-
/* if we have an armature, get the active bone */
if (buttons_context_path_data(path, OB_ARMATURE)) {
- arm = path->ptr[path->len - 1].data;
+ bArmature *arm = path->ptr[path->len - 1].data;
if (arm->edbo) {
if (arm->act_edbone) {
- edbo = arm->act_edbone;
+ EditBone *edbo = arm->act_edbone;
RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]);
path->len++;
return true;
@@ -409,8 +390,6 @@ static bool buttons_context_path_pose_bone(ButsContextPath *path)
static bool buttons_context_path_particle(ButsContextPath *path)
{
- Object *ob;
- ParticleSystem *psys;
PointerRNA *ptr = &path->ptr[path->len - 1];
/* if we already have (pinned) particle settings, we're done */
@@ -419,10 +398,10 @@ static bool buttons_context_path_particle(ButsContextPath *path)
}
/* if we have an object, get the active particle system */
if (buttons_context_path_object(path)) {
- ob = path->ptr[path->len - 1].data;
+ Object *ob = path->ptr[path->len - 1].data;
if (ob && ob->type == OB_MESH) {
- psys = psys_get_current(ob);
+ ParticleSystem *psys = psys_get_current(ob);
RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &path->ptr[path->len]);
path->len++;
@@ -436,8 +415,6 @@ static bool buttons_context_path_particle(ButsContextPath *path)
static bool buttons_context_path_brush(const bContext *C, ButsContextPath *path)
{
- Scene *scene;
- Brush *br = NULL;
PointerRNA *ptr = &path->ptr[path->len - 1];
/* if we already have a (pinned) brush, we're done */
@@ -446,8 +423,9 @@ static bool buttons_context_path_brush(const bContext *C, ButsContextPath *path)
}
/* if we have a scene, use the toolsettings brushes */
if (buttons_context_path_scene(path)) {
- scene = path->ptr[path->len - 1].data;
+ Scene *scene = path->ptr[path->len - 1].data;
+ Brush *br = NULL;
if (scene) {
wmWindow *window = CTX_wm_window(C);
ViewLayer *view_layer = WM_window_get_active_view_layer(window);
@@ -471,7 +449,6 @@ static bool buttons_context_path_texture(const bContext *C,
ButsContextTexture *ct)
{
PointerRNA *ptr = &path->ptr[path->len - 1];
- ID *id;
if (!ct) {
return false;
@@ -486,7 +463,7 @@ static bool buttons_context_path_texture(const bContext *C,
return false;
}
- id = ct->user->id;
+ ID *id = ct->user->id;
if (id) {
if (GS(id->name) == ID_BR) {
@@ -516,20 +493,18 @@ static bool buttons_context_linestyle_pinnable(const bContext *C, ViewLayer *vie
{
wmWindow *window = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(window);
- FreestyleConfig *config;
- SpaceProperties *sbuts;
/* if Freestyle is disabled in the scene */
if ((scene->r.mode & R_EDGE_FRS) == 0) {
return false;
}
/* if Freestyle is not in the Parameter Editor mode */
- config = &view_layer->freestyle_config;
+ FreestyleConfig *config = &view_layer->freestyle_config;
if (config->mode != FREESTYLE_CONTROL_EDITOR_MODE) {
return false;
}
/* if the scene has already been pinned */
- sbuts = CTX_wm_space_properties(C);
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
if (sbuts->pinid && sbuts->pinid == &scene->id) {
return false;
}
@@ -545,15 +520,13 @@ static bool buttons_context_path(const bContext *C, ButsContextPath *path, int m
wmWindow *window = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(window);
ViewLayer *view_layer = WM_window_get_active_view_layer(window);
- ID *id;
- int found;
memset(path, 0, sizeof(*path));
path->flag = flag;
/* If some ID datablock is pinned, set the root pointer. */
if (sbuts->pinid) {
- id = sbuts->pinid;
+ ID *id = sbuts->pinid;
RNA_id_pointer_create(id, &path->ptr[0]);
path->len++;
@@ -576,6 +549,7 @@ static bool buttons_context_path(const bContext *C, ButsContextPath *path, int m
/* now for each buttons context type, we try to construct a path,
* tracing back recursively */
+ bool found;
switch (mainb) {
case BCONTEXT_SCENE:
case BCONTEXT_RENDER:
@@ -676,15 +650,14 @@ static int buttons_shading_new_context(const bContext *C, int flag)
void buttons_context_compute(const bContext *C, SpaceProperties *sbuts)
{
- ButsContextPath *path;
- PointerRNA *ptr;
- int a, pflag = 0, flag = 0;
-
if (!sbuts->path) {
sbuts->path = MEM_callocN(sizeof(ButsContextPath), "ButsContextPath");
}
- path = sbuts->path;
+ ButsContextPath *path = sbuts->path;
+
+ int pflag = 0;
+ int flag = 0;
/* Set scene path. */
buttons_context_path(C, path, BCONTEXT_SCENE, pflag);
@@ -693,13 +666,13 @@ void buttons_context_compute(const bContext *C, SpaceProperties *sbuts)
/* for each context, see if we can compute a valid path to it, if
* this is the case, we know we have to display the button */
- for (a = 0; a < BCONTEXT_TOT; a++) {
- if (buttons_context_path(C, path, a, pflag)) {
- flag |= (1 << a);
+ for (int i = 0; i < BCONTEXT_TOT; i++) {
+ if (buttons_context_path(C, path, i, pflag)) {
+ flag |= (1 << i);
/* setting icon for data context */
- if (a == BCONTEXT_DATA) {
- ptr = &path->ptr[path->len - 1];
+ if (i == BCONTEXT_DATA) {
+ PointerRNA *ptr = &path->ptr[path->len - 1];
if (ptr->type) {
if (RNA_struct_is_a(ptr->type, &RNA_Light)) {
@@ -731,9 +704,9 @@ void buttons_context_compute(const bContext *C, SpaceProperties *sbuts)
sbuts->mainb = BCONTEXT_OBJECT;
}
else {
- for (a = 0; a < BCONTEXT_TOT; a++) {
- if (flag & (1 << a)) {
- sbuts->mainb = a;
+ for (int i = 0; i < BCONTEXT_TOT; i++) {
+ if (flag & (1 << i)) {
+ sbuts->mainb = i;
break;
}
}
@@ -1123,24 +1096,19 @@ static bool buttons_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
static void buttons_panel_context_draw(const bContext *C, Panel *panel)
{
- uiLayout *layout = panel->layout;
SpaceProperties *sbuts = CTX_wm_space_properties(C);
ButsContextPath *path = sbuts->path;
- uiLayout *row;
- PointerRNA *ptr;
- char namebuf[128], *name;
- int a, icon;
- bool first = true;
if (!path) {
return;
}
- row = uiLayoutRow(layout, true);
+ uiLayout *row = uiLayoutRow(panel->layout, true);
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
- for (a = 0; a < path->len; a++) {
- ptr = &path->ptr[a];
+ bool first = true;
+ for (int i = 0; i < path->len; i++) {
+ PointerRNA *ptr = &path->ptr[i];
/* Skip scene and view layer to save space. */
if ((!ELEM(sbuts->mainb,
@@ -1166,33 +1134,35 @@ static void buttons_panel_context_draw(const bContext *C, Panel *panel)
if (!first) {
uiItemL(row, "", ICON_SMALL_TRI_RIGHT_VEC);
}
- else {
- first = false;
+
+ if (ptr->data == NULL) {
+ continue;
}
- /* Add icon + name .*/
- if (ptr->data) {
- icon = RNA_struct_ui_icon(ptr->type);
- name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);
+ /* Add icon and name .*/
+ int icon = RNA_struct_ui_icon(ptr->type);
+ char namebuf[128];
+ char *name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);
- if (name) {
- uiItemLDrag(row, ptr, name, icon);
+ if (name) {
+ uiItemLDrag(row, ptr, name, icon);
- if (name != namebuf) {
- MEM_freeN(name);
- }
- }
- else {
- uiItemL(row, "", icon);
+ if (name != namebuf) {
+ MEM_freeN(name);
}
}
+ else {
+ uiItemL(row, "", icon);
+ }
+
+ first = false;
}
}
void buttons_context_register(ARegionType *art)
{
PanelType *pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
- strcpy(pt->idname, "BUTTONS_PT_context");
+ strcpy(pt->idname, "PROPERTIES_PT_context");
strcpy(pt->label, N_("Context")); /* XXX C panels unavailable through RNA bpy.types! */
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->poll = buttons_panel_context_poll;
@@ -1205,32 +1175,32 @@ ID *buttons_context_id_path(const bContext *C)
{
SpaceProperties *sbuts = CTX_wm_space_properties(C);
ButsContextPath *path = sbuts->path;
- PointerRNA *ptr;
- int a;
-
- if (path->len) {
- for (a = path->len - 1; a >= 0; a--) {
- ptr = &path->ptr[a];
-
- /* pin particle settings instead of system, since only settings are an idblock*/
- if (sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) {
- if (ptr->type == &RNA_ParticleSystem && ptr->data) {
- ParticleSystem *psys = ptr->data;
- return &psys->part->id;
- }
- }
- /* There is no valid image ID panel, Image Empty objects need this workaround.*/
- if (sbuts->mainb == BCONTEXT_DATA && sbuts->flag & SB_PIN_CONTEXT) {
- if (ptr->type == &RNA_Image && ptr->data) {
- continue;
- }
+ if (path->len == 0) {
+ return NULL;
+ }
+
+ for (int i = path->len - 1; i >= 0; i--) {
+ PointerRNA *ptr = &path->ptr[i];
+
+ /* pin particle settings instead of system, since only settings are an idblock*/
+ if (sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) {
+ if (ptr->type == &RNA_ParticleSystem && ptr->data) {
+ ParticleSystem *psys = ptr->data;
+ return &psys->part->id;
}
+ }
- if (ptr->owner_id) {
- return ptr->owner_id;
+ /* There is no valid image ID panel, Image Empty objects need this workaround.*/
+ if (sbuts->mainb == BCONTEXT_DATA && sbuts->flag & SB_PIN_CONTEXT) {
+ if (ptr->type == &RNA_Image && ptr->data) {
+ continue;
}
}
+
+ if (ptr->owner_id) {
+ return ptr->owner_id;
+ }
}
return NULL;
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index eb2969aa15d..a4043d426a3 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -1448,7 +1448,7 @@ static const EnumPropertyItem prop_object_op_types[] = {
"OBJECT_PROXY_TO_OVERRIDE",
0,
"Convert Proxy to Override",
- "Convert a Proxy object to a full library override, inclduing all its dependencies"},
+ "Convert a Proxy object to a full library override, including all its dependencies"},
{0, NULL, 0, NULL, NULL},
};
@@ -1739,7 +1739,7 @@ static const EnumPropertyItem prop_id_op_types[] = {
"OVERRIDE_LIBRARY_PROXY_CONVERT",
0,
"Convert Proxy to Override",
- "Convert a Proxy object to a full library override, inclduing all its dependencies"},
+ "Convert a Proxy object to a full library override, including all its dependencies"},
{OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
"OVERRIDE_LIBRARY_RESET",
0,
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index bc08cb91c0d..7ed276e45de 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -755,26 +755,26 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, bool is
stopConstraint(t);
}
else {
- setUserConstraint(t, V3D_ORIENT_GLOBAL, constraint_axis, msg1);
+ setUserConstraint(t, constraint_axis, msg1);
}
}
else if (!edit_2d) {
+ short orient_index = 1;
if (t->orient_curr == 0 || ELEM(cmode, '\0', axis)) {
/* Successive presses on existing axis, cycle orientation modes. */
- t->orient_curr = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient));
- transform_orientations_current_set(t, t->orient_curr);
+ orient_index = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient));
}
- if (t->orient_curr == 0) {
+ transform_orientations_current_set(t, orient_index);
+ if (orient_index == 0) {
stopConstraint(t);
}
else {
- const short orientation = t->orient[t->orient_curr].type;
if (is_plane == false) {
- setUserConstraint(t, orientation, constraint_axis, msg2);
+ setUserConstraint(t, constraint_axis, msg2);
}
else {
- setUserConstraint(t, orientation, constraint_plane, msg3);
+ setUserConstraint(t, constraint_plane, msg3);
}
}
}
@@ -1717,10 +1717,6 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
initTransInfo(C, t, op, event);
- /* Use the custom orientation when it is set. */
- short orient_index = t->orient[0].type == V3D_ORIENT_CUSTOM_MATRIX ? 0 : t->orient_curr;
- transform_orientations_current_set(t, orient_index);
-
if (t->spacetype == SPACE_VIEW3D) {
t->draw_handle_apply = ED_region_draw_cb_activate(
t->region->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);
@@ -1868,7 +1864,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
/* Constraint init from operator */
if (t->con.mode & CON_APPLY) {
- setUserConstraint(t, t->orient[t->orient_curr].type, t->con.mode, "%s");
+ setUserConstraint(t, t->con.mode, "%s");
}
/* Don't write into the values when non-modal because they are already set from operator redo
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 805411ffc20..27ece728276 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -686,9 +686,15 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[])
* ftext is a format string passed to BLI_snprintf. It will add the name of
* the orientation where %s is (logically).
*/
-void setUserConstraint(TransInfo *t, short orientation, int mode, const char ftext[])
+void setUserConstraint(TransInfo *t, int mode, const char ftext[])
{
char text[256];
+ short orientation = t->orient[t->orient_curr].type;
+ if (orientation == V3D_ORIENT_CUSTOM_MATRIX) {
+ /* Use the real value of the "orient_type". */
+ orientation = t->orient[0].type;
+ }
+
const char *spacename = transform_orientations_spacename_get(t, orientation);
BLI_snprintf(text, sizeof(text), ftext, spacename);
@@ -943,12 +949,10 @@ void stopConstraint(TransInfo *t)
void initSelectConstraint(TransInfo *t)
{
if (t->orient_curr == 0) {
- t->orient_curr = 1;
- transform_orientations_current_set(t, t->orient_curr);
+ transform_orientations_current_set(t, 1);
}
- short orientation = t->orient[t->orient_curr].type;
- setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, "%s");
+ setUserConstraint(t, CON_APPLY | CON_SELECT, "%s");
setNearestAxis(t);
}
diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h
index 4c901842964..ac62c057f9d 100644
--- a/source/blender/editors/transform/transform_constraints.h
+++ b/source/blender/editors/transform/transform_constraints.h
@@ -35,7 +35,7 @@ void transform_constraint_snap_axis_to_face(const TransInfo *t,
void setConstraint(TransInfo *t, int mode, const char text[]);
void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[]);
void setLocalConstraint(TransInfo *t, int mode, const char text[]);
-void setUserConstraint(TransInfo *t, short orientation, int mode, const char text[]);
+void setUserConstraint(TransInfo *t, int mode, const char text[]);
void drawConstraint(TransInfo *t);
void drawPropCircle(const struct bContext *C, TransInfo *t);
void startConstraint(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index a2e1c50e375..ba87f0bcc38 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -442,7 +442,10 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
BLI_assert(is_zero_v4(t->values_modal_offset));
+
+ bool use_orient_axis = false;
bool t_values_set_is_array = false;
+
if (op && (prop = RNA_struct_find_property(op->ptr, "value")) &&
RNA_property_is_set(op->ptr, prop)) {
float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */
@@ -465,19 +468,28 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
+ if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
+ t->orient_axis = RNA_property_enum_get(op->ptr, prop);
+ use_orient_axis = true;
+ }
+
if (op && (prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) {
bool constraint_axis[3] = {false, false, false};
- if (RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_get_array(op->ptr, prop, constraint_axis);
- }
-
- if (t_values_set_is_array && t->flag & T_INPUT_IS_VALUES_FINAL) {
- /* For operators whose `t->values` is array, set constraint so that the
- * orientation is more intuitive in the Redo Panel. */
- for (int i = 3; i--;) {
- constraint_axis[i] |= t->values[i] != 0.0f;
+ if (t->flag & T_INPUT_IS_VALUES_FINAL) {
+ if (t_values_set_is_array) {
+ /* For operators whose `t->values` is array, set constraint so that the
+ * orientation is more intuitive in the Redo Panel. */
+ for (int i = 3; i--;) {
+ constraint_axis[i] |= t->values[i] != 0.0f;
+ }
+ }
+ else if (use_orient_axis) {
+ constraint_axis[t->orient_axis] = true;
}
}
+ else if (RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_get_array(op->ptr, prop, constraint_axis);
+ }
if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) {
t->con.mode |= CON_APPLY;
@@ -495,9 +507,13 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
{
- short orient_type_set = -1;
- short orient_type_matrix_set = -1;
+ short orient_types[3];
+ float custom_matrix[3][3];
+
+ short orient_type_default = V3D_ORIENT_GLOBAL;
short orient_type_scene = V3D_ORIENT_GLOBAL;
+ short orient_type_set = V3D_ORIENT_GLOBAL;
+ short orient_type_matrix_set = -1;
if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
@@ -508,14 +524,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
- short orient_types[3];
- float custom_matrix[3][3];
- bool use_orient_axis = false;
-
- if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
- t->orient_axis = RNA_property_enum_get(op->ptr, prop);
- use_orient_axis = true;
- }
if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop);
}
@@ -530,21 +538,21 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
/* Change the default orientation to be used when redoing. */
- orient_types[0] = orient_type_set;
- orient_types[1] = orient_type_set;
- orient_types[2] = orient_type_scene;
+ orient_type_default = orient_type_set;
+ }
+ else if (t->con.mode & CON_APPLY) {
+ orient_type_set = orient_type_default = orient_type_scene;
}
else {
+ if (orient_type_set == orient_type_scene) {
+ BLI_assert(orient_type_set == V3D_ORIENT_GLOBAL);
+ orient_type_set = V3D_ORIENT_LOCAL;
+ }
+
if ((t->flag & T_MODAL) && (use_orient_axis || transform_mode_is_changeable(t->mode)) &&
(t->mode != TFM_ALIGN)) {
- orient_types[0] = V3D_ORIENT_VIEW;
+ orient_type_default = V3D_ORIENT_VIEW;
}
- else {
- orient_types[0] = orient_type_scene;
- }
- orient_types[1] = orient_type_scene;
- orient_types[2] = orient_type_scene != V3D_ORIENT_GLOBAL ? V3D_ORIENT_GLOBAL :
- V3D_ORIENT_LOCAL;
}
if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) &&
@@ -555,39 +563,39 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
RNA_property_is_set(op->ptr, prop)) {
orient_type_matrix_set = RNA_property_enum_get(op->ptr, prop);
}
- else if (orient_type_set != -1) {
- orient_type_matrix_set = orient_type_set;
- }
else {
- orient_type_matrix_set = orient_type_set = V3D_ORIENT_GLOBAL;
+ orient_type_matrix_set = orient_type_set;
}
if (orient_type_matrix_set == orient_type_set) {
/* Constraints are forced to use the custom matrix when redoing. */
- orient_types[0] = V3D_ORIENT_CUSTOM_MATRIX;
+ orient_type_set = V3D_ORIENT_CUSTOM_MATRIX;
}
}
- if (t->con.mode & CON_APPLY) {
- t->orient_curr = 1;
- }
+ orient_types[0] = orient_type_default;
+ orient_types[1] = orient_type_scene;
+ orient_types[2] = orient_type_set;
- /* For efficiency, avoid calculating the same orientation twice. */
- for (int i = 1; i < 3; i++) {
- t->orient[i].type = transform_orientation_matrix_get(
- C, t, orient_types[i], custom_matrix, t->orient[i].matrix);
- }
-
- if (orient_types[0] != orient_types[1]) {
- t->orient[0].type = transform_orientation_matrix_get(
- C, t, orient_types[0], custom_matrix, t->orient[0].matrix);
- }
- else {
- memcpy(&t->orient[0], &t->orient[1], sizeof(t->orient[0]));
+ for (int i = 0; i < 3; i++) {
+ /* For efficiency, avoid calculating the same orientation twice. */
+ int j;
+ for (j = 0; j < i; j++) {
+ if (orient_types[j] == orient_types[i]) {
+ memcpy(&t->orient[i], &t->orient[j], sizeof(*t->orient));
+ break;
+ }
+ }
+ if (j == i) {
+ t->orient[i].type = transform_orientation_matrix_get(
+ C, t, orient_types[i], custom_matrix, t->orient[i].matrix);
+ }
}
- const char *spacename = transform_orientations_spacename_get(t, orient_types[0]);
- BLI_strncpy(t->spacename, spacename, sizeof(t->spacename));
+ /* Set orient_curr to -1 in order to force the update in
+ * `transform_orientations_current_set`. */
+ t->orient_curr = -1;
+ transform_orientations_current_set(t, (t->con.mode & CON_APPLY) ? 2 : 0);
}
if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c
index c0ddd4eb2a6..37b68877b08 100644
--- a/source/blender/editors/transform/transform_mode_rotate.c
+++ b/source/blender/editors/transform/transform_mode_rotate.c
@@ -195,28 +195,30 @@ static void applyRotationValue(TransInfo *t,
static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
{
char str[UI_MAX_DRAW_STR];
-
- float final;
-
- final = t->values[0];
-
- transform_snap_increment(t, &final);
-
float axis_final[3];
- /* Use the negative axis to match the default Z axis of the view matrix. */
- negate_v3_v3(axis_final, t->spacemtx[t->orient_axis]);
+ float final = t->values[0];
if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
t->con.applyRot(t, NULL, NULL, axis_final, NULL);
}
-
- applySnapping(t, &final);
+ else {
+ copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]);
+ if (!(t->flag & T_INPUT_IS_VALUES_FINAL) && (dot_v3v3(axis_final, t->viewinv[2]) > 0.0f)) {
+ /* The input is obtained according to the position of the mouse.
+ * Flip to better match the movement. */
+ final *= -1;
+ }
+ }
if (applyNumInput(&t->num, &final)) {
/* We have to limit the amount of turns to a reasonable number here,
* to avoid things getting *very* slow, see how applyRotationValue() handles those... */
final = large_rotation_limit(final);
}
+ else {
+ transform_snap_increment(t, &final);
+ applySnapping(t, &final);
+ }
t->values_final[0] = final;
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 276d9381a0b..dc693bd6b15 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -616,12 +616,17 @@ const char *transform_orientations_spacename_get(TransInfo *t, const short orien
void transform_orientations_current_set(TransInfo *t, const short orient_index)
{
+ if (t->orient_curr == orient_index) {
+ return;
+ }
+
const short orientation = t->orient[orient_index].type;
const char *spacename = transform_orientations_spacename_get(t, orientation);
BLI_strncpy(t->spacename, spacename, sizeof(t->spacename));
copy_m3_m3(t->spacemtx, t->orient[orient_index].matrix);
invert_m3_m3(t->spacemtx_inv, t->spacemtx);
+ t->orient_curr = orient_index;
}
/**
diff --git a/source/blender/gpu/opengl/gl_texture.hh b/source/blender/gpu/opengl/gl_texture.hh
index 02e9bee3475..e686a7defca 100644
--- a/source/blender/gpu/opengl/gl_texture.hh
+++ b/source/blender/gpu/opengl/gl_texture.hh
@@ -349,6 +349,18 @@ inline GLenum to_gl_data_format(eGPUTextureFormat format)
case GPU_DEPTH_COMPONENT24:
case GPU_DEPTH_COMPONENT32F:
return GL_DEPTH_COMPONENT;
+ case GPU_SRGB8_A8_DXT1:
+ return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+ case GPU_SRGB8_A8_DXT3:
+ return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+ case GPU_SRGB8_A8_DXT5:
+ return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+ case GPU_RGBA8_DXT1:
+ return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ case GPU_RGBA8_DXT3:
+ return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ case GPU_RGBA8_DXT5:
+ return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
default:
BLI_assert(!"Texture format incorrect or unsupported\n");
return 0;
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 858daaac47c..7cb9978f768 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -1047,8 +1047,12 @@ typedef struct AnimOverride {
* See blenkernel/intern/anim_sys.c for details.
*/
typedef struct AnimData {
- /** active action - acts as the 'tweaking track' for the NLA */
+ /**
+ * Active action - acts as the 'tweaking track' for the NLA.
+ * Either use BKE_animdata_set_action() to set this, or call BKE_animdata_action_ensure_idroot()
+ * after setting. */
bAction *action;
+
/** temp-storage for the 'real' active action (i.e. the one used before the tweaking-action
* took over to be edited in the Animation Editors)
*/
diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c
index 6fd1609e77b..0251dc17fcd 100644
--- a/source/blender/makesrna/intern/rna_access_compare_override.c
+++ b/source/blender/makesrna/intern/rna_access_compare_override.c
@@ -886,9 +886,11 @@ static void rna_property_override_apply_ex(Main *bmain,
if (!do_insert != !ELEM(opop->operation,
IDOVERRIDE_LIBRARY_OP_INSERT_AFTER,
IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE)) {
+#ifndef NDEBUG
if (!do_insert) {
printf("Skipping insert override operations in first pass (%s)!\n", op->rna_path);
}
+#endif
continue;
}
@@ -972,18 +974,22 @@ static void rna_property_override_apply_ex(Main *bmain,
ptr_item_src = &private_ptr_item_src;
ptr_item_storage = &private_ptr_item_storage;
+#ifndef NDEBUG
if (ptr_item_dst->type == NULL) {
- printf("Failed to find destination sub-item '%s' of '%s' in new override data '%s'\n",
+ printf("Failed to find destination sub-item '%s' (%d) of '%s' in new override data '%s'\n",
opop->subitem_reference_name,
+ opop->subitem_reference_index,
op->rna_path,
ptr_dst->owner_id->name);
}
if (ptr_item_src->type == NULL) {
- printf("Failed to find source sub-item '%s' of '%s' in old override data '%s'\n",
+ printf("Failed to find source sub-item '%s' (%d) of '%s' in old override data '%s'\n",
opop->subitem_local_name,
+ opop->subitem_local_index,
op->rna_path,
ptr_src->owner_id->name);
}
+#endif
}
if (!rna_property_override_operation_apply(bmain,
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 823446a9d3b..a50d27a726b 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -144,14 +144,7 @@ static void rna_AnimData_dependency_update(Main *bmain, Scene *scene, PointerRNA
static int rna_AnimData_action_editable(PointerRNA *ptr, const char **UNUSED(r_info))
{
AnimData *adt = (AnimData *)ptr->data;
-
- /* active action is only editable when it is not a tweaking strip */
- if ((adt->flag & ADT_NLA_EDIT_ON) || (adt->actstrip) || (adt->tmpact)) {
- return 0;
- }
- else {
- return PROP_EDITABLE;
- }
+ return BKE_animdata_action_editable(adt) ? PROP_EDITABLE : 0;
}
static void rna_AnimData_action_set(PointerRNA *ptr,
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index b60da2c2260..2d6bf2897e0 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -1630,30 +1630,31 @@ static void rna_def_curve(BlenderRNA *brna)
RNA_def_property_range(prop, 0, 32);
RNA_def_property_ui_range(prop, 0, 32, 1.0, -1);
RNA_def_property_ui_text(
- prop,
- "Bevel Resolution",
- "Bevel resolution when depth is non-zero and no specific bevel object has been defined");
+ prop, "Bevel Resolution", "The number of segments in each quarter-circle of the bevel");
RNA_def_property_update(prop, 0, "rna_Curve_bevel_resolution_update");
prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH);
RNA_def_property_float_sdna(prop, NULL, "width");
RNA_def_property_ui_range(prop, -1.0, 1.0, 0.1, 3);
RNA_def_property_float_funcs(prop, "rna_Curve_offset_get", "rna_Curve_offset_set", NULL);
- RNA_def_property_ui_text(prop, "Offset", "Offset the curve to adjust the width of a text");
+ RNA_def_property_ui_text(prop, "Offset", "Distance to move the curve parallel to its normals");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
prop = RNA_def_property(srna, "extrude", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH);
RNA_def_property_float_sdna(prop, NULL, "ext1");
RNA_def_property_ui_range(prop, 0, 100.0, 0.1, 3);
RNA_def_property_range(prop, 0.0, FLT_MAX);
- RNA_def_property_ui_text(
- prop, "Extrude", "Amount of curve extrusion when not using a bevel object");
+ RNA_def_property_ui_text(prop,
+ "Extrude",
+ "Length of the depth added in the local Z direction along the curve, "
+ "perpendicular to its normals");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
prop = RNA_def_property(srna, "bevel_depth", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH);
RNA_def_property_float_sdna(prop, NULL, "ext2");
RNA_def_property_ui_range(prop, 0, 100.0, 0.1, 3);
- RNA_def_property_ui_text(prop, "Bevel Depth", "Bevel depth when not using a bevel object");
+ RNA_def_property_ui_text(
+ prop, "Bevel Depth", "Radius of the bevel geometry, not including extrusion");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
prop = RNA_def_property(srna, "resolution_u", PROP_INT, PROP_NONE);
@@ -1661,7 +1662,10 @@ static void rna_def_curve(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 1, 1024);
RNA_def_property_ui_range(prop, 1, 64, 1, -1);
- RNA_def_property_ui_text(prop, "Resolution U", "Surface resolution in U direction");
+ RNA_def_property_ui_text(
+ prop,
+ "Resolution U",
+ "Number of computed points in the U direction between every pair of control points");
RNA_def_property_update(prop, 0, "rna_Curve_resolution_u_update_data");
prop = RNA_def_property(srna, "resolution_v", PROP_INT, PROP_NONE);
@@ -1669,7 +1673,10 @@ static void rna_def_curve(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_range(prop, 1, 64, 1, -1);
RNA_def_property_range(prop, 1, 1024);
- RNA_def_property_ui_text(prop, "Resolution V", "Surface resolution in V direction");
+ RNA_def_property_ui_text(
+ prop,
+ "Resolution V",
+ "The number of computed points in the V direction between every pair of control points");
RNA_def_property_update(prop, 0, "rna_Curve_resolution_v_update_data");
prop = RNA_def_property(srna, "render_resolution_u", PROP_INT, PROP_NONE);
@@ -1705,7 +1712,8 @@ static void rna_def_curve(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "bevobj");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
- RNA_def_property_ui_text(prop, "Bevel Object", "Curve object name that defines the bevel shape");
+ RNA_def_property_ui_text(
+ prop, "Bevel Object", "The name of the Curve object that defines the bevel shape");
RNA_def_property_update(prop, 0, "rna_Curve_update_deps");
RNA_def_property_pointer_funcs(prop,
"rna_Curve_bevelObject_get",
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index a3458a7b8ff..00e5583f9c0 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -5649,11 +5649,13 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
prop = RNA_def_property(srna, "invert_spray", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_OCEAN_INVERT_SPRAY);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Invert Spray", "Invert the spray direction map");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "spray_layer_name", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "spraylayername");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
prop, "Spray Map", "Name of the vertex color layer used for the spray direction map");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
@@ -5688,6 +5690,7 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
prop = RNA_def_property(srna, "wind_velocity", PROP_FLOAT, PROP_VELOCITY);
RNA_def_property_float_sdna(prop, NULL, "wind_velocity");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Wind Velocity", "Wind speed");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
@@ -5707,6 +5710,7 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
prop = RNA_def_property(srna, "wave_alignment", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "wave_alignment");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Wave Alignment", "How much the waves are aligned to each other");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
@@ -5767,12 +5771,14 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
prop = RNA_def_property(srna, "spectrum", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "spectrum");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_enum_items(prop, spectrum_items);
RNA_def_property_ui_text(prop, "Spectrum", "Spectrum to use");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "fetch_jonswap", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "fetch_jonswap");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_ui_text(
prop,
@@ -5784,6 +5790,7 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
prop = RNA_def_property(srna, "sharpen_peak_jonswap", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "sharpen_peak_jonswap");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Sharpen peak", "Peak sharpening for 'JONSWAP' and 'TMA' models");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 8d87de23b3a..a7aa8ccdf71 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -1763,7 +1763,6 @@ int rna_property_override_diff_default(Main *bmain,
case PROP_COLLECTION: {
bool equals = true;
bool abort = false;
- bool is_first_insert = true;
int idx_a = 0;
int idx_b = 0;
@@ -1778,6 +1777,22 @@ int rna_property_override_diff_default(Main *bmain,
char *prev_propname_a = buff_prev_a;
char *propname_b = NULL;
+ if (use_collection_insertion) {
+ /* We need to clean up all possible existing insertion operations, and then re-generate
+ * them, otherwise we'd end up with a mess of opops every time something changes. */
+ op = BKE_lib_override_library_property_find(override, rna_path);
+ if (op != NULL) {
+ LISTBASE_FOREACH_MUTABLE (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
+ if (ELEM(opop->operation,
+ IDOVERRIDE_LIBRARY_OP_INSERT_AFTER,
+ IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE)) {
+ BKE_lib_override_library_property_operation_delete(op, opop);
+ }
+ }
+ op = NULL;
+ }
+ }
+
for (; iter_a.valid && !abort;) {
bool is_valid_for_diffing;
bool is_valid_for_insertion;
@@ -1860,22 +1875,6 @@ int rna_property_override_diff_default(Main *bmain,
if (is_valid_for_insertion && use_collection_insertion) {
op = BKE_lib_override_library_property_get(override, rna_path, &created);
- if (is_first_insert) {
- /* We need to clean up all possible existing insertion operations,
- * otherwise we'd end up with a mess of ops every time something changes. */
- for (IDOverrideLibraryPropertyOperation *opop = op->operations.first;
- opop != NULL;) {
- IDOverrideLibraryPropertyOperation *opop_next = opop->next;
- if (ELEM(opop->operation,
- IDOVERRIDE_LIBRARY_OP_INSERT_AFTER,
- IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE)) {
- BKE_lib_override_library_property_operation_delete(op, opop);
- }
- opop = opop_next;
- }
- is_first_insert = false;
- }
-
BKE_lib_override_library_property_operation_get(op,
IDOVERRIDE_LIBRARY_OP_INSERT_AFTER,
NULL,
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 18c80006496..3fa577d4230 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -1922,78 +1922,73 @@ static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr)
SpaceAction *saction = (SpaceAction *)(ptr->data);
ViewLayer *view_layer = CTX_data_view_layer(C);
Main *bmain = CTX_data_main(C);
- Object *obact = OBACT(view_layer);
- /* we must set this action to be the one used by active object (if not pinned) */
- if (obact /* && saction->pin == 0*/) {
- AnimData *adt = NULL;
+ Object *obact = OBACT(view_layer);
+ if (obact == NULL) {
+ return;
+ }
- if (saction->mode == SACTCONT_ACTION) {
+ AnimData *adt = NULL;
+ ID *id = NULL;
+ switch (saction->mode) {
+ case SACTCONT_ACTION:
/* TODO: context selector could help decide this with more control? */
- adt = BKE_animdata_add_id(&obact->id); /* this only adds if non-existent */
- }
- else if (saction->mode == SACTCONT_SHAPEKEY) {
+ adt = BKE_animdata_add_id(&obact->id);
+ id = &obact->id;
+ break;
+ case SACTCONT_SHAPEKEY: {
Key *key = BKE_key_from_object(obact);
- if (key) {
- adt = BKE_animdata_add_id(&key->id); /* this only adds if non-existent */
+ if (key == NULL) {
+ return;
}
+ adt = BKE_animdata_add_id(&key->id);
+ id = &key->id;
+ break;
}
+ case SACTCONT_GPENCIL:
+ case SACTCONT_DOPESHEET:
+ case SACTCONT_MASK:
+ case SACTCONT_CACHEFILE:
+ case SACTCONT_TIMELINE:
+ return;
+ }
- /* set action */
- // FIXME: this overlaps a lot with the BKE_animdata_set_action() API method
- if (adt) {
- /* Don't do anything if old and new actions are the same... */
- if (adt->action != saction->action) {
- /* NLA Tweak Mode needs special handling... */
- if (adt->flag & ADT_NLA_EDIT_ON) {
- /* Exit editmode first - we cannot change actions while in tweakmode
- * NOTE: This will clear the action ref properly
- */
- BKE_nla_tweakmode_exit(adt);
-
- /* Assign new action, and adjust the usercounts accordingly */
- adt->action = saction->action;
- id_us_plus((ID *)adt->action);
- }
- else {
- /* Handle old action... */
- if (adt->action) {
- /* Fix id-count of action we're replacing */
- id_us_min(&adt->action->id);
-
- /* To prevent data loss (i.e. if users flip between actions using the Browse menu),
- * stash this action if nothing else uses it.
- *
- * EXCEPTION:
- * This callback runs when unlinking actions. In that case, we don't want to
- * stash the action, as the user is signaling that they want to detach it.
- * This can be reviewed again later,
- * but it could get annoying if we keep these instead.
- */
- if ((adt->action->id.us <= 0) && (saction->action != NULL)) {
- /* XXX: Things here get dodgy if this action is only partially completed,
- * and the user then uses the browse menu to get back to this action,
- * assigning it as the active action (i.e. the stash strip gets out of sync)
- */
- BKE_nla_action_stash(adt);
- }
- }
-
- /* Assign new action, and adjust the usercounts accordingly */
- adt->action = saction->action;
- id_us_plus((ID *)adt->action);
- }
- }
+ if (adt == NULL) {
+ /* No animdata was added, so the depsgraph also doesn't need tagging. */
+ return;
+ }
- /* Force update of animdata */
- DEG_id_tag_update(&obact->id, ID_RECALC_ANIMATION);
- }
+ /* Don't do anything if old and new actions are the same... */
+ if (adt->action == saction->action) {
+ return;
+ }
- /* force depsgraph flush too */
- DEG_id_tag_update(&obact->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- /* Update relations as well, so new time source dependency is added. */
- DEG_relations_tag_update(bmain);
+ /* Exit editmode first - we cannot change actions while in tweakmode. */
+ BKE_nla_tweakmode_exit(adt);
+
+ /* To prevent data loss (i.e. if users flip between actions using the Browse menu),
+ * stash this action if nothing else uses it.
+ *
+ * EXCEPTION:
+ * This callback runs when unlinking actions. In that case, we don't want to
+ * stash the action, as the user is signaling that they want to detach it.
+ * This can be reviewed again later,
+ * but it could get annoying if we keep these instead.
+ */
+ if (adt->action != NULL && adt->action->id.us <= 0 && saction->action != NULL) {
+ /* XXX: Things here get dodgy if this action is only partially completed,
+ * and the user then uses the browse menu to get back to this action,
+ * assigning it as the active action (i.e. the stash strip gets out of sync)
+ */
+ BKE_nla_action_stash(adt);
}
+
+ BKE_animdata_set_action(NULL, id, saction->action);
+
+ DEG_id_tag_update(&obact->id, ID_RECALC_ANIMATION | ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ /* Update relations as well, so new time source dependency is added. */
+ DEG_relations_tag_update(bmain);
}
static void rna_SpaceDopeSheetEditor_mode_update(bContext *C, PointerRNA *ptr)
diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c
index a902da2496e..46e4f147e20 100644
--- a/source/blender/modifiers/intern/MOD_weld.c
+++ b/source/blender/modifiers/intern/MOD_weld.c
@@ -1578,7 +1578,6 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
const MLoop *mloop;
const MPoly *mpoly, *mp;
uint totvert, totedge, totloop, totpoly;
- uint i;
mvert = mesh->mvert;
totvert = mesh->totvert;
@@ -1592,7 +1591,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
const bool invert_vgroup = (wmd->flag & MOD_WELD_INVERT_VGROUP) != 0;
dv = &dvert[0];
v_mask = BLI_BITMAP_NEW(totvert, __func__);
- for (i = 0; i < totvert; i++, dv++) {
+ for (uint i = 0; i < totvert; i++, dv++) {
const bool found = BKE_defvert_find_weight(dv, defgrp_index) > 0.0f;
if (found != invert_vgroup) {
BLI_BITMAP_ENABLE(v_mask, i);
@@ -1687,9 +1686,8 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
}
#else
{
- vert_dest_map = MEM_malloc_arrayN(totvert, sizeof(*vert_dest_map), __func__);
KDTree_3d *tree = BLI_kdtree_3d_new(totvert);
- for (i = 0; i < totvert; i++) {
+ for (uint i = 0; i < totvert; i++) {
if (!(v_mask && !BLI_BITMAP_TEST(v_mask, i))) {
BLI_kdtree_3d_insert(tree, i, mvert[i].co);
}
@@ -1698,7 +1696,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
BLI_kdtree_3d_balance(tree);
vert_kill_len = BLI_kdtree_3d_calc_duplicates_fast(
- tree, wmd->merge_dist, false, (int *)vert_dest_map);
+ tree, wmd->merge_dist, true, (int *)vert_dest_map);
BLI_kdtree_3d_free(tree);
}
#endif
@@ -1731,7 +1729,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
uint *vert_final = vert_dest_map;
uint *index_iter = &vert_final[0];
int dest_index = 0;
- for (i = 0; i < totvert; i++, index_iter++) {
+ for (uint i = 0; i < totvert; i++, index_iter++) {
int source_index = i;
int count = 0;
while (i < totvert && *index_iter == OUT_OF_CONTEXT) {
@@ -1766,7 +1764,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
uint *edge_final = weld_mesh.edge_groups_map;
index_iter = &edge_final[0];
dest_index = 0;
- for (i = 0; i < totedge; i++, index_iter++) {
+ for (uint i = 0; i < totedge; i++, index_iter++) {
int source_index = i;
int count = 0;
while (i < totedge && *index_iter == OUT_OF_CONTEXT) {
@@ -1814,7 +1812,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
uint r_i = 0;
int loop_cur = 0;
uint *group_buffer = BLI_array_alloca(group_buffer, weld_mesh.max_poly_len);
- for (i = 0; i < totpoly; i++, mp++) {
+ for (uint i = 0; i < totpoly; i++, mp++) {
int loop_start = loop_cur;
uint poly_ctx = weld_mesh.poly_map[i];
if (poly_ctx == OUT_OF_CONTEXT) {
@@ -1860,7 +1858,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
}
WeldPoly *wp = &weld_mesh.wpoly_new[0];
- for (i = 0; i < weld_mesh.wpoly_new_len; i++, wp++) {
+ for (uint i = 0; i < weld_mesh.wpoly_new_len; i++, wp++) {
int loop_start = loop_cur;
WeldLoopOfPolyIter iter;
if (!weld_iter_loop_of_poly_begin(
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 80f330d91ca..8fba1ed342e 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -632,12 +632,16 @@ void WM_gesture_lasso_cancel(struct bContext *C, struct wmOperator *op);
const int (*WM_gesture_lasso_path_to_array(struct bContext *C,
struct wmOperator *op,
int *mcoords_len))[2];
+
int WM_gesture_straightline_invoke(struct bContext *C,
struct wmOperator *op,
const struct wmEvent *event);
int WM_gesture_straightline_modal(struct bContext *C,
struct wmOperator *op,
const struct wmEvent *event);
+int WM_gesture_straightline_oneshot_modal(struct bContext *C,
+ struct wmOperator *op,
+ const struct wmEvent *event);
void WM_gesture_straightline_cancel(struct bContext *C, struct wmOperator *op);
/* Gesture manager API */
diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c
index a38cbb920c4..25de76d4428 100644
--- a/source/blender/windowmanager/intern/wm_gesture_ops.c
+++ b/source/blender/windowmanager/intern/wm_gesture_ops.c
@@ -792,6 +792,16 @@ void WM_OT_lasso_gesture(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
/** \name Straight Line Gesture
+ *
+ * Gesture defined by the start and end points of a line that is created between the posistion of
+ * the initial event and the position of the current event.
+ *
+ * Straight Line Gesture has two modal callbacks depending on the tool that is being implemented: a
+ * regular modal callback intended to update the data during the execution of the gesture and a
+ * oneshot callback that only updates the data once when the gesture finishes.
+ *
+ * It stores 4 values (xstart, ystart, xend, yend).
+ *
* \{ */
static bool gesture_straightline_apply(bContext *C, wmOperator *op)
@@ -841,6 +851,11 @@ int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *e
return OPERATOR_RUNNING_MODAL;
}
+/**
+ * This modal callback calls exec once per mouse move event while the gesture is active with the
+ * updated line start and end values, so it can be used for tools that have a real time preview
+ * (like a gradient updating in real time over the mesh).
+ */
int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
@@ -886,6 +901,63 @@ int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *ev
return OPERATOR_RUNNING_MODAL;
}
+/**
+ * This modal oneshot callback only calls exec once after the gesture finishes without any updates
+ * during the gesture execution. Should be used for operations that are intended to be applied once
+ * without real time preview (like a trimming tool that only applies the bisect operation once
+ * after finishing the gesture as the bisect operation is too heavy to be computed in real time for
+ * a preview).
+ */
+int WM_gesture_straightline_oneshot_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ wmGesture *gesture = op->customdata;
+ wmWindow *win = CTX_wm_window(C);
+ rcti *rect = gesture->customdata;
+
+ if (event->type == MOUSEMOVE) {
+ if (gesture->is_active == false) {
+ rect->xmin = rect->xmax = event->x - gesture->winrct.xmin;
+ rect->ymin = rect->ymax = event->y - gesture->winrct.ymin;
+ }
+ else {
+ rect->xmax = event->x - gesture->winrct.xmin;
+ rect->ymax = event->y - gesture->winrct.ymin;
+ }
+
+ wm_gesture_tag_redraw(win);
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case GESTURE_MODAL_BEGIN:
+ if (gesture->is_active == false) {
+ gesture->is_active = true;
+ wm_gesture_tag_redraw(win);
+ }
+ break;
+ case GESTURE_MODAL_SELECT:
+ case GESTURE_MODAL_DESELECT:
+ case GESTURE_MODAL_IN:
+ case GESTURE_MODAL_OUT:
+ if (gesture->wait_for_input) {
+ gesture->modal_state = event->val;
+ }
+ if (gesture_straightline_apply(C, op)) {
+ gesture_modal_end(C, op);
+ return OPERATOR_FINISHED;
+ }
+ gesture_modal_end(C, op);
+ return OPERATOR_CANCELLED;
+
+ case GESTURE_MODAL_CANCEL:
+ gesture_modal_end(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ gesture->is_active_prev = gesture->is_active;
+ return OPERATOR_RUNNING_MODAL;
+}
+
void WM_gesture_straightline_cancel(bContext *C, wmOperator *op)
{
gesture_modal_end(C, op);
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 2b01c8fe90e..0e4bb1cc33a 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3904,6 +3904,7 @@ static void gesture_box_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "PAINT_OT_mask_box_gesture");
WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_box_gesture");
WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_box_gesture");
+ WM_modalkeymap_assign(keymap, "PAINT_OT_mask_line_gesture");
WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border");
WM_modalkeymap_assign(keymap, "VIEW3D_OT_clip_border");
WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border");
diff --git a/source/tools b/source/tools
-Subproject ff9928bc44e80ec30c78369bf1518599254a003
+Subproject 2afbb8ec472cac5102eb239f57b006f8c938768
diff --git a/tests/python/modifiers.py b/tests/python/modifiers.py
index 4bbcf226aba..ba156cef8ea 100644
--- a/tests/python/modifiers.py
+++ b/tests/python/modifiers.py
@@ -186,7 +186,7 @@ def main():
["testMergedWeld", "expectedMergedWeld",
[ModifierSpec("weld", 'WELD', {"merge_threshold": 0.021})]],
["testMergedAllWeld", "expectedMergedAllWeld",
- [ModifierSpec("weld", 'WELD', {"merge_threshold": 1.1})]],
+ [ModifierSpec("weld", 'WELD', {"merge_threshold": 1.8})]],
["testMergedNoneWeld", "expectedMergedNoneWeld",
[ModifierSpec("weld", 'WELD', {"merge_threshold": 0.019})]],