diff options
author | Jacques Lucke <jacques@blender.org> | 2020-09-28 13:30:39 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2020-09-28 13:30:39 +0300 |
commit | d525a541a2bf8913fce43e2f9bef3e37dba00d30 (patch) | |
tree | f2758c9fd14a2234c29d7130d1f776c3b88f4bbb | |
parent | e204f67cf0f570a69e46cf3eb731f2705c21ee46 (diff) | |
parent | f808f2a4950a99f74780ea87e9d62ee36bc4ff35 (diff) |
Merge branch 'master' into mesh-to-volume-modifier
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(®ion->winrct) + 1; + int getsizey = BLI_rcti_size_y(®ion->winrct) + 1; + int sx = region->winrct.xmin; + int sy = region->winrct.ymin; - getsizex = BLI_rcti_size_x(®ion->winrct) + 1; - getsizey = BLI_rcti_size_y(®ion->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(®ion->winrct) + 1; - getsizey = BLI_rcti_size_y(®ion->winrct) + 1; - sx = region->winrct.xmin; - sy = region->winrct.ymin; + int getsizex = BLI_rcti_size_x(®ion->winrct) + 1; + int getsizey = BLI_rcti_size_y(®ion->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, ®ion->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})]], |