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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Eagar <joeedh@gmail.com>2020-12-21 12:08:24 +0300
committerJoseph Eagar <joeedh@gmail.com>2020-12-21 12:08:24 +0300
commitb3fff9b07aa32dd9421143aeed1a941632f55322 (patch)
treeaff29045c84bb609d2bdfa0b926d35a4004983a1 /source/blender/editors
parent681e2b6134e8142d258fcbaafab0c8d9b19fac69 (diff)
parent84cc00f3b68e12209e000008f992fad3ac48f757 (diff)
Merge remote-tracking branch 'origin/master' into temp_bmesh_multires
Also redid vcol boundary tool icon, and made a little icon for sculpt color paint.
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/CMakeLists.txt1
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c10
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c52
-rw-r--r--source/blender/editors/animation/anim_deps.c11
-rw-r--r--source/blender/editors/animation/anim_filter.c24
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c3
-rw-r--r--source/blender/editors/animation/anim_ops.c5
-rw-r--r--source/blender/editors/animation/keyframes_general.c13
-rw-r--r--source/blender/editors/animation/keyframing.c23
-rw-r--r--source/blender/editors/armature/armature_edit.c2
-rw-r--r--source/blender/editors/armature/editarmature_undo.c2
-rw-r--r--source/blender/editors/armature/pose_select.c4
-rw-r--r--source/blender/editors/asset/CMakeLists.txt39
-rw-r--r--source/blender/editors/asset/asset_edit.c69
-rw-r--r--source/blender/editors/asset/asset_ops.c238
-rw-r--r--source/blender/editors/curve/editcurve.c2
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt1
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c102
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_add_monkey.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_add_stroke.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c22
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c74
-rw-r--r--source/blender/editors/gpencil/gpencil_merge.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_ops_versioning.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_sculpt_paint.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_vertex_ops.c3
-rw-r--r--source/blender/editors/gpencil/gpencil_vertex_paint.c1
-rw-r--r--source/blender/editors/include/ED_armature.h1
-rw-r--r--source/blender/editors/include/ED_asset.h39
-rw-r--r--source/blender/editors/include/ED_fileselect.h13
-rw-r--r--source/blender/editors/include/ED_gpencil.h1
-rw-r--r--source/blender/editors/include/ED_image.h2
-rw-r--r--source/blender/editors/include/ED_info.h8
-rw-r--r--source/blender/editors/include/ED_object.h1
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/include/ED_transform.h2
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h1
-rw-r--r--source/blender/editors/include/ED_util.h5
-rw-r--r--source/blender/editors/include/ED_util_imbuf.h1
-rw-r--r--source/blender/editors/include/ED_uvedit.h9
-rw-r--r--source/blender/editors/include/ED_view3d.h10
-rw-r--r--source/blender/editors/include/UI_icons.h1
-rw-r--r--source/blender/editors/include/UI_interface.h60
-rw-r--r--source/blender/editors/interface/interface.c193
-rw-r--r--source/blender/editors/interface/interface_context_menu.c29
-rw-r--r--source/blender/editors/interface/interface_eyedropper_gpencil_color.c1
-rw-r--r--source/blender/editors/interface/interface_handlers.c113
-rw-r--r--source/blender/editors/interface/interface_icons.c48
-rw-r--r--source/blender/editors/interface/interface_intern.h36
-rw-r--r--source/blender/editors/interface/interface_layout.c204
-rw-r--r--source/blender/editors/interface/interface_ops.c17
-rw-r--r--source/blender/editors/interface/interface_region_color_picker.c197
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c68
-rw-r--r--source/blender/editors/interface/interface_style.c8
-rw-r--r--source/blender/editors/interface/interface_templates.c1097
-rw-r--r--source/blender/editors/interface/interface_widgets.c64
-rw-r--r--source/blender/editors/interface/view2d_ops.c72
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c2
-rw-r--r--source/blender/editors/mesh/editmesh_select.c3
-rw-r--r--source/blender/editors/mesh/editmesh_select_similar.c1
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c8
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c1
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c6
-rw-r--r--source/blender/editors/metaball/editmball_undo.c2
-rw-r--r--source/blender/editors/object/CMakeLists.txt3
-rw-r--r--source/blender/editors/object/object_add.c14
-rw-r--r--source/blender/editors/object/object_bake.c1
-rw-r--r--source/blender/editors/object/object_constraint.c5
-rw-r--r--source/blender/editors/object/object_gpencil_modifier.c10
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_modifier.c5
-rw-r--r--source/blender/editors/object/object_ops.c1
-rw-r--r--source/blender/editors/object/object_relations.c27
-rw-r--r--source/blender/editors/object/object_shader_fx.c54
-rw-r--r--source/blender/editors/object/object_vgroup.c19
-rw-r--r--source/blender/editors/physics/particle_object.c3
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c1
-rw-r--r--source/blender/editors/physics/rigidbody_object.c1
-rw-r--r--source/blender/editors/render/render_intern.h3
-rw-r--r--source/blender/editors/render/render_internal.c142
-rw-r--r--source/blender/editors/render/render_opengl.c2
-rw-r--r--source/blender/editors/render/render_ops.c3
-rw-r--r--source/blender/editors/render/render_preview.c301
-rw-r--r--source/blender/editors/render/render_shading.c236
-rw-r--r--source/blender/editors/screen/screen_context.c10
-rw-r--r--source/blender/editors/screen/screen_edit.c186
-rw-r--r--source/blender/editors/screen/screen_ops.c5
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt1
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c3
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h1
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c10
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_ops.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c259
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c37
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_detail.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_face_set.c97
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_color.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mask.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mesh.c6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h41
-rw-r--r--source/blender/editors/sound/sound_ops.c36
-rw-r--r--source/blender/editors/space_action/action_data.c187
-rw-r--r--source/blender/editors/space_action/action_edit.c2
-rw-r--r--source/blender/editors/space_action/action_intern.h1
-rw-r--r--source/blender/editors/space_action/action_ops.c2
-rw-r--r--source/blender/editors/space_action/action_select.c4
-rw-r--r--source/blender/editors/space_api/spacetypes.c4
-rw-r--r--source/blender/editors/space_buttons/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c11
-rw-r--r--source/blender/editors/space_buttons/buttons_intern.h1
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c2
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c1
-rw-r--r--source/blender/editors/space_clip/clip_ops.c2
-rw-r--r--source/blender/editors/space_console/space_console.c4
-rw-r--r--source/blender/editors/space_file/file_draw.c228
-rw-r--r--source/blender/editors/space_file/file_intern.h4
-rw-r--r--source/blender/editors/space_file/file_ops.c347
-rw-r--r--source/blender/editors/space_file/file_panels.c11
-rw-r--r--source/blender/editors/space_file/file_utils.c17
-rw-r--r--source/blender/editors/space_file/filelist.c652
-rw-r--r--source/blender/editors/space_file/filelist.h19
-rw-r--r--source/blender/editors/space_file/filesel.c257
-rw-r--r--source/blender/editors/space_file/space_file.c253
-rw-r--r--source/blender/editors/space_graph/CMakeLists.txt2
-rw-r--r--source/blender/editors/space_graph/graph_edit.c174
-rw-r--r--source/blender/editors/space_graph/graph_select.c4
-rw-r--r--source/blender/editors/space_graph/graph_view.c2
-rw-r--r--source/blender/editors/space_image/image_buttons.c145
-rw-r--r--source/blender/editors/space_image/image_edit.c3
-rw-r--r--source/blender/editors/space_image/image_ops.c4
-rw-r--r--source/blender/editors/space_info/info_report.c2
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c5
-rw-r--r--source/blender/editors/space_nla/nla_channels.c17
-rw-r--r--source/blender/editors/space_nla/nla_edit.c99
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt2
-rw-r--r--source/blender/editors/space_node/drawnode.c216
-rw-r--r--source/blender/editors/space_node/node_draw.c63
-rw-r--r--source/blender/editors/space_node/node_edit.c344
-rw-r--r--source/blender/editors/space_node/node_view.c2
-rw-r--r--source/blender/editors/space_node/space_node.c8
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt7
-rw-r--r--source/blender/editors/space_outliner/outliner_context.c73
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.c22
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c11
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h7
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c10
-rw-r--r--source/blender/editors/space_outliner/outliner_sync.c6
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c31
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c6
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c1
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_data.cc2
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_libraries.cc2
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_orphaned.cc2
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_scenes.cc4
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_sequencer.cc8
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_view_layer.cc1
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element.h2
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element_nla.hh1
-rw-r--r--source/blender/editors/space_script/script_edit.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c129
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c330
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c685
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h3
-rw-r--r--source/blender/editors/space_sequencer/sequencer_modifier.c38
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_proxy.c15
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c106
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c10
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c9
-rw-r--r--source/blender/editors/space_text/space_text.c2
-rw-r--r--source/blender/editors/space_text/text_header.c98
-rw-r--r--source/blender/editors/space_text/text_ops.c2
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c67
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt2
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c26
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c9
-rw-r--r--source/blender/editors/space_view3d/view3d_placement.c11
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c35
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c28
-rw-r--r--source/blender/editors/transform/CMakeLists.txt2
-rw-r--r--source/blender/editors/transform/transform.c18
-rw-r--r--source/blender/editors/transform/transform.h2
-rw-r--r--source/blender/editors/transform/transform_convert.c2
-rw-r--r--source/blender/editors/transform/transform_convert.h3
-rw-r--r--source/blender/editors/transform/transform_convert_armature.c28
-rw-r--r--source/blender/editors/transform/transform_convert_nla.c16
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c80
-rw-r--r--source/blender/editors/transform/transform_mode_edge_seq_slide.c30
-rw-r--r--source/blender/editors/transform/transform_mode_shrink_fatten.c28
-rw-r--r--source/blender/editors/transform/transform_mode_translate.c3
-rw-r--r--source/blender/editors/transform/transform_ops.c2
-rw-r--r--source/blender/editors/transform/transform_snap.c3
-rw-r--r--source/blender/editors/transform/transform_snap.h2
-rw-r--r--source/blender/editors/undo/memfile_undo.c1
-rw-r--r--source/blender/editors/util/CMakeLists.txt2
-rw-r--r--source/blender/editors/util/ed_util.c102
-rw-r--r--source/blender/editors/util/ed_util_imbuf.c3
-rw-r--r--source/blender/editors/util/ed_util_ops.c155
-rw-r--r--source/blender/editors/uvedit/CMakeLists.txt2
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h1
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c2
213 files changed, 6740 insertions, 3250 deletions
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
index 1f5dc73f732..a2ae350ce4b 100644
--- a/source/blender/editors/CMakeLists.txt
+++ b/source/blender/editors/CMakeLists.txt
@@ -22,6 +22,7 @@ if(WITH_BLENDER)
add_subdirectory(animation)
add_subdirectory(armature)
+ add_subdirectory(asset)
add_subdirectory(curve)
add_subdirectory(geometry)
add_subdirectory(gizmo_library)
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index c70a86eab1d..6cb829d3a23 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -5353,7 +5353,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
"",
ICON_NONE,
offset,
- ymid,
+ rect->ymin,
SLIDER_WIDTH,
channel_height);
UI_but_func_set(but, achannel_setting_slider_nla_curve_cb, ale->id, ale->data);
@@ -5411,7 +5411,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
"",
icon,
offset,
- ymid,
+ rect->ymin,
ICON_WIDTH,
channel_height);
}
@@ -5437,7 +5437,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
"",
icon,
offset,
- ymid,
+ rect->ymin,
ICON_WIDTH,
channel_height);
}
@@ -5457,7 +5457,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
"",
ICON_NONE,
offset,
- ymid,
+ rect->ymin,
width,
channel_height);
}
@@ -5483,7 +5483,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
"",
ICON_NONE,
offset,
- ymid,
+ rect->ymin,
SLIDER_WIDTH,
channel_height);
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index ba3796ad245..124992bed71 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -49,6 +49,7 @@
#include "BKE_gpencil.h"
#include "BKE_lib_id.h"
#include "BKE_mask.h"
+#include "BKE_nla.h"
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
@@ -1063,18 +1064,27 @@ static void rearrange_animchannels_filter_visible(ListBase *anim_data_visible,
eAnim_ChannelType type)
{
ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale, *ale_next;
- int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ eAnimFilter_Flags filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
+ ANIMFILTER_LIST_CHANNELS);
/* get all visible channels */
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* now, only keep the ones that are of the types we are interested in */
- for (ale = anim_data.first; ale; ale = ale_next) {
- ale_next = ale->next;
-
+ LISTBASE_FOREACH_MUTABLE (bAnimListElem *, ale, &anim_data) {
if (ale->type != type) {
BLI_freelinkN(&anim_data, ale);
+ continue;
+ }
+
+ if (type == ANIMTYPE_NLATRACK) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+
+ if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
+ /* No re-arrangement of non-local tracks of override data. */
+ BLI_freelinkN(&anim_data, ale);
+ continue;
+ }
}
}
@@ -1146,6 +1156,7 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn
{
AnimChanRearrangeFp rearrange_func;
ListBase anim_data_visible = {NULL, NULL};
+ const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ac->obact);
/* hack: invert mode so that functions will work in right order */
mode *= -1;
@@ -1156,6 +1167,29 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn
return;
}
+ /* In liboverride case, we need to extract non-local NLA tracks from current anim data before we
+ * can perform the move, and add then back afterwards. It's the only way to prevent them from
+ * being affected by the reordering.
+ *
+ * Note that both override apply code for NLA tracks collection, and NLA editing code, are
+ * responsible to ensure that non-local tracks always remain first in the list. */
+ ListBase extracted_nonlocal_nla_tracks = {NULL, NULL};
+ if (is_liboverride) {
+ NlaTrack *nla_track;
+ for (nla_track = adt->nla_tracks.first; nla_track != NULL; nla_track = nla_track->next) {
+ if (!BKE_nlatrack_is_nonlocal_in_liboverride(&ac->obact->id, nla_track)) {
+ break;
+ }
+ }
+ if (nla_track != NULL && nla_track->prev != NULL) {
+ extracted_nonlocal_nla_tracks.first = adt->nla_tracks.first;
+ extracted_nonlocal_nla_tracks.last = nla_track->prev;
+ adt->nla_tracks.first = nla_track;
+ nla_track->prev->next = NULL;
+ nla_track->prev = NULL;
+ }
+ }
+
/* Filter visible data. */
rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLATRACK);
@@ -1163,6 +1197,14 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn
rearrange_animchannel_islands(
&adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK, &anim_data_visible);
+ /* Add back non-local NLA tracks at the begining of the animation data's list. */
+ if (!BLI_listbase_is_empty(&extracted_nonlocal_nla_tracks)) {
+ BLI_assert(is_liboverride);
+ ((NlaTrack *)extracted_nonlocal_nla_tracks.last)->next = adt->nla_tracks.first;
+ ((NlaTrack *)adt->nla_tracks.first)->prev = extracted_nonlocal_nla_tracks.last;
+ adt->nla_tracks.first = extracted_nonlocal_nla_tracks.first;
+ }
+
/* free temp data */
BLI_freelistN(&anim_data_visible);
}
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index e552a321bca..17251587d3b 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -50,6 +50,7 @@
#include "RNA_access.h"
#include "SEQ_sequencer.h"
+#include "SEQ_utils.h"
#include "ED_anim_api.h"
@@ -212,15 +213,17 @@ static void animchan_sync_fcurve_scene(bAnimListElem *ale)
return;
}
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
/* get strip name, and check if this strip is selected */
char *seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all[");
- Sequence *seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false);
- if (seq_name) {
- MEM_freeN(seq_name);
+ if (seq_name == NULL) {
+ return;
}
+ Sequence *seq = SEQ_get_sequence_by_name(ed->seqbasep, seq_name, false);
+ MEM_freeN(seq_name);
+
if (seq == NULL) {
return;
}
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 2e65fff69f1..f2022194ed5 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -101,6 +101,7 @@
#include "ED_markers.h"
#include "SEQ_sequencer.h"
+#include "SEQ_utils.h"
#include "UI_resources.h" /* for TH_KEYFRAME_SCALE lookup */
@@ -225,7 +226,7 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
{
/* TODO, other methods to get the mask */
#if 0
- Sequence *seq = BKE_sequencer_active_get(ac->scene);
+ Sequence *seq = SEQ_select_active_get(ac->scene);
MovieClip *clip = ac->scene->clip;
struct Mask *mask = seq ? seq->mask : NULL;
#endif
@@ -1063,13 +1064,12 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id
/* only consider if F-Curve involves pose.bones */
if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) {
- bPoseChannel *pchan;
- char *bone_name;
/* get bone-name, and check if this bone is selected */
- bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
- pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+ bPoseChannel *pchan = NULL;
+ char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
if (bone_name) {
+ pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
MEM_freeN(bone_name);
}
@@ -1104,15 +1104,14 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id
/* only consider if F-Curve involves sequence_editor.sequences */
if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq = NULL;
- char *seq_name;
if (ed) {
/* get strip name, and check if this strip is selected */
- seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all[");
- seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false);
+ char *seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all[");
if (seq_name) {
+ seq = SEQ_get_sequence_by_name(ed->seqbasep, seq_name, false);
MEM_freeN(seq_name);
}
}
@@ -1130,13 +1129,12 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id
/* check for selected nodes */
if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) {
- bNode *node;
- char *node_name;
+ bNode *node = NULL;
/* get strip name, and check if this strip is selected */
- node_name = BLI_str_quoted_substrN(fcu->rna_path, "nodes[");
- node = nodeFindNodebyName(ntree, node_name);
+ char *node_name = BLI_str_quoted_substrN(fcu->rna_path, "nodes[");
if (node_name) {
+ node = nodeFindNodebyName(ntree, node_name);
MEM_freeN(node_name);
}
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index 72103d68b05..5992545bdbe 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -112,7 +112,8 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
char *constName = BLI_str_quoted_substrN(fcu->rna_path, "constraints[");
/* assemble the string to display in the UI... */
- structname = BLI_sprintfN("%s : %s", pchanName, constName);
+ structname = BLI_sprintfN(
+ "%s : %s", pchanName ? pchanName : "", constName ? constName : "");
free_structname = 1;
/* free the temp names */
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 9e622aea6ab..a5514f6517e 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -56,6 +56,7 @@
#include "DEG_depsgraph_query.h"
#include "SEQ_sequencer.h"
+#include "SEQ_time.h"
#include "anim_intern.h"
@@ -93,7 +94,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
if (do_snap) {
if (CTX_wm_space_seq(C)) {
- frame = BKE_sequencer_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false);
+ frame = SEQ_time_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false);
}
else {
frame = BKE_scene_frame_snap_by_seconds(scene, 1.0, frame);
@@ -503,7 +504,7 @@ static void ANIM_OT_previewrange_clear(wmOperatorType *ot)
/* identifiers */
ot->name = "Clear Preview Range";
ot->idname = "ANIM_OT_previewrange_clear";
- ot->description = "Clear Preview Range";
+ ot->description = "Clear preview range";
/* api callbacks */
ot->exec = previewrange_clear_exec;
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index 08b02020f76..6ed9803dbd3 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -767,16 +767,15 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
* Storing the relevant information here helps avoiding crashes if we undo-repaste. */
if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) {
Object *ob = (Object *)aci->id;
- bPoseChannel *pchan;
- char *bone_name;
- bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones[");
- pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
- if (pchan) {
- aci->is_bone = true;
- }
+ char *bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones[");
if (bone_name) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
MEM_freeN(bone_name);
+
+ if (pchan) {
+ aci->is_bone = true;
+ }
}
}
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 09c33c48170..e8146ca960a 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -2236,20 +2236,18 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
/* in pose mode, only delete the F-Curve if it belongs to a selected bone */
if (ob->mode & OB_MODE_POSE) {
if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones[")) {
- bPoseChannel *pchan;
- char *bone_name;
/* get bone-name, and check if this bone is selected */
- bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
- pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+ char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
if (bone_name) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
MEM_freeN(bone_name);
- }
- /* delete if bone is selected*/
- if ((pchan) && (pchan->bone)) {
- if (pchan->bone->flag & BONE_SELECTED) {
- can_delete = true;
+ /* delete if bone is selected*/
+ if ((pchan) && (pchan->bone)) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ can_delete = true;
+ }
}
}
}
@@ -2342,13 +2340,12 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op)
* In object mode, we're dealing with the entire object.
*/
if ((ob->mode & OB_MODE_POSE) && strstr(fcu->rna_path, "pose.bones[\"")) {
- bPoseChannel *pchan;
- char *bone_name;
+ bPoseChannel *pchan = NULL;
/* get bone-name, and check if this bone is selected */
- bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
- pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+ char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
if (bone_name) {
+ pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
MEM_freeN(bone_name);
}
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index b20d2738bda..f2cb00f67f0 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -1014,7 +1014,7 @@ void ARMATURE_OT_switch_direction(wmOperatorType *ot)
/* identifiers */
ot->name = "Switch Direction";
ot->idname = "ARMATURE_OT_switch_direction";
- ot->description = "Change the direction that a chain of bones points in (head <-> tail swap)";
+ ot->description = "Change the direction that a chain of bones points in (head and tail swap)";
/* api callbacks */
ot->exec = armature_switch_direction_exec;
diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c
index c217b615db6..7c11c5e537e 100644
--- a/source/blender/editors/armature/editarmature_undo.c
+++ b/source/blender/editors/armature/editarmature_undo.c
@@ -26,7 +26,9 @@
#include "CLG_log.h"
#include "DNA_armature_types.h"
+#include "DNA_layer_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BLI_array_utils.h"
#include "BLI_listbase.h"
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 731d0d10e0b..6a03207b3b0 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -1090,6 +1090,7 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, bool ex
if (boneName) {
bPoseChannel *pchan = BKE_pose_channel_find_name(pose, boneName);
+ MEM_freeN(boneName);
if (pchan) {
/* select if bone is visible and can be affected */
@@ -1098,9 +1099,6 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, bool ex
changed = true;
}
}
-
- /* free temp memory */
- MEM_freeN(boneName);
}
}
}
diff --git a/source/blender/editors/asset/CMakeLists.txt b/source/blender/editors/asset/CMakeLists.txt
new file mode 100644
index 00000000000..63a1761b264
--- /dev/null
+++ b/source/blender/editors/asset/CMakeLists.txt
@@ -0,0 +1,39 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ ../include
+ ../../blenlib
+ ../../blenkernel
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+)
+
+set(INC_SYS
+)
+
+set(SRC
+ asset_edit.c
+ asset_ops.c
+)
+
+set(LIB
+)
+
+blender_add_lib(bf_editor_asset "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/asset/asset_edit.c b/source/blender/editors/asset/asset_edit.c
new file mode 100644
index 00000000000..5333c08c66a
--- /dev/null
+++ b/source/blender/editors/asset/asset_edit.c
@@ -0,0 +1,69 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edasset
+ */
+
+#include "BKE_asset.h"
+#include "BKE_context.h"
+#include "BKE_idtype.h"
+#include "BKE_lib_id.h"
+
+#include "DNA_ID.h"
+#include "DNA_asset_types.h"
+
+#include "UI_interface_icons.h"
+
+#include "RNA_access.h"
+
+#include "ED_asset.h"
+
+bool ED_asset_mark_id(const bContext *C, ID *id)
+{
+ if (id->asset_data) {
+ return false;
+ }
+ if (!BKE_id_can_be_asset(id)) {
+ return false;
+ }
+
+ id_fake_user_set(id);
+
+ id->asset_data = BKE_asset_metadata_create();
+
+ UI_icon_render_id(C, NULL, id, true, true);
+
+ return true;
+}
+
+bool ED_asset_clear_id(ID *id)
+{
+ if (!id->asset_data) {
+ return false;
+ }
+ BKE_asset_metadata_free(&id->asset_data);
+ /* Don't clear fake user here, there's no guarantee that it was actually set by
+ * #ED_asset_mark_id(), it might have been something/someone else. */
+
+ return true;
+}
+
+bool ED_asset_can_make_single_from_context(const bContext *C)
+{
+ /* Context needs a "id" pointer to be set for #ASSET_OT_mark()/#ASSET_OT_clear() to use. */
+ return CTX_data_pointer_get_type_silent(C, "id", &RNA_ID).data != NULL;
+}
diff --git a/source/blender/editors/asset/asset_ops.c b/source/blender/editors/asset/asset_ops.c
new file mode 100644
index 00000000000..929d49e19fa
--- /dev/null
+++ b/source/blender/editors/asset/asset_ops.c
@@ -0,0 +1,238 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edasset
+ */
+
+#include <string.h>
+
+#include "BKE_asset.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string_utils.h"
+
+#include "DNA_asset_types.h"
+
+#include "ED_asset.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* -------------------------------------------------------------------- */
+
+struct AssetMarkResultStats {
+ int tot_created;
+ int tot_already_asset;
+ ID *last_id;
+};
+
+/**
+ * Return the IDs to operate on as list of #CollectionPointerLink links. Needs freeing.
+ */
+static ListBase /* CollectionPointerLink */ asset_operation_get_ids_from_context(const bContext *C)
+{
+ ListBase list = {0};
+
+ PointerRNA idptr = CTX_data_pointer_get_type(C, "id", &RNA_ID);
+
+ if (idptr.data) {
+ CollectionPointerLink *ctx_link = MEM_callocN(sizeof(*ctx_link), __func__);
+ ctx_link->ptr = idptr;
+ BLI_addtail(&list, ctx_link);
+ }
+ else {
+ CTX_data_selected_ids(C, &list);
+ }
+
+ return list;
+}
+
+static void asset_mark_for_idptr_list(const bContext *C,
+ const ListBase /* CollectionPointerLink */ *ids,
+ struct AssetMarkResultStats *r_stats)
+{
+ memset(r_stats, 0, sizeof(*r_stats));
+
+ LISTBASE_FOREACH (CollectionPointerLink *, ctx_id, ids) {
+ BLI_assert(RNA_struct_is_ID(ctx_id->ptr.type));
+
+ ID *id = ctx_id->ptr.data;
+ if (id->asset_data) {
+ r_stats->tot_already_asset++;
+ continue;
+ }
+
+ if (ED_asset_mark_id(C, id)) {
+ r_stats->last_id = id;
+ r_stats->tot_created++;
+ }
+ }
+}
+
+static bool asset_mark_results_report(const struct AssetMarkResultStats *stats,
+ ReportList *reports)
+{
+ /* User feedback on failure. */
+ if ((stats->tot_created < 1) && (stats->tot_already_asset > 0)) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Selected data-blocks are already assets (or do not support use as assets)");
+ return false;
+ }
+ if (stats->tot_created < 1) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "No data-blocks to create assets for found (or do not support use as assets)");
+ return false;
+ }
+
+ /* User feedback on success. */
+ if (stats->tot_created == 1) {
+ /* If only one data-block: Give more useful message by printing asset name. */
+ BKE_reportf(reports, RPT_INFO, "Data-block '%s' is now an asset", stats->last_id->name + 2);
+ }
+ else {
+ BKE_reportf(reports, RPT_INFO, "%i data-blocks are now assets", stats->tot_created);
+ }
+
+ return true;
+}
+
+static int asset_mark_exec(bContext *C, wmOperator *op)
+{
+ ListBase ids = asset_operation_get_ids_from_context(C);
+
+ struct AssetMarkResultStats stats;
+ asset_mark_for_idptr_list(C, &ids, &stats);
+ BLI_freelistN(&ids);
+
+ if (!asset_mark_results_report(&stats, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_main_add_notifier(NC_ID | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_ASSET | NA_ADDED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void ASSET_OT_mark(wmOperatorType *ot)
+{
+ ot->name = "Mark Asset";
+ ot->description =
+ "Enable easier reuse of selected data-blocks through the Asset Browser, with the help of "
+ "customizable metadata (like previews, descriptions and tags)";
+ ot->idname = "ASSET_OT_mark";
+
+ ot->exec = asset_mark_exec;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* -------------------------------------------------------------------- */
+
+struct AssetClearResultStats {
+ int tot_removed;
+ ID *last_id;
+};
+
+static void asset_clear_from_idptr_list(const ListBase /* CollectionPointerLink */ *ids,
+ struct AssetClearResultStats *r_stats)
+{
+ memset(r_stats, 0, sizeof(*r_stats));
+
+ LISTBASE_FOREACH (CollectionPointerLink *, ctx_id, ids) {
+ BLI_assert(RNA_struct_is_ID(ctx_id->ptr.type));
+
+ ID *id = ctx_id->ptr.data;
+ if (!id->asset_data) {
+ continue;
+ }
+
+ if (ED_asset_clear_id(id)) {
+ r_stats->tot_removed++;
+ r_stats->last_id = id;
+ }
+ }
+}
+
+static bool asset_clear_result_report(const struct AssetClearResultStats *stats,
+ ReportList *reports)
+
+{
+ if (stats->tot_removed < 1) {
+ BKE_report(reports, RPT_ERROR, "No asset data-blocks selected/focused");
+ return false;
+ }
+
+ if (stats->tot_removed == 1) {
+ /* If only one data-block: Give more useful message by printing asset name. */
+ BKE_reportf(
+ reports, RPT_INFO, "Data-block '%s' is no asset anymore", stats->last_id->name + 2);
+ }
+ else {
+ BKE_reportf(reports, RPT_INFO, "%i data-blocks are no assets anymore", stats->tot_removed);
+ }
+
+ return true;
+}
+
+static int asset_clear_exec(bContext *C, wmOperator *op)
+{
+ ListBase ids = asset_operation_get_ids_from_context(C);
+
+ struct AssetClearResultStats stats;
+ asset_clear_from_idptr_list(&ids, &stats);
+ BLI_freelistN(&ids);
+
+ if (!asset_clear_result_report(&stats, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_main_add_notifier(NC_ID | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_ASSET | NA_REMOVED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void ASSET_OT_clear(wmOperatorType *ot)
+{
+ ot->name = "Clear Asset";
+ ot->description =
+ "Delete all asset metadata and turn the selected asset data-blocks back into normal "
+ "data-blocks";
+ ot->idname = "ASSET_OT_clear";
+
+ ot->exec = asset_clear_exec;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* -------------------------------------------------------------------- */
+
+void ED_operatortypes_asset(void)
+{
+ WM_operatortype_append(ASSET_OT_mark);
+ WM_operatortype_append(ASSET_OT_clear);
+}
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index db472c9ffa7..2b627971286 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -3838,7 +3838,7 @@ void CURVE_OT_subdivide(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of cuts", "", 1, 10);
+ prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of Cuts", "", 1, 10);
/* Avoid re-using last var because it can cause _very_ high poly meshes
* and annoy users (or worse crash). */
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 361c5d4048e..6ec7fbe80b6 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -657,6 +657,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
brush.sculpt.mask
brush.sculpt.multiplane_scrape
brush.sculpt.nudge
+ brush.sculpt.paint
brush.sculpt.pinch
brush.sculpt.pose
brush.sculpt.rotate
diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
index f7caf8e4c6a..8755dea51e1 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
@@ -50,7 +50,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "wm.h"
/* own includes */
#include "../gizmo_geometry.h"
@@ -66,7 +65,13 @@ typedef struct SnapGizmo3D {
/* We could have other snap contexts, for now only support 3D view. */
SnapObjectContext *snap_context_v3d;
- int mval[2];
+
+ /* Copy of the parameters of the last event state in order to detect updates. */
+ struct {
+ int x;
+ int y;
+ short shift, ctrl, alt, oskey;
+ } last_eventstate;
#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
wmKeyMap *keymap;
@@ -77,6 +82,37 @@ typedef struct SnapGizmo3D {
short snap_elem;
} SnapGizmo3D;
+/* Checks if the current event is different from the one captured in the last update. */
+static bool eventstate_has_changed(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm)
+{
+ if (wm && wm->winactive) {
+ const wmEvent *event = wm->winactive->eventstate;
+ if ((event->x != snap_gizmo->last_eventstate.x) ||
+ (event->y != snap_gizmo->last_eventstate.y) ||
+ (event->ctrl != snap_gizmo->last_eventstate.ctrl) ||
+ (event->shift != snap_gizmo->last_eventstate.shift) ||
+ (event->alt != snap_gizmo->last_eventstate.alt) ||
+ (event->oskey != snap_gizmo->last_eventstate.oskey)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Copies the current eventstate. */
+static void eventstate_save(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm)
+{
+ if (wm && wm->winactive) {
+ const wmEvent *event = wm->winactive->eventstate;
+ snap_gizmo->last_eventstate.x = event->x;
+ snap_gizmo->last_eventstate.y = event->y;
+ snap_gizmo->last_eventstate.ctrl = event->ctrl;
+ snap_gizmo->last_eventstate.shift = event->shift;
+ snap_gizmo->last_eventstate.alt = event->alt;
+ snap_gizmo->last_eventstate.oskey = event->oskey;
+ }
+}
+
#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm)
{
@@ -84,6 +120,15 @@ static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm)
return false;
}
+ const wmEvent *event = wm->winactive->eventstate;
+ if ((event->ctrl == snap_gizmo->last_eventstate.ctrl) &&
+ (event->shift == snap_gizmo->last_eventstate.shift) &&
+ (event->alt == snap_gizmo->last_eventstate.alt) &&
+ (event->oskey == snap_gizmo->last_eventstate.oskey)) {
+ /* Nothing has changed. */
+ return snap_gizmo->invert_snap;
+ }
+
if (snap_gizmo->keymap == NULL) {
/* Lazy initialization. */
snap_gizmo->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map");
@@ -92,7 +137,6 @@ static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm)
const int snap_on = snap_gizmo->snap_on;
wmKeyMap *keymap = WM_keymap_active(wm, snap_gizmo->keymap);
- const wmEvent *event = wm->winactive->eventstate;
for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
if (kmi->flag & KMI_INACTIVE) {
continue;
@@ -250,12 +294,6 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
float r_nor[3])
{
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
- Scene *scene = DEG_get_input_scene(depsgraph);
- float co[3], no[3];
- short snap_elem = 0;
- int snap_elem_index[3] = {-1, -1, -1};
- int index = -1;
-
if (snap_gizmo->use_snap_override != -1) {
if (snap_gizmo->use_snap_override == false) {
snap_gizmo->snap_elem = 0;
@@ -265,7 +303,12 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
snap_gizmo->invert_snap = invert_snap(snap_gizmo, wm);
+#endif
+ eventstate_save(snap_gizmo, wm);
+ Scene *scene = DEG_get_input_scene(depsgraph);
+
+#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
if (snap_gizmo->use_snap_override == -1) {
const ToolSettings *ts = scene->toolsettings;
if (snap_gizmo->invert_snap != !(ts->snap_flag & SCE_SNAP)) {
@@ -273,10 +316,13 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
return 0;
}
}
-#else
- UNUSED_VARS(wm);
#endif
+ float co[3], no[3];
+ short snap_elem = 0;
+ int snap_elem_index[3] = {-1, -1, -1};
+ int index = -1;
+
wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "snap_elements");
int snap_elements = RNA_property_enum_get(&gz_prop->ptr, gz_prop->prop);
if (gz_prop->prop != snap_gizmo->prop_snap_force) {
@@ -381,14 +427,17 @@ static void snap_gizmo_draw(const bContext *C, wmGizmo *gz)
return;
}
- ARegion *region = CTX_wm_region(C);
- RegionView3D *rv3d = region->regiondata;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (eventstate_has_changed(snap_gizmo, wm)) {
+ /* The eventstate has changed but the snap has not been updated.
+ * This means that the current position is no longer valid. */
+ snap_gizmo->snap_elem = 0;
+ return;
+ }
- /* Ideally, we shouldn't assign values here.
- * But `test_select` is not called during navigation.
- * And `snap_elem` is not really useful in this case. */
- if ((rv3d->rflag & RV3D_NAVIGATING) ||
- (!(gz->state & WM_GIZMO_STATE_HIGHLIGHT) && !wm_gizmomap_modal_get(region->gizmo_map))) {
+ RegionView3D *rv3d = CTX_wm_region_data(C);
+ if (rv3d->rflag & RV3D_NAVIGATING) {
+ /* Don't draw the gizmo while navigating. It can be distracting. */
snap_gizmo->snap_elem = 0;
return;
}
@@ -418,30 +467,17 @@ static void snap_gizmo_draw(const bContext *C, wmGizmo *gz)
static int snap_gizmo_test_select(bContext *C, wmGizmo *gz, const int mval[2])
{
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
-
-#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
wmWindowManager *wm = CTX_wm_manager(C);
- const bool invert = invert_snap(snap_gizmo, wm);
- if (snap_gizmo->invert_snap == invert && snap_gizmo->mval[0] == mval[0] &&
- snap_gizmo->mval[1] == mval[1]) {
+ if (!eventstate_has_changed(snap_gizmo, wm)) {
/* Performance, do not update. */
return snap_gizmo->snap_elem ? 0 : -1;
}
- snap_gizmo->invert_snap = invert;
-#else
- if (snap_gizmo->mval[0] == mval[0] && snap_gizmo->mval[1] == mval[1]) {
- /* Performance, do not update. */
- return snap_gizmo->snap_elem ? 0 : -1;
- }
-#endif
- copy_v2_v2_int(snap_gizmo->mval, mval);
-
ARegion *region = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
const float mval_fl[2] = {UNPACK2(mval)};
short snap_elem = ED_gizmotypes_snap_3d_update(
- gz, CTX_data_ensure_evaluated_depsgraph(C), region, v3d, NULL, mval_fl, NULL, NULL);
+ gz, CTX_data_ensure_evaluated_depsgraph(C), region, v3d, wm, mval_fl, NULL, NULL);
if (snap_elem) {
ED_region_tag_redraw_editor_overlays(region);
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 93767127cc7..4e2951c3571 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -41,6 +41,7 @@
#include "DNA_brush_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c
index 315b3c281da..65141442237 100644
--- a/source/blender/editors/gpencil/gpencil_add_monkey.c
+++ b/source/blender/editors/gpencil/gpencil_add_monkey.c
@@ -25,6 +25,7 @@
#include "BLI_utildefines.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c
index f26fd936d40..0c8cc621a3b 100644
--- a/source/blender/editors/gpencil/gpencil_add_stroke.c
+++ b/source/blender/editors/gpencil/gpencil_add_stroke.c
@@ -25,6 +25,7 @@
#include "BLI_utildefines.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index 63aa242275a..09b57029350 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -41,6 +41,7 @@
#include "DNA_collection_types.h"
#include "DNA_curve_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 33a1469beab..aff109eb98e 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -42,6 +42,7 @@
#include "DNA_anim_types.h"
#include "DNA_brush_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
@@ -1330,19 +1331,24 @@ static int gpencil_merge_layer_exec(bContext *C, wmOperator *op)
BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_dst->framenum), gpf_dst);
}
- /* Read all frames from merge layer and add any missing in destination layer. */
+ /* Read all frames from merge layer and add any missing in destination layer,
+ * copying all previous strokes to keep the image equals.
+ * Need to do it in a separated loop to avoid strokes accumulation. */
LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
/* Try to find frame in destination layer hash table. */
bGPDframe *gpf_dst = BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum));
if (!gpf_dst) {
- gpf_dst = BKE_gpencil_frame_addnew(gpl_dst, gpf_src->framenum);
- /* Duplicate strokes into destination frame. */
- if (gpf_dst) {
- BKE_gpencil_frame_copy_strokes(gpf_src, gpf_dst);
- }
+ gpf_dst = BKE_gpencil_layer_frame_get(gpl_dst, gpf_src->framenum, GP_GETFRAME_ADD_COPY);
+ BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum), gpf_dst);
}
- else {
- /* Add to tail all strokes. */
+ }
+
+ /* Read all frames from merge layer and add strokes. */
+ LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
+ /* Try to find frame in destination layer hash table. */
+ bGPDframe *gpf_dst = BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum));
+ /* Add to tail all strokes. */
+ if (gpf_dst) {
BLI_movelisttolist(&gpf_dst->strokes, &gpf_src->strokes);
}
}
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 95c94f8cfed..36e383cf3c2 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -41,6 +41,7 @@
#include "DNA_gpencil_modifier_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 93941ea3766..39968aac9fa 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -35,6 +35,7 @@
#include "DNA_brush_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_image_types.h"
+#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_windowmanager_types.h"
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 3617f20763e..1c967110198 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -283,8 +283,8 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer");
tgpil->gpl = gpl;
- tgpil->prevFrame = gpl->actframe;
- tgpil->nextFrame = gpl->actframe->next;
+ tgpil->prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe);
+ tgpil->nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next);
BLI_addtail(&tgpi->ilayers, tgpil);
@@ -326,24 +326,25 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
valid = false;
}
- /* create new stroke */
- new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
-
if (valid) {
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
if (gps_from->totpoints > gps_to->totpoints) {
- new_stroke->points = MEM_recallocN(new_stroke->points,
- sizeof(*new_stroke->points) * gps_to->totpoints);
- if (new_stroke->dvert != NULL) {
- new_stroke->dvert = MEM_recallocN(new_stroke->dvert,
- sizeof(*new_stroke->dvert) * gps_to->totpoints);
- }
- new_stroke->totpoints = gps_to->totpoints;
+ BKE_gpencil_stroke_uniform_subdivide(gpd, gps_to, gps_from->totpoints, true);
}
- /* update points position */
+ if (gps_to->totpoints > gps_from->totpoints) {
+ BKE_gpencil_stroke_uniform_subdivide(gpd, gps_from, gps_to->totpoints, true);
+ }
+
+ /* Create new stroke. */
+ new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
+
+ /* Update points position. */
gpencil_interpolate_update_points(gps_from, gps_to, new_stroke, tgpil->factor);
}
else {
+ /* Create new stroke. */
+ new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
+
/* need an empty stroke to keep index correct for lookup, but resize to smallest size */
new_stroke->totpoints = 0;
new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points));
@@ -443,12 +444,16 @@ static void gpencil_interpolate_exit(bContext *C, wmOperator *op)
/* finally, free memory used by temp data */
LISTBASE_FOREACH (tGPDinterpolate_layer *, tgpil, &tgpi->ilayers) {
+ BKE_gpencil_free_strokes(tgpil->prevFrame);
+ BKE_gpencil_free_strokes(tgpil->nextFrame);
BKE_gpencil_free_strokes(tgpil->interFrame);
- MEM_freeN(tgpil->interFrame);
+ MEM_SAFE_FREE(tgpil->prevFrame);
+ MEM_SAFE_FREE(tgpil->nextFrame);
+ MEM_SAFE_FREE(tgpil->interFrame);
}
BLI_freelistN(&tgpi->ilayers);
- MEM_freeN(tgpi);
+ MEM_SAFE_FREE(tgpi);
}
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
@@ -478,14 +483,15 @@ static bool gpencil_interpolate_set_init_values(bContext *C, wmOperator *op, tGP
/* set interpolation weight */
tgpi->shift = RNA_float_get(op->ptr, "shift");
- /* set layers */
- gpencil_interpolate_set_points(C, tgpi);
/* Untag strokes to be sure nothing is pending due any canceled process. */
LISTBASE_FOREACH (bGPDlayer *, gpl, &tgpi->gpd->layers) {
gpencil_interpolate_untag_strokes(gpl);
}
+ /* Set layers */
+ gpencil_interpolate_set_points(C, tgpi);
+
return 1;
}
@@ -992,8 +998,8 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
}
/* store extremes */
- prevFrame = gpl->actframe;
- nextFrame = gpl->actframe->next;
+ prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe);
+ nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next);
/* Loop over intermediary frames and create the interpolation */
for (cframe = prevFrame->framenum + step; cframe < nextFrame->framenum; cframe += step) {
@@ -1049,28 +1055,17 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN;
}
- /* create new stroke */
- bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
-
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
if (gps_from->totpoints > gps_to->totpoints) {
- /* free weights of removed points */
- if (new_stroke->dvert != NULL) {
- BKE_defvert_array_free_elems(new_stroke->dvert + gps_to->totpoints,
- gps_from->totpoints - gps_to->totpoints);
- }
-
- new_stroke->points = MEM_recallocN(new_stroke->points,
- sizeof(*new_stroke->points) * gps_to->totpoints);
-
- if (new_stroke->dvert != NULL) {
- new_stroke->dvert = MEM_recallocN(new_stroke->dvert,
- sizeof(*new_stroke->dvert) * gps_to->totpoints);
- }
-
- new_stroke->totpoints = gps_to->totpoints;
+ BKE_gpencil_stroke_uniform_subdivide(gpd, gps_to, gps_from->totpoints, true);
+ }
+ if (gps_to->totpoints > gps_from->totpoints) {
+ BKE_gpencil_stroke_uniform_subdivide(gpd, gps_from, gps_to->totpoints, true);
}
+ /* create new stroke */
+ bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
+
/* update points position */
gpencil_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
@@ -1081,6 +1076,11 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
BLI_addtail(&interFrame->strokes, new_stroke);
}
}
+
+ BKE_gpencil_free_strokes(prevFrame);
+ BKE_gpencil_free_strokes(nextFrame);
+ MEM_SAFE_FREE(prevFrame);
+ MEM_SAFE_FREE(nextFrame);
}
/* notifiers */
diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c
index 9f2bf3818a4..272dff56291 100644
--- a/source/blender/editors/gpencil/gpencil_merge.c
+++ b/source/blender/editors/gpencil/gpencil_merge.c
@@ -31,6 +31,7 @@
#include "BLI_math.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "BKE_brush.h"
#include "BKE_context.h"
diff --git a/source/blender/editors/gpencil/gpencil_ops_versioning.c b/source/blender/editors/gpencil/gpencil_ops_versioning.c
index 4721736489e..815bbbaa254 100644
--- a/source/blender/editors/gpencil/gpencil_ops_versioning.c
+++ b/source/blender/editors/gpencil/gpencil_ops_versioning.c
@@ -33,6 +33,7 @@
#include "BLI_math.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
index ed18c2eed5d..bb9dd8cac5d 100644
--- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c
+++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
@@ -41,6 +41,7 @@
#include "BLT_translation.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 2c0b9534141..281ab8c5adc 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -36,6 +36,7 @@
#include "BLI_utildefines.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index e8e25a55796..c3ac33063af 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -40,7 +40,9 @@
#include "PIL_time.h"
#include "DNA_brush_types.h"
+#include "DNA_collection_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c
index c3fd8d10b64..b212872b607 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_ops.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c
@@ -32,6 +32,7 @@
#include "DNA_brush_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
@@ -236,7 +237,7 @@ void GPENCIL_OT_vertex_color_brightness_contrast(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "Vertex Paint Bright/Contrast";
+ ot->name = "Vertex Paint Brightness/Contrast";
ot->idname = "GPENCIL_OT_vertex_color_brightness_contrast";
ot->description = "Adjust vertex color brightness/contrast";
diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c
index a4dc677f0dc..3afff897734 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_paint.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c
@@ -31,6 +31,7 @@
#include "DNA_brush_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "BKE_brush.h"
#include "BKE_colortools.h"
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 3501acd4fdf..0c4576096fb 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -31,7 +31,6 @@ struct Base;
struct Bone;
struct Depsgraph;
struct EditBone;
-struct IDProperty;
struct ListBase;
struct Main;
struct Mesh;
diff --git a/source/blender/editors/include/ED_asset.h b/source/blender/editors/include/ED_asset.h
new file mode 100644
index 00000000000..6fe50528cc5
--- /dev/null
+++ b/source/blender/editors/include/ED_asset.h
@@ -0,0 +1,39 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup editors
+ */
+
+#ifndef __ED_ASSET_H__
+#define __ED_ASSET_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool ED_asset_mark_id(const struct bContext *C, struct ID *id);
+bool ED_asset_clear_id(struct ID *id);
+
+bool ED_asset_can_make_single_from_context(const struct bContext *C);
+
+void ED_operatortypes_asset(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ED_ASSET_H__ */
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index 84808416074..7b240e0569f 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -28,7 +28,9 @@ extern "C" {
#endif
struct ARegion;
+struct FileAssetSelectParams;
struct FileSelectParams;
+struct FileDirEntry;
struct Scene;
struct ScrArea;
struct SpaceFile;
@@ -101,16 +103,16 @@ typedef struct FileSelection {
struct View2D;
struct rcti;
-struct FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile);
+struct FileSelectParams *ED_fileselect_ensure_active_params(struct SpaceFile *sfile);
+struct FileSelectParams *ED_fileselect_get_active_params(const struct SpaceFile *sfile);
+struct FileSelectParams *ED_fileselect_get_file_params(const struct SpaceFile *sfile);
+struct FileAssetSelectParams *ED_fileselect_get_asset_params(const struct SpaceFile *sfile);
-short ED_fileselect_set_params(struct SpaceFile *sfile);
void ED_fileselect_set_params_from_userdef(struct SpaceFile *sfile);
void ED_fileselect_params_to_userdef(struct SpaceFile *sfile,
const int temp_win_size[],
const bool is_maximized);
-void ED_fileselect_reset_params(struct SpaceFile *sfile);
-
void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *region);
FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, struct ARegion *region);
@@ -142,6 +144,8 @@ void ED_fileselect_exit(struct wmWindowManager *wm,
struct Scene *owner_scene,
struct SpaceFile *sfile);
+bool ED_fileselect_is_asset_browser(const struct SpaceFile *sfile);
+
void ED_fileselect_window_params_get(const struct wmWindow *win,
int win_size[2],
bool *is_maximized);
@@ -151,6 +155,7 @@ struct ScrArea *ED_fileselect_handler_area_find(const struct wmWindow *win,
int ED_path_extension_type(const char *path);
int ED_file_extension_icon(const char *path);
+int ED_file_icon(const struct FileDirEntry *file);
void ED_file_read_bookmarks(void);
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index be2f714dfe1..1b7caf27ecf 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -51,7 +51,6 @@ struct ScrArea;
struct SnapObjectContext;
struct ToolSettings;
struct View3D;
-struct ViewLayer;
struct bContext;
struct Material;
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index c1d3a17b9b6..b139b0765a3 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -34,12 +34,10 @@ struct ARegion;
struct ImBuf;
struct Image;
struct ImageUser;
-struct LinkNodePair;
struct Main;
struct ReportList;
struct Scene;
struct SpaceImage;
-struct ViewLayer;
struct bContext;
struct wmOperator;
struct wmWindowManager;
diff --git a/source/blender/editors/include/ED_info.h b/source/blender/editors/include/ED_info.h
index e3ce494e09a..9ac6b6c1085 100644
--- a/source/blender/editors/include/ED_info.h
+++ b/source/blender/editors/include/ED_info.h
@@ -38,8 +38,12 @@ const char *ED_info_statistics_string(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer);
-void ED_info_draw_stats(
- struct Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height);
+void ED_info_draw_stats(struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ int x,
+ int *y,
+ int height);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 2e9b711c99a..f9358f62274 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -53,7 +53,6 @@ struct uiLayout;
struct wmKeyConfig;
struct wmOperator;
struct wmOperatorType;
-struct wmWindowManager;
/* object_edit.c */
/* context.object */
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index dc1c43c0337..20417634020 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -239,6 +239,7 @@ void ED_screen_restore_temp_type(struct bContext *C, ScrArea *area);
ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *area, int type);
void ED_screen_full_prevspace(struct bContext *C, ScrArea *area);
void ED_screen_full_restore(struct bContext *C, ScrArea *area);
+ScrArea *ED_screen_state_maximized_create(struct bContext *C);
struct ScrArea *ED_screen_state_toggle(struct bContext *C,
struct wmWindow *win,
struct ScrArea *area,
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 0ea86e006e0..ca3e351a052 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -32,7 +32,6 @@ extern "C" {
struct Object;
struct bContext;
struct wmKeyConfig;
-struct wmMsgBus;
struct wmOperatorType;
void ED_keymap_transform(struct wmKeyConfig *keyconf);
@@ -108,7 +107,6 @@ bool calculateTransformCenter(struct bContext *C,
struct Object;
struct Scene;
-struct wmGizmoGroup;
struct wmGizmoGroupType;
/* UNUSED */
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index ebaa32941f2..b7174964ef6 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -31,7 +31,6 @@ struct BMVert;
struct ARegion;
struct Depsgraph;
struct ListBase;
-struct Main;
struct Object;
struct Scene;
struct View3D;
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index 68ae3589064..1e87a940a7d 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -52,7 +52,10 @@ void ED_spacedata_id_remap(struct ScrArea *area,
struct ID *old_id,
struct ID *new_id);
-void ED_OT_flush_edits(struct wmOperatorType *ot);
+void ED_OT_lib_id_load_custom_preview(struct wmOperatorType *ot);
+void ED_OT_lib_id_generate_preview(struct wmOperatorType *ot);
+
+void ED_operatortypes_edutils(void);
/* ************** XXX OLD CRUFT WARNING ************* */
diff --git a/source/blender/editors/include/ED_util_imbuf.h b/source/blender/editors/include/ED_util_imbuf.h
index d142d3d6425..4bbaa68e849 100644
--- a/source/blender/editors/include/ED_util_imbuf.h
+++ b/source/blender/editors/include/ED_util_imbuf.h
@@ -31,7 +31,6 @@ extern "C" {
#endif
struct ARegion;
-struct Main;
struct bContext;
struct wmEvent;
struct wmOperator;
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 2066d7da511..4de97411059 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -33,7 +33,6 @@ struct BMEditMesh;
struct BMFace;
struct BMLoop;
struct BMesh;
-struct Depsgraph;
struct Image;
struct ImageUser;
struct Main;
@@ -217,8 +216,10 @@ struct BMLoop *ED_uvedit_active_vert_loop_get(struct BMesh *bm);
void ED_uvedit_active_edge_loop_set(struct BMesh *bm, struct BMLoop *l);
struct BMLoop *ED_uvedit_active_edge_loop_get(struct BMesh *bm);
-char ED_uvedit_select_mode_get(const Scene *scene);
-void ED_uvedit_select_sync_flush(const ToolSettings *ts, struct BMEditMesh *em, const bool select);
+char ED_uvedit_select_mode_get(const struct Scene *scene);
+void ED_uvedit_select_sync_flush(const struct ToolSettings *ts,
+ struct BMEditMesh *em,
+ const bool select);
/* uvedit_unwrap_ops.c */
void ED_uvedit_live_unwrap_begin(struct Scene *scene, struct Object *obedit);
@@ -244,7 +245,7 @@ struct UVPackIsland_Params {
uint use_seams : 1;
uint correct_aspect : 1;
};
-void ED_uvedit_pack_islands_multi(const Scene *scene,
+void ED_uvedit_pack_islands_multi(const struct Scene *scene,
Object **objects,
const uint objects_len,
const struct UVPackIsland_Params *params);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 596533406c3..a4856845a65 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -41,8 +41,6 @@ struct Camera;
struct CustomData_MeshMasks;
struct Depsgraph;
struct EditBone;
-struct GPUOffScreen;
-struct GPUViewport;
struct ID;
struct MVert;
struct Main;
@@ -55,7 +53,6 @@ struct RenderEngineType;
struct Scene;
struct ScrArea;
struct View3D;
-struct View3DShading;
struct ViewContext;
struct ViewLayer;
struct bContext;
@@ -64,8 +61,6 @@ struct bScreen;
struct rctf;
struct rcti;
struct wmGizmo;
-struct wmOperator;
-struct wmOperatorType;
struct wmWindow;
struct wmWindowManager;
@@ -141,6 +136,11 @@ void ED_view3d_to_object(const struct Depsgraph *depsgraph,
const float quat[4],
const float dist);
+bool ED_view3d_camera_to_view_selected(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ const struct Scene *scene,
+ struct Object *camera_ob);
+
void ED_view3d_lastview_store(struct RegionView3D *rv3d);
/* Depth buffer */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index faf34573475..79311042274 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -920,6 +920,7 @@ DEF_ICON_COLOR(BRUSH_TEXMASK)
DEF_ICON_COLOR(BRUSH_THUMB)
DEF_ICON_COLOR(BRUSH_ROTATE)
DEF_ICON_COLOR(BRUSH_VCOL_BOUNDARY)
+DEF_ICON_COLOR(BRUSH_PAINT)
/* grease pencil sculpt */
DEF_ICON_COLOR(GPBRUSH_SMOOTH)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 005dbf0e381..2705dd27756 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -50,7 +50,6 @@ struct PointerRNA;
struct PropertyRNA;
struct ReportList;
struct ResultBLF;
-struct ScrArea;
struct bContext;
struct bContextStore;
struct bNode;
@@ -77,6 +76,7 @@ struct wmWindow;
typedef struct uiBlock uiBlock;
typedef struct uiBut uiBut;
+typedef struct uiButExtraOpIcon uiButExtraOpIcon;
typedef struct uiLayout uiLayout;
typedef struct uiPopupBlockHandle uiPopupBlockHandle;
@@ -103,14 +103,19 @@ typedef struct uiPopupBlockHandle uiPopupBlockHandle;
#define UI_SCREEN_MARGIN 10
/** #uiBlock.emboss and #uiBut.emboss */
-enum {
+typedef enum eUIEmbossType {
UI_EMBOSS = 0, /* use widget style for drawing */
UI_EMBOSS_NONE = 1, /* Nothing, only icon and/or text */
UI_EMBOSS_PULLDOWN = 2, /* Pulldown menu style */
UI_EMBOSS_RADIAL = 3, /* Pie Menu */
+ /**
+ * The same as #UI_EMBOSS_NONE, unless the the button has
+ * a coloring status like an animation state or red alert.
+ */
+ UI_EMBOSS_NONE_OR_STATUS = 4,
UI_EMBOSS_UNDEFINED = 255, /* For layout engine, use emboss from block. */
-};
+} eUIEmbossType;
/* uiBlock->direction */
enum {
@@ -666,7 +671,7 @@ bool UI_popup_block_name_exists(const struct bScreen *screen, const char *name);
uiBlock *UI_block_begin(const struct bContext *C,
struct ARegion *region,
const char *name,
- char emboss);
+ eUIEmbossType emboss);
void UI_block_end_ex(const struct bContext *C, uiBlock *block, const int xy[2], int r_xy[2]);
void UI_block_end(const struct bContext *C, uiBlock *block);
void UI_block_draw(const struct bContext *C, struct uiBlock *block);
@@ -680,7 +685,7 @@ enum {
};
void UI_block_theme_style_set(uiBlock *block, char theme_style);
char UI_block_emboss_get(uiBlock *block);
-void UI_block_emboss_set(uiBlock *block, char emboss);
+void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss);
bool UI_block_is_search_only(const uiBlock *block);
void UI_block_set_search_only(uiBlock *block, bool search_only);
@@ -727,6 +732,13 @@ void UI_block_translate(uiBlock *block, int x, int y);
int UI_but_return_value_get(uiBut *but);
void UI_but_drag_set_id(uiBut *but, struct ID *id);
+void UI_but_drag_set_asset(uiBut *but,
+ const char *name,
+ const char *path,
+ int id_type,
+ int icon,
+ struct ImBuf *imb,
+ float scale);
void UI_but_drag_set_rna(uiBut *but, struct PointerRNA *ptr);
void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free);
void UI_but_drag_set_name(uiBut *but, const char *name);
@@ -1375,13 +1387,16 @@ typedef struct uiStringInfo {
/* Note: Expects pointers to uiStringInfo structs as parameters.
* Will fill them with translated strings, when possible.
* Strings in uiStringInfo must be MEM_freeN'ed by caller. */
-void UI_but_string_info_get(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0);
+void UI_but_string_info_get(struct bContext *C, uiBut *but, uiButExtraOpIcon *extra_icon, ...)
+ ATTR_SENTINEL(0);
/* Edit i18n stuff. */
/* Name of the main py op from i18n addon. */
#define EDTSRC_I18N_OP_NAME "UI_OT_edittranslation"
/**
+ * TODO This is old stuff, only used by templateID. Should be cleaned up.
+ *
* Special Buttons
*
* Buttons with a more specific purpose:
@@ -1399,14 +1414,16 @@ enum {
UI_ID_ALONE = 1 << 4,
UI_ID_OPEN = 1 << 3,
UI_ID_DELETE = 1 << 5,
- UI_ID_LOCAL = 1 << 6,
- UI_ID_AUTO_NAME = 1 << 7,
- UI_ID_FAKE_USER = 1 << 8,
+ UI_ID_MAKE_LOCAL = 1 << 6,
+ UI_ID_LIB_OVERRIDE_ADD = 1 << 7,
+ UI_ID_AUTO_NAME = 1 << 8,
UI_ID_PIN = 1 << 9,
UI_ID_PREVIEWS = 1 << 10,
- UI_ID_OVERRIDE = 1 << 11,
+ UI_ID_LIB_OVERRIDE_REMOVE = 1 << 11,
+ UI_ID_LIB_OVERRIDE_RESET = 1 << 12,
UI_ID_FULL = UI_ID_RENAME | UI_ID_BROWSE | UI_ID_ADD_NEW | UI_ID_OPEN | UI_ID_ALONE |
- UI_ID_DELETE | UI_ID_LOCAL,
+ UI_ID_DELETE | UI_ID_MAKE_LOCAL | UI_ID_LIB_OVERRIDE_ADD |
+ UI_ID_LIB_OVERRIDE_REMOVE | UI_ID_LIB_OVERRIDE_RESET,
};
/**
@@ -1652,10 +1669,12 @@ void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN);
void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, void *arg);
-PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
- const char *opname,
- short opcontext,
- int icon);
+struct uiButExtraOpIcon *UI_but_extra_operator_icon_add(uiBut *but,
+ const char *opname,
+ short opcontext,
+ int icon);
+struct wmOperatorType *UI_but_extra_operator_icon_optype_get(struct uiButExtraOpIcon *extra_icon);
+PointerRNA *UI_but_extra_operator_icon_opptr_get(struct uiButExtraOpIcon *extra_icon);
/* Autocomplete
*
@@ -1879,6 +1898,7 @@ uiBlock *uiLayoutGetBlock(uiLayout *layout);
void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv);
void uiLayoutSetContextPointer(uiLayout *layout, const char *name, struct PointerRNA *ptr);
+struct bContextStore *uiLayoutGetContextStore(uiLayout *layout);
void uiLayoutContextCopy(uiLayout *layout, struct bContextStore *context);
struct wmOperatorType *UI_but_operatortype_get_from_enum_menu(struct uiBut *but,
PropertyRNA **r_prop);
@@ -1903,7 +1923,7 @@ void uiLayoutSetScaleX(uiLayout *layout, float scale);
void uiLayoutSetScaleY(uiLayout *layout, float scale);
void uiLayoutSetUnitsX(uiLayout *layout, float unit);
void uiLayoutSetUnitsY(uiLayout *layout, float unit);
-void uiLayoutSetEmboss(uiLayout *layout, char emboss);
+void uiLayoutSetEmboss(uiLayout *layout, eUIEmbossType emboss);
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep);
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep);
int uiLayoutGetLocalDir(const uiLayout *layout);
@@ -1922,7 +1942,7 @@ float uiLayoutGetScaleX(uiLayout *layout);
float uiLayoutGetScaleY(uiLayout *layout);
float uiLayoutGetUnitsX(uiLayout *layout);
float uiLayoutGetUnitsY(uiLayout *layout);
-int uiLayoutGetEmboss(uiLayout *layout);
+eUIEmbossType uiLayoutGetEmboss(uiLayout *layout);
bool uiLayoutGetPropSep(uiLayout *layout);
bool uiLayoutGetPropDecorate(uiLayout *layout);
@@ -1956,6 +1976,7 @@ void uiTemplateID(uiLayout *layout,
struct PointerRNA *ptr,
const char *propname,
const char *newop,
+ const char *duplicateop,
const char *openop,
const char *unlinkop,
int filter,
@@ -2560,6 +2581,11 @@ struct ARegion *UI_tooltip_create_from_button(struct bContext *C,
struct ARegion *butregion,
uiBut *but,
bool is_label);
+struct ARegion *UI_tooltip_create_from_button_or_extra_icon(struct bContext *C,
+ struct ARegion *butregion,
+ uiBut *but,
+ uiButExtraOpIcon *extra_icon,
+ bool is_label);
struct ARegion *UI_tooltip_create_from_gizmo(struct bContext *C, struct wmGizmo *gz);
void UI_tooltip_free(struct bContext *C, struct bScreen *screen, struct ARegion *region);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 4a02c6b6e88..7713efd1c78 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1167,16 +1167,21 @@ void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_str
* \{ */
static bool ui_but_event_operator_string_from_operator(const bContext *C,
- uiBut *but,
+ wmOperatorCallParams *op_call_params,
char *buf,
const size_t buf_len)
{
- BLI_assert(but->optype != NULL);
+ BLI_assert(op_call_params->optype != NULL);
bool found = false;
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
-
- if (WM_key_event_operator_string(
- C, but->optype->idname, but->opcontext, prop, true, buf, buf_len)) {
+ IDProperty *prop = (op_call_params->opptr) ? op_call_params->opptr->data : NULL;
+
+ if (WM_key_event_operator_string(C,
+ op_call_params->optype->idname,
+ op_call_params->opcontext,
+ prop,
+ true,
+ buf,
+ buf_len)) {
found = true;
}
return found;
@@ -1253,15 +1258,22 @@ static bool ui_but_event_operator_string_from_panel(const bContext *C,
return found;
}
-static bool ui_but_event_operator_string(const bContext *C,
- uiBut *but,
- char *buf,
- const size_t buf_len)
+static bool ui_but_event_operator_string(
+ const bContext *C, uiBut *but, uiButExtraOpIcon *extra_icon, char *buf, const size_t buf_len)
{
bool found = false;
+ wmOperatorType *extra_icon_optype = UI_but_extra_operator_icon_optype_get(extra_icon);
- if (but->optype != NULL) {
- found = ui_but_event_operator_string_from_operator(C, but, buf, buf_len);
+ if (extra_icon_optype) {
+ found = ui_but_event_operator_string_from_operator(C, extra_icon->optype_params, buf, buf_len);
+ }
+ else if (but->optype != NULL) {
+ found = ui_but_event_operator_string_from_operator(
+ C,
+ &(wmOperatorCallParams){
+ .optype = but->optype, .opptr = but->opptr, .opcontext = but->opcontext},
+ buf,
+ buf_len);
}
else if (UI_but_menutype_get(but) != NULL) {
found = ui_but_event_operator_string_from_menu(C, but, buf, buf_len);
@@ -1564,7 +1576,7 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
continue;
}
- if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) {
+ if (ui_but_event_operator_string(C, but, NULL, buf, sizeof(buf))) {
ui_but_add_shortcut(but, buf, false);
}
else if (ui_but_event_property_operator_string(C, but, buf, sizeof(buf))) {
@@ -1605,12 +1617,12 @@ typedef enum PredefinedExtraOpIconType {
PREDEFINED_EXTRA_OP_ICON_EYEDROPPER,
} PredefinedExtraOpIconType;
-static PointerRNA *ui_but_extra_operator_icon_add_ptr(uiBut *but,
- wmOperatorType *optype,
- short opcontext,
- int icon)
+static uiButExtraOpIcon *ui_but_extra_operator_icon_add_ptr(uiBut *but,
+ wmOperatorType *optype,
+ short opcontext,
+ int icon)
{
- uiButExtraOpIcon *extra_op_icon = MEM_mallocN(sizeof(*extra_op_icon), __func__);
+ uiButExtraOpIcon *extra_op_icon = MEM_callocN(sizeof(*extra_op_icon), __func__);
extra_op_icon->icon = (BIFIconID)icon;
extra_op_icon->optype_params = MEM_callocN(sizeof(*extra_op_icon->optype_params),
@@ -1625,13 +1637,15 @@ static PointerRNA *ui_but_extra_operator_icon_add_ptr(uiBut *but,
BLI_addtail(&but->extra_op_icons, extra_op_icon);
- return extra_op_icon->optype_params->opptr;
+ return extra_op_icon;
}
static void ui_but_extra_operator_icon_free(uiButExtraOpIcon *extra_icon)
{
- WM_operator_properties_free(extra_icon->optype_params->opptr);
- MEM_freeN(extra_icon->optype_params->opptr);
+ if (extra_icon->optype_params->opptr) {
+ WM_operator_properties_free(extra_icon->optype_params->opptr);
+ MEM_freeN(extra_icon->optype_params->opptr);
+ }
MEM_freeN(extra_icon->optype_params);
MEM_freeN(extra_icon);
}
@@ -1644,18 +1658,25 @@ void ui_but_extra_operator_icons_free(uiBut *but)
BLI_listbase_clear(&but->extra_op_icons);
}
-PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
- const char *opname,
- short opcontext,
- int icon)
+uiButExtraOpIcon *UI_but_extra_operator_icon_add(uiBut *but,
+ const char *opname,
+ short opcontext,
+ int icon)
{
wmOperatorType *optype = WM_operatortype_find(opname, false);
- if (optype) {
- return ui_but_extra_operator_icon_add_ptr(but, optype, opcontext, icon);
- }
+ BLI_assert(optype);
+ return ui_but_extra_operator_icon_add_ptr(but, optype, opcontext, icon);
+}
- return NULL;
+PointerRNA *UI_but_extra_operator_icon_opptr_get(uiButExtraOpIcon *extra_icon)
+{
+ return extra_icon->optype_params->opptr;
+}
+
+wmOperatorType *UI_but_extra_operator_icon_optype_get(uiButExtraOpIcon *extra_icon)
+{
+ return extra_icon ? extra_icon->optype_params->optype : NULL;
}
static bool ui_but_icon_extra_is_visible_text_clear(const uiBut *but)
@@ -3352,7 +3373,7 @@ static void ui_but_free(const bContext *C, uiBut *but)
}
if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- MEM_freeN(but->dragpoin);
+ WM_drag_data_free(but->dragtype, but->dragpoin);
}
ui_but_extra_operator_icons_free(but);
@@ -3457,7 +3478,7 @@ void UI_block_region_set(uiBlock *block, ARegion *region)
block->oldblock = oldblock;
}
-uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, char emboss)
+uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, eUIEmbossType emboss)
{
wmWindow *window = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
@@ -3508,7 +3529,7 @@ char UI_block_emboss_get(uiBlock *block)
return block->emboss;
}
-void UI_block_emboss_set(uiBlock *block, char emboss)
+void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss)
{
block->emboss = emboss;
}
@@ -4552,6 +4573,15 @@ static uiBut *ui_def_but_rna(uiBlock *block,
UI_but_disable(but, info);
}
+ if (proptype == PROP_POINTER) {
+ /* If the button shows an ID, automatically set it as focused in context so operators can
+ * access it.*/
+ const PointerRNA pptr = RNA_property_pointer_get(ptr, prop);
+ if (pptr.data && RNA_struct_is_ID(pptr.type)) {
+ but->context = CTX_store_add(&block->contexts, "id", &pptr);
+ }
+ }
+
if (but->flag & UI_BUT_UNDO && (ui_but_is_rna_undo(but) == false)) {
but->flag &= ~UI_BUT_UNDO;
}
@@ -6089,17 +6119,42 @@ void UI_but_drag_set_id(uiBut *but, ID *id)
{
but->dragtype = WM_DRAG_ID;
if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- MEM_SAFE_FREE(but->dragpoin);
+ WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)id;
}
+void UI_but_drag_set_asset(uiBut *but,
+ const char *name,
+ const char *path,
+ int id_type,
+ int icon,
+ struct ImBuf *imb,
+ float scale)
+{
+ wmDragAsset *asset_drag = MEM_mallocN(sizeof(*asset_drag), "wmDragAsset");
+
+ BLI_strncpy(asset_drag->name, name, sizeof(asset_drag->name));
+ asset_drag->path = path;
+ asset_drag->id_type = id_type;
+
+ but->dragtype = WM_DRAG_ASSET;
+ ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */
+ if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ WM_drag_data_free(but->dragtype, but->dragpoin);
+ }
+ but->dragpoin = asset_drag;
+ but->dragflag |= UI_BUT_DRAGPOIN_FREE;
+ but->imb = imb;
+ but->imb_scale = scale;
+}
+
void UI_but_drag_set_rna(uiBut *but, PointerRNA *ptr)
{
but->dragtype = WM_DRAG_RNA;
if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- MEM_SAFE_FREE(but->dragpoin);
+ WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)ptr;
@@ -6109,7 +6164,7 @@ void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free)
{
but->dragtype = WM_DRAG_PATH;
if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- MEM_SAFE_FREE(but->dragpoin);
+ WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)path;
@@ -6122,7 +6177,7 @@ void UI_but_drag_set_name(uiBut *but, const char *name)
{
but->dragtype = WM_DRAG_NAME;
if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- MEM_SAFE_FREE(but->dragpoin);
+ WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)name;
@@ -6140,7 +6195,7 @@ void UI_but_drag_set_image(
but->dragtype = WM_DRAG_PATH;
ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */
if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- MEM_SAFE_FREE(but->dragpoin);
+ WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)path;
@@ -6784,7 +6839,7 @@ void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN)
but->hold_argN = argN;
}
-void UI_but_string_info_get(bContext *C, uiBut *but, ...)
+void UI_but_string_info_get(bContext *C, uiBut *but, uiButExtraOpIcon *extra_icon, ...)
{
va_list args;
uiStringInfo *si;
@@ -6793,13 +6848,19 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
int totitems;
bool free_items = false;
- va_start(args, but);
+ wmOperatorType *extra_icon_optype = UI_but_extra_operator_icon_optype_get(extra_icon);
+ wmOperatorType *optype = extra_icon ? extra_icon_optype : but->optype;
+
+ /* Don't query RNA data when the extra-icon overrides the button. */
+ PropertyRNA *rnaprop = extra_icon ? NULL : but->rnaprop;
+
+ va_start(args, extra_icon);
while ((si = (uiStringInfo *)va_arg(args, void *))) {
uiStringInfoType type = si->type;
char *tmp = NULL;
if (type == BUT_GET_LABEL) {
- if (but->str && but->str[0]) {
+ if (but->str && but->str[0] && !extra_icon) {
const char *str_sep;
size_t str_len;
@@ -6829,16 +6890,16 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
}
if (type == BUT_GET_RNAPROP_IDENTIFIER) {
- if (but->rnaprop) {
- tmp = BLI_strdup(RNA_property_identifier(but->rnaprop));
+ if (rnaprop) {
+ tmp = BLI_strdup(RNA_property_identifier(rnaprop));
}
}
else if (type == BUT_GET_RNASTRUCT_IDENTIFIER) {
- if (but->rnaprop && but->rnapoin.data) {
+ if (rnaprop && but->rnapoin.data) {
tmp = BLI_strdup(RNA_struct_identifier(but->rnapoin.type));
}
- else if (but->optype) {
- tmp = BLI_strdup(but->optype->idname);
+ else if (optype) {
+ tmp = BLI_strdup(optype->idname);
}
else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
MenuType *mt = UI_but_menutype_get(but);
@@ -6854,23 +6915,25 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
}
}
else if (ELEM(type, BUT_GET_RNA_LABEL, BUT_GET_RNA_TIP)) {
- if (but->rnaprop) {
+ if (rnaprop) {
if (type == BUT_GET_RNA_LABEL) {
- tmp = BLI_strdup(RNA_property_ui_name(but->rnaprop));
+ tmp = BLI_strdup(RNA_property_ui_name(rnaprop));
}
else {
- const char *t = RNA_property_ui_description(but->rnaprop);
+ const char *t = RNA_property_ui_description(rnaprop);
if (t && t[0]) {
tmp = BLI_strdup(t);
}
}
}
- else if (but->optype) {
+ else if (optype) {
+ PointerRNA *opptr = extra_icon_optype ? UI_but_extra_operator_icon_opptr_get(extra_icon) :
+ but->opptr;
if (type == BUT_GET_RNA_LABEL) {
- tmp = BLI_strdup(WM_operatortype_name(but->optype, but->opptr));
+ tmp = BLI_strdup(WM_operatortype_name(optype, opptr));
}
else {
- tmp = WM_operatortype_description(C, but->optype, but->opptr);
+ tmp = WM_operatortype_description(C, optype, opptr);
}
}
else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) {
@@ -6922,11 +6985,11 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
}
else if (type == BUT_GET_RNA_LABEL_CONTEXT) {
const char *_tmp = BLT_I18NCONTEXT_DEFAULT;
- if (but->rnaprop) {
- _tmp = RNA_property_translation_context(but->rnaprop);
+ if (rnaprop) {
+ _tmp = RNA_property_translation_context(rnaprop);
}
- else if (but->optype) {
- _tmp = RNA_struct_translation_context(but->optype->srna);
+ else if (optype) {
+ _tmp = RNA_struct_translation_context(optype->srna);
}
else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
MenuType *mt = UI_but_menutype_get(but);
@@ -6945,16 +7008,16 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
int value = 0;
/* get the enum property... */
- if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) {
+ if (rnaprop && RNA_property_type(rnaprop) == PROP_ENUM) {
/* enum property */
ptr = &but->rnapoin;
- prop = but->rnaprop;
+ prop = rnaprop;
value = (ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_TAB)) ? (int)but->hardmax :
(int)ui_but_value_get(but);
}
- else if (but->optype) {
- PointerRNA *opptr = UI_but_operator_ptr_get(but);
- wmOperatorType *ot = but->optype;
+ else if (optype) {
+ PointerRNA *opptr = extra_icon_optype ? UI_but_extra_operator_icon_opptr_get(extra_icon) :
+ UI_but_operator_ptr_get(but);
/* so the context is passed to itemf functions */
WM_operator_properties_sanitize(opptr, false);
@@ -6964,11 +7027,11 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
* operator menus in the Anim Editors will show tooltips for the different
* operations instead of the meaningless generic operator tooltip
*/
- if (ot->prop && RNA_property_type(ot->prop) == PROP_ENUM) {
- if (RNA_struct_contains_property(opptr, ot->prop)) {
+ if (optype->prop && RNA_property_type(optype->prop) == PROP_ENUM) {
+ if (RNA_struct_contains_property(opptr, optype->prop)) {
ptr = opptr;
- prop = ot->prop;
- value = RNA_property_enum_get(opptr, ot->prop);
+ prop = optype->prop;
+ value = RNA_property_enum_get(opptr, optype->prop);
}
}
}
@@ -7001,7 +7064,7 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
else if (type == BUT_GET_OP_KEYMAP) {
if (!ui_block_is_menu(but->block)) {
char buf[128];
- if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) {
+ if (ui_but_event_operator_string(C, but, extra_icon, buf, sizeof(buf))) {
tmp = BLI_strdup(buf);
}
}
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 39b405a02b8..fd3b00eec31 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -38,6 +38,7 @@
#include "BKE_idprop.h"
#include "BKE_screen.h"
+#include "ED_asset.h"
#include "ED_keyframing.h"
#include "ED_screen.h"
@@ -503,17 +504,23 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
uiPopupMenu *pup;
uiLayout *layout;
+ bContextStore *previous_ctx = CTX_store_get(C);
{
uiStringInfo label = {BUT_GET_LABEL, NULL};
/* highly unlikely getting the label ever fails */
- UI_but_string_info_get(C, but, &label, NULL);
+ UI_but_string_info_get(C, but, NULL, &label, NULL);
pup = UI_popup_menu_begin(C, label.strinfo ? label.strinfo : "", ICON_NONE);
layout = UI_popup_menu_layout(pup);
if (label.strinfo) {
MEM_freeN(label.strinfo);
}
+
+ if (but->context) {
+ uiLayoutContextCopy(layout, but->context);
+ CTX_store_set(C, uiLayoutGetContextStore(layout));
+ }
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
}
@@ -946,6 +953,22 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
}
}
+ /* If the button reprents an id, it can set the "id" context pointer. */
+ if (ED_asset_can_make_single_from_context(C)) {
+ ID *id = CTX_data_pointer_get_type(C, "id", &RNA_ID).data;
+
+ /* Gray out items depending on if data-block is an asset. Preferably this could be done via
+ * operator poll, but that doesn't work since the operator also works with "selected_ids",
+ * which isn't cheap to check. */
+ uiLayout *sub = uiLayoutColumn(layout, true);
+ uiLayoutSetEnabled(sub, !id->asset_data);
+ uiItemO(sub, NULL, ICON_NONE, "ASSET_OT_mark");
+ sub = uiLayoutColumn(layout, true);
+ uiLayoutSetEnabled(sub, id->asset_data);
+ uiItemO(sub, NULL, ICON_NONE, "ASSET_OT_clear");
+ uiItemS(layout);
+ }
+
/* Pointer properties and string properties with
* prop_search support jumping to target object/bone. */
if (but->rnapoin.data && but->rnaprop) {
@@ -1210,6 +1233,10 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
UI_menutype_draw(C, mt, uiLayoutColumn(layout, false));
}
+ if (but->context) {
+ CTX_store_set(C, previous_ctx);
+ }
+
return UI_popup_menu_end_or_cancel(C, pup);
}
diff --git a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
index 7f735a0e789..f2899fc0098 100644
--- a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
@@ -34,6 +34,7 @@
#include "BLT_translation.h"
#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "DNA_space_types.h"
#include "BKE_context.h"
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index f914ccd7497..790c2cd5313 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -334,6 +334,7 @@ typedef struct uiHandleButtonData {
int retval;
/* booleans (could be made into flags) */
bool cancel, escapecancel;
+ bool skip_undo_push;
bool applied, applied_interactive;
bool changed_cursor;
wmTimer *flashtimer;
@@ -626,7 +627,11 @@ static bool ui_rna_is_userdef(PointerRNA *ptr, PropertyRNA *prop)
if (base == NULL) {
base = ptr->type;
}
- if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences, &RNA_KeyMapItem)) {
+ if (ELEM(base,
+ &RNA_AddonPreferences,
+ &RNA_KeyConfigPreferences,
+ &RNA_KeyMapItem,
+ &RNA_UserAssetLibrary)) {
tag = true;
}
}
@@ -816,7 +821,9 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
/* typically call ui_apply_but_undo(), ui_apply_but_autokey() */
static void ui_apply_but_undo(uiBut *but)
{
- if (but->flag & UI_BUT_UNDO) {
+ const bool force_skip_undo = (but->active && but->active->skip_undo_push);
+
+ if (but->flag & UI_BUT_UNDO && !force_skip_undo) {
const char *str = NULL;
size_t str_len_clip = SIZE_MAX - 1;
bool skip_undo = false;
@@ -1349,6 +1356,9 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl
if (mbut_state == NULL) {
/* Highly unlikely. */
printf("%s: Can't find button\n", __func__);
+ /* While this avoids crashing, multi-button dragging will fail,
+ * which is still a bug from the user perspective. See T83651. */
+ continue;
}
void *active_back;
@@ -1984,6 +1994,8 @@ static bool ui_but_drag_init(bContext *C,
else {
wmDrag *drag = WM_event_start_drag(
C, but->icon, but->dragtype, but->dragpoin, ui_but_value_get(but), WM_DRAG_NOP);
+ /* wmDrag has ownership over dragpoin now, stop messing with it. */
+ but->dragpoin = NULL;
if (but->imb) {
WM_event_drag_image(drag,
@@ -2256,10 +2268,11 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
ListBase *drags = event->customdata; /* drop event type has listbase customdata by default */
LISTBASE_FOREACH (wmDrag *, wmd, drags) {
+ /* TODO asset dropping. */
if (wmd->type == WM_DRAG_ID) {
/* align these types with UI_but_active_drop_name */
if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
- ID *id = WM_drag_ID(wmd, 0);
+ ID *id = WM_drag_get_local_ID(wmd, 0);
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
@@ -2856,7 +2869,8 @@ void ui_but_active_string_clear_and_exit(bContext *C, uiBut *but)
but->active->str[0] = 0;
ui_apply_but_TEX(C, but, but->active);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ /* use onfree event so undo is handled by caller and apply is already done above */
+ button_activate_exit((bContext *)C, but, but->active, false, true);
}
static void ui_textedit_string_ensure_max_length(uiBut *but, uiHandleButtonData *data, int maxlen)
@@ -4001,16 +4015,38 @@ static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
ED_region_tag_redraw(data->region);
}
-static void ui_but_extra_operator_icon_apply(bContext *C, uiBut *but, uiButExtraOpIcon *op_icon)
+static void ui_but_extra_operator_icon_apply_func(uiBut *but, uiButExtraOpIcon *op_icon)
{
- if (but->active->interactive) {
- ui_apply_but(C, but->block, but, but->active, true);
+ if (ui_afterfunc_check(but->block, but)) {
+ uiAfterFunc *after = ui_afterfunc_new();
+
+ after->optype = op_icon->optype_params->optype;
+ after->opcontext = op_icon->optype_params->opcontext;
+ after->opptr = op_icon->optype_params->opptr;
+
+ if (but->context) {
+ after->context = CTX_store_copy(but->context);
+ }
+
+ /* Ownership moved, don't let the UI code free it. */
+ op_icon->optype_params->opptr = NULL;
}
+}
+
+static void ui_but_extra_operator_icon_apply(bContext *C,
+ uiBut *but,
+ uiHandleButtonData *data,
+ uiButExtraOpIcon *op_icon)
+{
button_activate_state(C, but, BUTTON_STATE_EXIT);
- WM_operator_name_call_ptr(C,
- op_icon->optype_params->optype,
- op_icon->optype_params->opcontext,
- op_icon->optype_params->opptr);
+ ui_apply_but(C, but->block, but, data, true);
+
+ data->postbut = but;
+ data->posttype = BUTTON_ACTIVATE_OVER;
+ /* Leave undo up to the operator. */
+ data->skip_undo_push = true;
+
+ ui_but_extra_operator_icon_apply_func(but, op_icon);
/* Force recreation of extra operator icons (pseudo update). */
ui_but_extra_operator_icons_free(but);
@@ -4209,7 +4245,7 @@ static bool ui_do_but_extra_operator_icon(bContext *C,
ED_region_tag_redraw(data->region);
button_tooltip_timer_reset(C, but);
- ui_but_extra_operator_icon_apply(C, but, op_icon);
+ ui_but_extra_operator_icon_apply(C, but, data, op_icon);
/* Note: 'but', 'data' may now be freed, don't access. */
return true;
@@ -5851,7 +5887,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
ColorPicker *cpicker = but->custom_data;
float hsv_static[3] = {0.0f};
- float *hsv = cpicker ? cpicker->color_data : hsv_static;
+ float *hsv = cpicker ? cpicker->hsv_perceptual : hsv_static;
float col[3];
ui_but_v3_get(but, col);
@@ -6079,7 +6115,7 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but,
{
const uiButHSVCube *hsv_but = (uiButHSVCube *)but;
ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
+ float *hsv = cpicker->hsv_perceptual;
float rgb[3];
float x, y;
float mx_fl, my_fl;
@@ -6097,7 +6133,7 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but,
#endif
ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
+ ui_scene_linear_to_perceptual_space(but, rgb);
ui_rgb_to_color_picker_HSVCUBE_compat_v(hsv_but, rgb, hsv);
@@ -6110,7 +6146,7 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but,
/* calculate original hsv again */
copy_v3_v3(rgb, data->origvec);
- ui_scene_linear_to_color_picker_space(but, rgb);
+ ui_scene_linear_to_perceptual_space(but, rgb);
copy_v3_v3(hsvo, hsv);
@@ -6173,7 +6209,7 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but,
}
ui_color_picker_to_rgb_HSVCUBE_v(hsv_but, hsv, rgb);
- ui_color_picker_to_scene_linear_space(but, rgb);
+ ui_perceptual_to_scene_linear_space(but, rgb);
/* clamp because with color conversion we can exceed range T34295. */
if (hsv_but->gradient_type == UI_GRAD_V_ALT) {
@@ -6196,13 +6232,13 @@ static void ui_ndofedit_but_HSVCUBE(uiButHSVCube *hsv_but,
const bool shift)
{
ColorPicker *cpicker = hsv_but->but.custom_data;
- float *hsv = cpicker->color_data;
+ float *hsv = cpicker->hsv_perceptual;
const float hsv_v_max = max_ff(hsv[2], hsv_but->but.softmax);
float rgb[3];
const float sensitivity = (shift ? 0.15f : 0.3f) * ndof->dt;
ui_but_v3_get(&hsv_but->but, rgb);
- ui_scene_linear_to_color_picker_space(&hsv_but->but, rgb);
+ ui_scene_linear_to_perceptual_space(&hsv_but->but, rgb);
ui_rgb_to_color_picker_HSVCUBE_compat_v(hsv_but, rgb, hsv);
switch (hsv_but->gradient_type) {
@@ -6251,7 +6287,7 @@ static void ui_ndofedit_but_HSVCUBE(uiButHSVCube *hsv_but,
hsv_clamp_v(hsv, hsv_v_max);
ui_color_picker_to_rgb_HSVCUBE_v(hsv_but, hsv, rgb);
- ui_color_picker_to_scene_linear_space(&hsv_but->but, rgb);
+ ui_perceptual_to_scene_linear_space(&hsv_but->but, rgb);
copy_v3_v3(data->vec, rgb);
ui_but_v3_set(&hsv_but->but, data->vec);
@@ -6308,7 +6344,7 @@ static int ui_do_but_HSVCUBE(
float rgb[3], def_hsv[3];
float def[4];
ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
+ float *hsv = cpicker->hsv_perceptual;
RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def);
ui_rgb_to_color_picker_HSVCUBE_v(hsv_but, def, def_hsv);
@@ -6364,7 +6400,7 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but,
{
const bool changed = true;
ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
+ float *hsv = cpicker->hsv_perceptual;
float mx_fl, my_fl;
ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift);
@@ -6390,8 +6426,8 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but,
float rgb[3];
ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
- ui_rgb_to_color_picker_compat_v(rgb, hsv);
+ ui_scene_linear_to_perceptual_space(but, rgb);
+ ui_color_picker_rgb_to_hsv_compat(rgb, hsv);
/* exception, when using color wheel in 'locked' value state:
* allow choosing a hue for black values, by giving a tiny increment */
@@ -6418,8 +6454,8 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but,
/* calculate original hsv again */
copy_v3_v3(hsvo, hsv);
copy_v3_v3(rgbo, data->origvec);
- ui_scene_linear_to_color_picker_space(but, rgbo);
- ui_rgb_to_color_picker_compat_v(rgbo, hsvo);
+ ui_scene_linear_to_perceptual_space(but, rgbo);
+ ui_color_picker_rgb_to_hsv_compat(rgbo, hsvo);
/* and original position */
ui_hsvcircle_pos_from_vals(cpicker, &rect, hsvo, &xpos, &ypos);
@@ -6438,7 +6474,7 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but,
ui_color_snap_hue(snap, &hsv[0]);
}
- ui_color_picker_to_rgb_v(hsv, rgb);
+ ui_color_picker_hsv_to_rgb(hsv, rgb);
if ((cpicker->use_luminosity_lock)) {
if (!is_zero_v3(rgb)) {
@@ -6446,7 +6482,7 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but,
}
}
- ui_color_picker_to_scene_linear_space(but, rgb);
+ ui_perceptual_to_scene_linear_space(but, rgb);
ui_but_v3_set(but, rgb);
data->draglastx = mx;
@@ -6463,14 +6499,14 @@ static void ui_ndofedit_but_HSVCIRCLE(uiBut *but,
const bool shift)
{
ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
+ float *hsv = cpicker->hsv_perceptual;
float rgb[3];
float phi, r /*, sqr */ /* UNUSED */, v[2];
const float sensitivity = (shift ? 0.06f : 0.3f) * ndof->dt;
ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
- ui_rgb_to_color_picker_compat_v(rgb, hsv);
+ ui_scene_linear_to_perceptual_space(but, rgb);
+ ui_color_picker_rgb_to_hsv_compat(rgb, hsv);
/* Convert current color on hue/sat disc to circular coordinates phi, r */
phi = fmodf(hsv[0] + 0.25f, 1.0f) * -2.0f * (float)M_PI;
@@ -6520,7 +6556,7 @@ static void ui_ndofedit_but_HSVCIRCLE(uiBut *but,
hsv_clamp_v(hsv, FLT_MAX);
- ui_color_picker_to_rgb_v(hsv, data->vec);
+ ui_color_picker_hsv_to_rgb(hsv, data->vec);
if (cpicker->use_luminosity_lock) {
if (!is_zero_v3(data->vec)) {
@@ -6528,7 +6564,7 @@ static void ui_ndofedit_but_HSVCIRCLE(uiBut *but,
}
}
- ui_color_picker_to_scene_linear_space(but, data->vec);
+ ui_perceptual_to_scene_linear_space(but, data->vec);
ui_but_v3_set(but, data->vec);
}
#endif /* WITH_INPUT_NDOF */
@@ -6537,7 +6573,7 @@ static int ui_do_but_HSVCIRCLE(
bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
+ float *hsv = cpicker->hsv_perceptual;
int mx = event->x;
int my = event->y;
ui_window_to_block(data->region, block, &mx, &my);
@@ -6584,10 +6620,10 @@ static int ui_do_but_HSVCIRCLE(
def = MEM_callocN(sizeof(float) * len, "reset_defaults - float");
RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def);
- ui_color_picker_to_rgb_v(def, def_hsv);
+ ui_color_picker_hsv_to_rgb(def, def_hsv);
ui_but_v3_get(but, rgb);
- ui_rgb_to_color_picker_compat_v(rgb, hsv);
+ ui_color_picker_rgb_to_hsv_compat(rgb, hsv);
def_hsv[0] = hsv[0];
def_hsv[2] = hsv[2];
@@ -7844,7 +7880,10 @@ static ARegion *ui_but_tooltip_init(
uiBut *but = UI_region_active_but_get(region);
*r_exit_on_event = false;
if (but) {
- return UI_tooltip_create_from_button(C, region, but, is_label);
+ uiButExtraOpIcon *extra_icon = ui_but_extra_operator_icon_mouse_over_get(
+ but, but->active, CTX_wm_window(C)->eventstate);
+
+ return UI_tooltip_create_from_button_or_extra_icon(C, region, but, extra_icon, is_label);
}
return NULL;
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 90f5172f6ec..899f4a6ddb1 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -100,11 +100,12 @@ typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
#define ICON_TYPE_COLOR_TEXTURE 1
#define ICON_TYPE_MONO_TEXTURE 2
#define ICON_TYPE_BUFFER 3
-#define ICON_TYPE_VECTOR 4
-#define ICON_TYPE_GEOM 5
-#define ICON_TYPE_EVENT 6 /* draw keymap entries using custom renderer. */
-#define ICON_TYPE_GPLAYER 7
-#define ICON_TYPE_BLANK 8
+#define ICON_TYPE_IMBUF 4
+#define ICON_TYPE_VECTOR 5
+#define ICON_TYPE_GEOM 6
+#define ICON_TYPE_EVENT 7 /* draw keymap entries using custom renderer. */
+#define ICON_TYPE_GPLAYER 8
+#define ICON_TYPE_BLANK 9
typedef struct DrawInfo {
int type;
@@ -1147,6 +1148,9 @@ static DrawInfo *icon_create_drawinfo(Icon *icon)
if (ELEM(icon_data_type, ICON_DATA_ID, ICON_DATA_PREVIEW)) {
di->type = ICON_TYPE_PREVIEW;
}
+ else if (icon_data_type == ICON_DATA_IMBUF) {
+ di->type = ICON_TYPE_IMBUF;
+ }
else if (icon_data_type == ICON_DATA_GEOM) {
di->type = ICON_TYPE_GEOM;
}
@@ -1262,7 +1266,7 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
else if (!prv_img->rect[size]) {
prv_img->w[size] = render_size;
prv_img->h[size] = render_size;
- prv_img->flag[size] |= PRV_CHANGED;
+ prv_img->flag[size] |= (PRV_CHANGED | PRV_UNFINISHED);
prv_img->changed_timestamp[size] = 0;
prv_img->rect[size] = MEM_callocN(render_size * render_size * sizeof(uint), "prv_rect");
}
@@ -1384,8 +1388,12 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi
}
}
-/* only called when icon has changed */
-/* only call with valid pointer from UI_icon_draw */
+/**
+ * * Only call with valid pointer from UI_icon_draw.
+ * * Only called when icon has changed.
+ *
+ * Note that if an ID doesn't support jobs for preview creation, \a use_job will be ignored.
+ */
static void icon_set_image(const bContext *C,
Scene *scene,
ID *id,
@@ -1408,7 +1416,7 @@ static void icon_set_image(const bContext *C,
const bool delay = prv_img->rect[size] != NULL;
icon_create_rect(prv_img, size);
- if (use_job) {
+ if (use_job && (!id || BKE_previewimg_id_supports_jobs(id))) {
/* Job (background) version */
ED_preview_icon_job(
C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size], delay);
@@ -1790,7 +1798,14 @@ static void icon_draw_size(float x,
/* We need to flush widget base first to ensure correct ordering. */
UI_widgetbase_draw_cache_flush();
- if (di->type == ICON_TYPE_VECTOR) {
+ if (di->type == ICON_TYPE_IMBUF) {
+ ImBuf *ibuf = icon->obj;
+
+ GPU_blend(GPU_BLEND_ALPHA_PREMULT);
+ icon_draw_rect(x, y, w, h, aspect, ibuf->x, ibuf->y, ibuf->rect, alpha, desaturate);
+ GPU_blend(GPU_BLEND_ALPHA);
+ }
+ else if (di->type == ICON_TYPE_VECTOR) {
/* vector icons use the uiBlock transformation, they are not drawn
* with untransformed coordinates like the other icons */
di->data.vector.func((int)x, (int)y, w, h, 1.0f);
@@ -1937,6 +1952,9 @@ static void ui_id_preview_image_render_size(
}
}
+/**
+ * Note that if an ID doesn't support jobs for preview creation, \a use_job will be ignored.
+ */
void UI_icon_render_id(const bContext *C, Scene *scene, ID *id, const bool big, const bool use_job)
{
PreviewImage *pi = BKE_previewimg_id_ensure(id);
@@ -1964,12 +1982,7 @@ static void ui_id_icon_render(const bContext *C, ID *id, bool use_jobs)
}
for (enum eIconSizes i = 0; i < NUM_ICON_SIZES; i++) {
- /* check if rect needs to be created; changed
- * only set by dynamic icons */
- if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) {
- icon_set_image(C, NULL, id, pi, i, use_jobs);
- pi->flag[i] &= ~PRV_CHANGED;
- }
+ ui_id_preview_image_render_size(C, NULL, id, pi, i, use_jobs);
}
}
@@ -2186,6 +2199,9 @@ int UI_icon_from_library(const ID *id)
if (ID_IS_OVERRIDE_LIBRARY(id)) {
return ICON_LIBRARY_DATA_OVERRIDE;
}
+ if (ID_IS_ASSET(id)) {
+ return ICON_MAT_SPHERE_SKY;
+ }
return ICON_NONE;
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 5c7cad4c8d5..c005b456b6a 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -220,8 +220,8 @@ struct uiBut {
const char *disabled_info;
BIFIconID icon;
- /** emboss: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied from the #uiBlock.emboss */
- char emboss;
+ /** Copied from the #uiBlock.emboss */
+ eUIEmbossType emboss;
/** direction in a pie menu, used for collision detection (RadialDirection) */
signed char pie_dir;
/** could be made into a single flag */
@@ -378,11 +378,20 @@ typedef struct uiButExtraOpIcon {
typedef struct ColorPicker {
struct ColorPicker *next, *prev;
- /** Color data, may be HSV or HSL. */
- float color_data[3];
- /** Initial color data (detect changes). */
- float color_data_init[3];
+
+ /** Color in HSV or HSL, in color picking color space. Used for HSV cube,
+ * circle and slider widgets. The color picking space is perceptually
+ * linear for intuitive editing. */
+ float hsv_perceptual[3];
+ /** Initial color data (to detect changes). */
+ float hsv_perceptual_init[3];
bool is_init;
+
+ /** HSV or HSL color in scene linear color space value used for number
+ * buttons. This is scene linear so that there is a clear correspondence
+ * to the scene linear RGB values. */
+ float hsv_scene_linear[3];
+
/** Cubic saturation for the color wheel. */
bool use_color_cubic;
bool use_color_lock;
@@ -493,8 +502,8 @@ struct uiBlock {
char direction;
/** UI_BLOCK_THEME_STYLE_* */
char theme_style;
- /** UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied to #uiBut.emboss */
- char emboss;
+ /** Copied to #uiBut.emboss */
+ eUIEmbossType emboss;
bool auto_open;
char _pad[5];
double auto_open_last;
@@ -734,15 +743,14 @@ struct uiPopupBlockHandle {
/* exposed as public API in UI_interface.h */
/* interface_region_color_picker.c */
-void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3]);
-void ui_rgb_to_color_picker_v(const float rgb[3], float r_cp[3]);
-void ui_color_picker_to_rgb_v(const float r_cp[3], float rgb[3]);
-void ui_color_picker_to_rgb(float r_cp0, float r_cp1, float r_cp2, float *r, float *g, float *b);
+void ui_color_picker_rgb_to_hsv_compat(const float rgb[3], float r_cp[3]);
+void ui_color_picker_rgb_to_hsv(const float rgb[3], float r_cp[3]);
+void ui_color_picker_hsv_to_rgb(const float r_cp[3], float rgb[3]);
bool ui_but_is_color_gamma(uiBut *but);
-void ui_scene_linear_to_color_picker_space(uiBut *but, float rgb[3]);
-void ui_color_picker_to_scene_linear_space(uiBut *but, float rgb[3]);
+void ui_scene_linear_to_perceptual_space(uiBut *but, float rgb[3]);
+void ui_perceptual_to_scene_linear_space(uiBut *but, float rgb[3]);
uiBlock *ui_block_func_COLOR(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
ColorPicker *ui_block_colorpicker_create(struct uiBlock *block);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 0403287125c..3ea7a5f5973 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -172,7 +172,7 @@ struct uiLayout {
/** For layouts inside gridflow, they and their items shall never have a fixed maximal size. */
bool variable_size;
char alignment;
- char emboss;
+ eUIEmbossType emboss;
/** for fixed width or height to avoid UI size changes */
float units[2];
};
@@ -651,7 +651,7 @@ static void ui_item_array(uiLayout *layout,
uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, 0, 0, w, UI_UNIT_Y);
}
else {
- /* even if 'expand' is fale, expanding anyway */
+ /* Even if 'expand' is false, we expand anyway. */
/* layout for known array subtypes */
char str[3] = {'\0'};
@@ -1189,7 +1189,7 @@ static uiBut *uiItemFullO_ptr_ex(uiLayout *layout,
const int w = ui_text_icon_width(layout, name, icon, 0);
- const int prev_emboss = layout->emboss;
+ const eUIEmbossType prev_emboss = layout->emboss;
if (flag & UI_ITEM_R_NO_BG) {
layout->emboss = UI_EMBOSS_NONE;
}
@@ -2120,7 +2120,7 @@ void uiItemFullR(uiLayout *layout,
int w, h;
ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, compact, &w, &h);
- const int prev_emboss = layout->emboss;
+ const eUIEmbossType prev_emboss = layout->emboss;
if (no_bg) {
layout->emboss = UI_EMBOSS_NONE;
}
@@ -3457,8 +3457,6 @@ static void menu_item_enum_rna_menu(bContext *UNUSED(C), uiLayout *layout, void
void uiItemMenuEnumR_prop(
uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon)
{
- MenuItemLevel *lvl;
-
if (!name) {
name = RNA_property_ui_name(prop);
}
@@ -3466,7 +3464,7 @@ void uiItemMenuEnumR_prop(
icon = ICON_BLANK1;
}
- lvl = MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
+ MenuItemLevel *lvl = MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
lvl->rnapoin = *ptr;
BLI_strncpy(lvl->propname, RNA_property_identifier(prop), sizeof(lvl->propname));
lvl->opcontext = layout->root->opcontext;
@@ -3550,15 +3548,15 @@ static int ui_litem_min_width(int itemw)
static void ui_litem_layout_row(uiLayout *litem)
{
uiItem *last_free_item = NULL;
- int x, y, w, tot, totw, neww, newtotw, itemw, minw, itemh, offset;
- int fixedw, freew, fixedx, freex, flag = 0, lastw = 0;
+ int x, neww, newtotw, itemw, minw, itemh, offset;
+ int freew, fixedx, freex, flag = 0, lastw = 0;
float extra_pixel;
/* x = litem->x; */ /* UNUSED */
- y = litem->y;
- w = litem->w;
- totw = 0;
- tot = 0;
+ int y = litem->y;
+ int w = litem->w;
+ int totw = 0;
+ int tot = 0;
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
ui_item_size(item, &itemw, &itemh);
@@ -3573,7 +3571,7 @@ static void ui_litem_layout_row(uiLayout *litem)
if (w != 0) {
w -= (tot - 1) * litem->space;
}
- fixedw = 0;
+ int fixedw = 0;
/* keep clamping items to fixed minimum size until all are done */
do {
@@ -3724,12 +3722,11 @@ static void ui_litem_estimate_column(uiLayout *litem, bool is_box)
static void ui_litem_layout_column(uiLayout *litem, bool is_box, bool is_menu)
{
- int itemw, itemh, x, y;
-
- x = litem->x;
- y = litem->y;
+ int x = litem->x;
+ int y = litem->y;
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
+ int itemw, itemh;
ui_item_size(item, &itemw, &itemh);
y -= itemh;
@@ -3753,15 +3750,13 @@ static void ui_litem_layout_column(uiLayout *litem, bool is_box, bool is_menu)
* stores a float vector in unit circle */
static RadialDirection ui_get_radialbut_vec(float vec[2], short itemnum)
{
- RadialDirection dir;
-
if (itemnum >= PIE_MAX_ITEMS) {
itemnum %= PIE_MAX_ITEMS;
printf("Warning: Pie menus with more than %i items are currently unsupported\n",
PIE_MAX_ITEMS);
}
- dir = ui_radial_dir_order[itemnum];
+ RadialDirection dir = ui_radial_dir_order[itemnum];
ui_but_pie_dir(dir, vec);
return dir;
@@ -3789,7 +3784,7 @@ static bool ui_item_is_radial_drawable(uiButtonItem *bitem)
static void ui_litem_layout_radial(uiLayout *litem)
{
- int itemh, itemw, x, y;
+ int itemh, itemw;
int itemnum = 0;
int totitems = 0;
@@ -3800,8 +3795,8 @@ static void ui_litem_layout_radial(uiLayout *litem)
const int pie_radius = U.pie_menu_radius * UI_DPI_FAC;
- x = litem->x;
- y = litem->y;
+ int x = litem->x;
+ int y = litem->y;
int minx = x, miny = y, maxx = x, maxy = y;
@@ -3921,16 +3916,14 @@ static void ui_litem_layout_box(uiLayout *litem)
{
uiLayoutItemBx *box = (uiLayoutItemBx *)litem;
const uiStyle *style = litem->root->style;
- uiBut *but;
- int w, h;
int boxspace = style->boxspace;
if (litem->root->type == UI_LAYOUT_HEADER) {
boxspace = 0;
}
- w = litem->w;
- h = litem->h;
+ int w = litem->w;
+ int h = litem->h;
litem->x += boxspace;
litem->y -= boxspace;
@@ -3955,7 +3948,7 @@ static void ui_litem_layout_box(uiLayout *litem)
}
/* roundbox around the sublayout */
- but = box->roundbox;
+ uiBut *but = box->roundbox;
but->rect.xmin = litem->x;
but->rect.ymin = litem->y;
but->rect.xmax = litem->x + litem->w;
@@ -3967,12 +3960,11 @@ static void ui_litem_estimate_column_flow(uiLayout *litem)
{
const uiStyle *style = litem->root->style;
uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem;
- int col, x, y, emh, emy, miny, itemw, itemh, maxw = 0;
- int toth, totitem;
+ int itemw, itemh, maxw = 0;
/* compute max needed width and total height */
- toth = 0;
- totitem = 0;
+ int toth = 0;
+ int totitem = 0;
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
ui_item_size(item, &itemw, &itemh);
maxw = MAX2(maxw, itemw);
@@ -3995,16 +3987,16 @@ static void ui_litem_estimate_column_flow(uiLayout *litem)
}
/* compute sizes */
- x = 0;
- y = 0;
- emy = 0;
- miny = 0;
+ int x = 0;
+ int y = 0;
+ int emy = 0;
+ int miny = 0;
maxw = 0;
- emh = toth / flow->totcol;
+ int emh = toth / flow->totcol;
/* create column per column */
- col = 0;
+ int col = 0;
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
ui_item_size(item, &itemw, &itemh);
@@ -4031,12 +4023,11 @@ static void ui_litem_layout_column_flow(uiLayout *litem)
{
const uiStyle *style = litem->root->style;
uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem;
- int col, x, y, w, emh, emy, miny, itemw, itemh;
- int toth, totitem;
+ int col, emh, itemw, itemh;
/* compute max needed width and total height */
- toth = 0;
- totitem = 0;
+ int toth = 0;
+ int totitem = 0;
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
ui_item_size(item, &itemw, &itemh);
toth += itemh;
@@ -4044,12 +4035,12 @@ static void ui_litem_layout_column_flow(uiLayout *litem)
}
/* compute sizes */
- x = litem->x;
- y = litem->y;
- emy = 0;
- miny = 0;
+ int x = litem->x;
+ int y = litem->y;
+ int emy = 0;
+ int miny = 0;
- w = litem->w - (flow->totcol - 1) * style->columnspace;
+ int w = litem->w - (flow->totcol - 1) * style->columnspace;
emh = toth / flow->totcol;
/* create column per column */
@@ -4457,14 +4448,13 @@ static void ui_litem_layout_grid_flow(uiLayout *litem)
/* free layout */
static void ui_litem_estimate_absolute(uiLayout *litem)
{
- int itemx, itemy, itemw, itemh, minx, miny;
-
- minx = 1e6;
- miny = 1e6;
+ int minx = 1e6;
+ int miny = 1e6;
litem->w = 0;
litem->h = 0;
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
+ int itemx, itemy, itemw, itemh;
ui_item_offset(item, &itemx, &itemy);
ui_item_size(item, &itemw, &itemh);
@@ -4482,12 +4472,12 @@ static void ui_litem_estimate_absolute(uiLayout *litem)
static void ui_litem_layout_absolute(uiLayout *litem)
{
float scalex = 1.0f, scaley = 1.0f;
- int x, y, newx, newy, itemx, itemy, itemh, itemw, minx, miny, totw, toth;
+ int x, y, newx, newy, itemx, itemy, itemh, itemw;
- minx = 1e6;
- miny = 1e6;
- totw = 0;
- toth = 0;
+ int minx = 1e6;
+ int miny = 1e6;
+ int totw = 0;
+ int toth = 0;
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
ui_item_offset(item, &itemx, &itemy);
@@ -4548,24 +4538,24 @@ static void ui_litem_estimate_split(uiLayout *litem)
static void ui_litem_layout_split(uiLayout *litem)
{
uiLayoutItemSplit *split = (uiLayoutItemSplit *)litem;
- float percentage, extra_pixel = 0.0f;
+ float extra_pixel = 0.0f;
const int tot = BLI_listbase_count(&litem->items);
- int itemh, x, y, w, colw = 0;
if (tot == 0) {
return;
}
- x = litem->x;
- y = litem->y;
+ int x = litem->x;
+ int y = litem->y;
- percentage = (split->percentage == 0.0f) ? 1.0f / (float)tot : split->percentage;
+ float percentage = (split->percentage == 0.0f) ? 1.0f / (float)tot : split->percentage;
- w = (litem->w - (tot - 1) * litem->space);
- colw = w * percentage;
+ int w = (litem->w - (tot - 1) * litem->space);
+ int colw = w * percentage;
colw = MAX2(colw, 0);
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
+ int itemh;
ui_item_size(item, NULL, &itemh);
ui_item_position(item, x, y - itemh, colw, itemh);
@@ -4590,12 +4580,11 @@ static void ui_litem_layout_split(uiLayout *litem)
/* overlap layout */
static void ui_litem_estimate_overlap(uiLayout *litem)
{
- int itemw, itemh;
-
litem->w = 0;
litem->h = 0;
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
+ int itemw, itemh;
ui_item_size(item, &itemw, &itemh);
litem->w = MAX2(itemw, litem->w);
@@ -4605,12 +4594,12 @@ static void ui_litem_estimate_overlap(uiLayout *litem)
static void ui_litem_layout_overlap(uiLayout *litem)
{
- int itemw, itemh, x, y;
- x = litem->x;
- y = litem->y;
+ int x = litem->x;
+ int y = litem->y;
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
+ int itemw, itemh;
ui_item_size(item, &itemw, &itemh);
ui_item_position(item, x, y - itemh, litem->w, itemh);
@@ -4657,9 +4646,7 @@ static void ui_layout_heading_set(uiLayout *layout, const char *heading)
/* layout create functions */
uiLayout *uiLayoutRow(uiLayout *layout, bool align)
{
- uiLayout *litem;
-
- litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
+ uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
ui_litem_init_from_parent(litem, layout, align);
litem->item.type = ITEM_LAYOUT_ROW;
@@ -4682,9 +4669,7 @@ uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *headi
uiLayout *uiLayoutColumn(uiLayout *layout, bool align)
{
- uiLayout *litem;
-
- litem = MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
+ uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
ui_litem_init_from_parent(litem, layout, align);
litem->item.type = ITEM_LAYOUT_COLUMN;
@@ -4710,9 +4695,7 @@ uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *he
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align)
{
- uiLayoutItemFlow *flow;
-
- flow = MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
+ uiLayoutItemFlow *flow = MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
ui_litem_init_from_parent(&flow->litem, layout, align);
flow->litem.item.type = ITEM_LAYOUT_COLUMN_FLOW;
@@ -4731,9 +4714,7 @@ uiLayout *uiLayoutGridFlow(uiLayout *layout,
bool even_rows,
bool align)
{
- uiLayoutItemGridFlow *flow;
-
- flow = MEM_callocN(sizeof(uiLayoutItemGridFlow), __func__);
+ uiLayoutItemGridFlow *flow = MEM_callocN(sizeof(uiLayoutItemGridFlow), __func__);
flow->litem.item.type = ITEM_LAYOUT_GRID_FLOW;
ui_litem_init_from_parent(&flow->litem, layout, align);
@@ -4750,9 +4731,7 @@ uiLayout *uiLayoutGridFlow(uiLayout *layout,
static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type)
{
- uiLayoutItemBx *box;
-
- box = MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
+ uiLayoutItemBx *box = MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
ui_litem_init_from_parent(&box->litem, layout, false);
box->litem.item.type = ITEM_LAYOUT_BOX;
@@ -4767,8 +4746,6 @@ static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type)
uiLayout *uiLayoutRadial(uiLayout *layout)
{
- uiLayout *litem;
-
/* radial layouts are only valid for radial menus */
if (layout->root->type != UI_LAYOUT_PIEMENU) {
return ui_item_local_sublayout(layout, layout, 0);
@@ -4776,14 +4753,14 @@ uiLayout *uiLayoutRadial(uiLayout *layout)
/* only one radial wheel per root layout is allowed, so check and return that, if it exists */
LISTBASE_FOREACH (uiItem *, item, &layout->root->layout->items) {
- litem = (uiLayout *)item;
+ uiLayout *litem = (uiLayout *)item;
if (litem->item.type == ITEM_LAYOUT_RADIAL) {
UI_block_layout_set_current(layout->root->block, litem);
return litem;
}
}
- litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRadial");
+ uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRadial");
ui_litem_init_from_parent(litem, layout, false);
litem->item.type = ITEM_LAYOUT_RADIAL;
@@ -4838,9 +4815,7 @@ uiLayout *uiLayoutListBox(uiLayout *layout,
uiLayout *uiLayoutAbsolute(uiLayout *layout, bool align)
{
- uiLayout *litem;
-
- litem = MEM_callocN(sizeof(uiLayout), "uiLayoutAbsolute");
+ uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutAbsolute");
ui_litem_init_from_parent(litem, layout, align);
litem->item.type = ITEM_LAYOUT_ABSOLUTE;
@@ -4852,9 +4827,7 @@ uiLayout *uiLayoutAbsolute(uiLayout *layout, bool align)
uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout)
{
- uiBlock *block;
-
- block = uiLayoutGetBlock(layout);
+ uiBlock *block = uiLayoutGetBlock(layout);
uiLayoutAbsolute(layout, false);
return block;
@@ -4862,9 +4835,7 @@ uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout)
uiLayout *uiLayoutOverlap(uiLayout *layout)
{
- uiLayout *litem;
-
- litem = MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap");
+ uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap");
ui_litem_init_from_parent(litem, layout, false);
litem->item.type = ITEM_LAYOUT_OVERLAP;
@@ -4876,9 +4847,7 @@ uiLayout *uiLayoutOverlap(uiLayout *layout)
uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, bool align)
{
- uiLayoutItemSplit *split;
-
- split = MEM_callocN(sizeof(uiLayoutItemSplit), "uiLayoutItemSplit");
+ uiLayoutItemSplit *split = MEM_callocN(sizeof(uiLayoutItemSplit), "uiLayoutItemSplit");
ui_litem_init_from_parent(&split->litem, layout, align);
split->litem.item.type = ITEM_LAYOUT_SPLIT;
@@ -4945,7 +4914,7 @@ void uiLayoutSetUnitsY(uiLayout *layout, float unit)
layout->units[1] = unit;
}
-void uiLayoutSetEmboss(uiLayout *layout, char emboss)
+void uiLayoutSetEmboss(uiLayout *layout, eUIEmbossType emboss)
{
layout->emboss = emboss;
}
@@ -5030,7 +4999,7 @@ float uiLayoutGetUnitsY(uiLayout *layout)
return layout->units[1];
}
-int uiLayoutGetEmboss(uiLayout *layout)
+eUIEmbossType uiLayoutGetEmboss(uiLayout *layout)
{
if (layout->emboss == UI_EMBOSS_UNDEFINED) {
return layout->root->block->emboss;
@@ -5290,12 +5259,9 @@ static void ui_item_estimate(uiItem *item)
static void ui_item_align(uiLayout *litem, short nr)
{
- uiButtonItem *bitem;
- uiLayoutItemBx *box;
-
LISTBASE_FOREACH_BACKWARD (uiItem *, item, &litem->items) {
if (item->type == ITEM_BUTTON) {
- bitem = (uiButtonItem *)item;
+ uiButtonItem *bitem = (uiButtonItem *)item;
#ifndef USE_UIBUT_SPATIAL_ALIGN
if (ui_but_can_align(bitem->but))
#endif
@@ -5312,7 +5278,7 @@ static void ui_item_align(uiLayout *litem, short nr)
/* pass */
}
else if (item->type == ITEM_LAYOUT_BOX) {
- box = (uiLayoutItemBx *)item;
+ uiLayoutItemBx *box = (uiLayoutItemBx *)item;
if (!box->roundbox->alignnr) {
box->roundbox->alignnr = nr;
}
@@ -5325,11 +5291,9 @@ static void ui_item_align(uiLayout *litem, short nr)
static void ui_item_flag(uiLayout *litem, int flag)
{
- uiButtonItem *bitem;
-
LISTBASE_FOREACH_BACKWARD (uiItem *, item, &litem->items) {
if (item->type == ITEM_BUTTON) {
- bitem = (uiButtonItem *)item;
+ uiButtonItem *bitem = (uiButtonItem *)item;
bitem->but->flag |= flag;
}
else {
@@ -5465,17 +5429,14 @@ uiLayout *UI_block_layout(uiBlock *block,
int padding,
const uiStyle *style)
{
- uiLayout *layout;
- uiLayoutRoot *root;
-
- root = MEM_callocN(sizeof(uiLayoutRoot), "uiLayoutRoot");
+ uiLayoutRoot *root = MEM_callocN(sizeof(uiLayoutRoot), "uiLayoutRoot");
root->type = type;
root->style = style;
root->block = block;
root->padding = padding;
root->opcontext = WM_OP_INVOKE_REGION_WIN;
- layout = MEM_callocN(sizeof(uiLayout), "uiLayout");
+ uiLayout *layout = MEM_callocN(sizeof(uiLayout), "uiLayout");
layout->item.type = (type == UI_LAYOUT_VERT_BAR) ? ITEM_LAYOUT_COLUMN : ITEM_LAYOUT_ROOT;
/* Only used when 'UI_ITEM_PROP_SEP' is set. */
@@ -5485,8 +5446,8 @@ uiLayout *UI_block_layout(uiBlock *block,
layout->y = y;
layout->root = root;
layout->space = style->templatespace;
- layout->active = 1;
- layout->enabled = 1;
+ layout->active = true;
+ layout->enabled = true;
layout->context = NULL;
layout->emboss = UI_EMBOSS_UNDEFINED;
@@ -5529,9 +5490,7 @@ void UI_block_layout_set_current(uiBlock *block, uiLayout *layout)
void ui_layout_add_but(uiLayout *layout, uiBut *but)
{
- uiButtonItem *bitem;
-
- bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
+ uiButtonItem *bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
bitem->item.type = ITEM_BUTTON;
bitem->but = but;
@@ -5663,6 +5622,11 @@ void uiLayoutSetContextPointer(uiLayout *layout, const char *name, PointerRNA *p
layout->context = CTX_store_add(&block->contexts, name, ptr);
}
+bContextStore *uiLayoutGetContextStore(uiLayout *layout)
+{
+ return layout->context;
+}
+
void uiLayoutContextCopy(uiLayout *layout, bContextStore *context)
{
uiBlock *block = layout->root->block;
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 0d1e2802242..2995cff8ed5 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1223,7 +1223,7 @@ typedef struct uiEditSourceStore {
typedef struct uiEditSourceButStore {
char py_dbg_fn[FILE_MAX];
- int py_dbg_ln;
+ int py_dbg_line_number;
} uiEditSourceButStore;
/* should only ever be set while the edit source operator is running */
@@ -1276,21 +1276,21 @@ void UI_editsource_active_but_test(uiBut *but)
struct uiEditSourceButStore *but_store = MEM_callocN(sizeof(uiEditSourceButStore), __func__);
const char *fn;
- int lineno = -1;
+ int line_number = -1;
# if 0
printf("comparing buttons: '%s' == '%s'\n", but->drawstr, ui_editsource_info->but_orig.drawstr);
# endif
- PyC_FileAndNum_Safe(&fn, &lineno);
+ PyC_FileAndNum_Safe(&fn, &line_number);
- if (lineno != -1) {
+ if (line_number != -1) {
BLI_strncpy(but_store->py_dbg_fn, fn, sizeof(but_store->py_dbg_fn));
- but_store->py_dbg_ln = lineno;
+ but_store->py_dbg_line_number = line_number;
}
else {
but_store->py_dbg_fn[0] = '\0';
- but_store->py_dbg_ln = -1;
+ but_store->py_dbg_line_number = -1;
}
BLI_ghash_insert(ui_editsource_info->hash, but, but_store);
@@ -1375,8 +1375,8 @@ static int editsource_exec(bContext *C, wmOperator *op)
}
if (but_store) {
- if (but_store->py_dbg_ln != -1) {
- ret = editsource_text_edit(C, op, but_store->py_dbg_fn, but_store->py_dbg_ln);
+ if (but_store->py_dbg_line_number != -1) {
+ ret = editsource_text_edit(C, op, but_store->py_dbg_fn, but_store->py_dbg_line_number);
}
else {
BKE_report(
@@ -1521,6 +1521,7 @@ static int edittranslation_exec(bContext *C, wmOperator *op)
UI_but_string_info_get(C,
but,
+ NULL,
&but_label,
&rna_label,
&enum_label,
diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c
index f9a9e7182d2..82028d4e595 100644
--- a/source/blender/editors/interface/interface_region_color_picker.c
+++ b/source/blender/editors/interface/interface_region_color_picker.c
@@ -77,8 +77,10 @@ static void ui_color_picker_rgb_round(float rgb[3])
}
}
-void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3])
+void ui_color_picker_rgb_to_hsv_compat(const float rgb[3], float r_cp[3])
{
+ /* Convert RGB to HSV, remaining as compatible as possible with the existing
+ * r_hsv value (for example when value goes to zero, preserve the hue). */
switch (U.color_picker_type) {
case USER_CP_CIRCLE_HSL:
rgb_to_hsl_compat_v(rgb, r_cp);
@@ -89,7 +91,7 @@ void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3])
}
}
-void ui_rgb_to_color_picker_v(const float rgb[3], float r_cp[3])
+void ui_color_picker_rgb_to_hsv(const float rgb[3], float r_cp[3])
{
switch (U.color_picker_type) {
case USER_CP_CIRCLE_HSL:
@@ -101,7 +103,7 @@ void ui_rgb_to_color_picker_v(const float rgb[3], float r_cp[3])
}
}
-void ui_color_picker_to_rgb_v(const float r_cp[3], float rgb[3])
+void ui_color_picker_hsv_to_rgb(const float r_cp[3], float rgb[3])
{
switch (U.color_picker_type) {
case USER_CP_CIRCLE_HSL:
@@ -113,18 +115,6 @@ void ui_color_picker_to_rgb_v(const float r_cp[3], float rgb[3])
}
}
-void ui_color_picker_to_rgb(float r_cp0, float r_cp1, float r_cp2, float *r, float *g, float *b)
-{
- switch (U.color_picker_type) {
- case USER_CP_CIRCLE_HSL:
- hsl_to_rgb(r_cp0, r_cp1, r_cp2, r, g, b);
- break;
- default:
- hsv_to_rgb(r_cp0, r_cp1, r_cp2, r, g, b);
- break;
- }
-}
-
/* Returns true if the button is for a color with gamma baked in,
* or if it's a color picker for such a button. */
bool ui_but_is_color_gamma(uiBut *but)
@@ -138,7 +128,7 @@ bool ui_but_is_color_gamma(uiBut *but)
return but->block->is_color_gamma_picker;
}
-void ui_scene_linear_to_color_picker_space(uiBut *but, float rgb[3])
+void ui_scene_linear_to_perceptual_space(uiBut *but, float rgb[3])
{
/* Map to color picking space for HSV values and HSV cube/circle,
* assuming it is more perceptually linear than the scene linear
@@ -149,7 +139,7 @@ void ui_scene_linear_to_color_picker_space(uiBut *but, float rgb[3])
}
}
-void ui_color_picker_to_scene_linear_space(uiBut *but, float rgb[3])
+void ui_perceptual_to_scene_linear_space(uiBut *but, float rgb[3])
{
if (!ui_but_is_color_gamma(but)) {
IMB_colormanagement_color_picking_to_scene_linear_v3(rgb);
@@ -163,16 +153,46 @@ void ui_color_picker_to_scene_linear_space(uiBut *but, float rgb[3])
/** \name Color Picker
* \{ */
+static void ui_color_picker_update_hsv(ColorPicker *cpicker,
+ uiBut *from_but,
+ const float rgb_scene_linear[3])
+{
+ /* Convert from RGB to HSV in scene linear space color for number editing. */
+ if (cpicker->is_init == false) {
+ ui_color_picker_rgb_to_hsv(rgb_scene_linear, cpicker->hsv_scene_linear);
+ }
+ else {
+ ui_color_picker_rgb_to_hsv_compat(rgb_scene_linear, cpicker->hsv_scene_linear);
+ }
+
+ /* Convert from RGB to HSV in perceptually linear space for picker widgets. */
+ float rgb_perceptual[3];
+ copy_v3_v3(rgb_perceptual, rgb_scene_linear);
+ if (from_but) {
+ ui_scene_linear_to_perceptual_space(from_but, rgb_perceptual);
+ }
+
+ if (cpicker->is_init == false) {
+ ui_color_picker_rgb_to_hsv(rgb_perceptual, cpicker->hsv_perceptual);
+ copy_v3_v3(cpicker->hsv_perceptual_init, cpicker->hsv_perceptual);
+ }
+ else {
+ ui_color_picker_rgb_to_hsv_compat(rgb_perceptual, cpicker->hsv_perceptual);
+ }
+
+ cpicker->is_init = true;
+}
+
/* for picker, while editing hsv */
void ui_but_hsv_set(uiBut *but)
{
- float col[3];
+ float rgb_perceptual[3];
ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
+ float *hsv_perceptual = cpicker->hsv_perceptual;
- ui_color_picker_to_rgb_v(hsv, col);
+ ui_color_picker_hsv_to_rgb(hsv_perceptual, rgb_perceptual);
- ui_but_v3_set(but, col);
+ ui_but_v3_set(but, rgb_perceptual);
}
/* Updates all buttons who share the same color picker as the one passed
@@ -180,17 +200,9 @@ void ui_but_hsv_set(uiBut *but)
static void ui_update_color_picker_buts_rgb(uiBut *from_but,
uiBlock *block,
ColorPicker *cpicker,
- const float rgb[3])
+ const float rgb_scene_linear[3])
{
- float *hsv = cpicker->color_data;
-
- /* Convert from RGB to HSV in perceptually linear space. */
- float tmp[3];
- copy_v3_v3(tmp, rgb);
- if (from_but) {
- ui_scene_linear_to_color_picker_space(from_but, tmp);
- }
- ui_rgb_to_color_picker_compat_v(tmp, hsv);
+ ui_color_picker_update_hsv(cpicker, from_but, rgb_scene_linear);
/* this updates button strings,
* is hackish... but button pointers are on stack of caller function */
@@ -200,7 +212,7 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but,
}
if (bt->rnaprop) {
- ui_but_v3_set(bt, rgb);
+ ui_but_v3_set(bt, rgb_scene_linear);
/* original button that created the color picker already does undo
* push, so disable it on RNA buttons in the color picker block */
@@ -213,7 +225,7 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but,
/* Hex code is assumed to be in sRGB space
* (coming from other applications, web, etc) */
- copy_v3_v3(rgb_hex, rgb);
+ copy_v3_v3(rgb_hex, rgb_scene_linear);
if (from_but && !ui_but_is_color_gamma(from_but)) {
IMB_colormanagement_scene_linear_to_srgb_v3(rgb_hex);
ui_color_picker_rgb_round(rgb_hex);
@@ -226,25 +238,25 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but,
}
else if (bt->str[1] == ' ') {
if (bt->str[0] == 'R') {
- ui_but_value_set(bt, rgb[0]);
+ ui_but_value_set(bt, rgb_scene_linear[0]);
}
else if (bt->str[0] == 'G') {
- ui_but_value_set(bt, rgb[1]);
+ ui_but_value_set(bt, rgb_scene_linear[1]);
}
else if (bt->str[0] == 'B') {
- ui_but_value_set(bt, rgb[2]);
+ ui_but_value_set(bt, rgb_scene_linear[2]);
}
else if (bt->str[0] == 'H') {
- ui_but_value_set(bt, hsv[0]);
+ ui_but_value_set(bt, cpicker->hsv_scene_linear[0]);
}
else if (bt->str[0] == 'S') {
- ui_but_value_set(bt, hsv[1]);
+ ui_but_value_set(bt, cpicker->hsv_scene_linear[1]);
}
else if (bt->str[0] == 'V') {
- ui_but_value_set(bt, hsv[2]);
+ ui_but_value_set(bt, cpicker->hsv_scene_linear[2]);
}
else if (bt->str[0] == 'L') {
- ui_but_value_set(bt, hsv[2]);
+ ui_but_value_set(bt, cpicker->hsv_scene_linear[2]);
}
}
@@ -252,17 +264,17 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but,
}
}
-static void ui_colorpicker_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
+static void ui_colorpicker_rgba_update_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
{
uiBut *but = (uiBut *)bt1;
uiPopupBlockHandle *popup = but->block->handle;
PropertyRNA *prop = but->rnaprop;
PointerRNA ptr = but->rnapoin;
- float rgb[4];
+ float rgb_scene_linear[4];
if (prop) {
- RNA_property_float_get_array(&ptr, prop, rgb);
- ui_update_color_picker_buts_rgb(but, but->block, but->custom_data, rgb);
+ RNA_property_float_get_array(&ptr, prop, rgb_scene_linear);
+ ui_update_color_picker_buts_rgb(but, but->block, but->custom_data, rgb_scene_linear);
}
if (popup) {
@@ -270,20 +282,15 @@ static void ui_colorpicker_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(a
}
}
-static void ui_color_wheel_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
+static void ui_colorpicker_hsv_update_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
{
uiBut *but = (uiBut *)bt1;
uiPopupBlockHandle *popup = but->block->handle;
- float rgb[3];
+ float rgb_scene_linear[3];
ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
- ui_color_picker_to_rgb_v(hsv, rgb);
-
- /* hsv is saved in perceptually linear space so convert back */
- ui_color_picker_to_scene_linear_space(but, rgb);
-
- ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb);
+ ui_color_picker_hsv_to_rgb(cpicker->hsv_scene_linear, rgb_scene_linear);
+ ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb_scene_linear);
if (popup) {
popup->menuretval = UI_RETURN_UPDATE;
@@ -321,7 +328,7 @@ static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
if (popup) {
ColorPicker *cpicker = but->custom_data;
BLI_assert(cpicker->is_init);
- popup->menuretval = (equals_v3v3(cpicker->color_data, cpicker->color_data_init) ?
+ popup->menuretval = (equals_v3v3(cpicker->hsv_perceptual, cpicker->hsv_perceptual_init) ?
UI_RETURN_CANCEL :
UI_RETURN_OK);
}
@@ -331,12 +338,12 @@ static void ui_colorpicker_hide_reveal(uiBlock *block, enum ePickerType colormod
{
/* tag buttons */
LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
- if ((bt->func == ui_colorpicker_rna_cb) && (bt->type == UI_BTYPE_NUM_SLIDER) &&
+ if ((bt->func == ui_colorpicker_rgba_update_cb) && (bt->type == UI_BTYPE_NUM_SLIDER) &&
(bt->rnaindex != 3)) {
/* RGB sliders (color circle and alpha are always shown) */
SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_RGB), UI_HIDDEN);
}
- else if (bt->func == ui_color_wheel_rna_cb) {
+ else if (bt->func == ui_colorpicker_hsv_update_cb) {
/* HSV sliders */
SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_HSV), UI_HIDDEN);
}
@@ -386,7 +393,7 @@ static void ui_colorpicker_circle(uiBlock *block,
0.0,
0,
TIP_("Color"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL);
bt->custom_data = cpicker;
/* value */
@@ -408,7 +415,7 @@ static void ui_colorpicker_circle(uiBlock *block,
0,
"Lightness");
hsv_but->gradient_type = UI_GRAD_L_ALT;
- UI_but_func_set(&hsv_but->but, ui_colorpicker_rna_cb, &hsv_but->but, NULL);
+ UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL);
}
else {
hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
@@ -428,7 +435,7 @@ static void ui_colorpicker_circle(uiBlock *block,
0,
TIP_("Value"));
hsv_but->gradient_type = UI_GRAD_V_ALT;
- UI_but_func_set(&hsv_but->but, ui_colorpicker_rna_cb, &hsv_but->but, NULL);
+ UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL);
}
hsv_but->but.custom_data = cpicker;
}
@@ -461,7 +468,7 @@ static void ui_colorpicker_square(uiBlock *block,
0,
TIP_("Color"));
hsv_but->gradient_type = type;
- UI_but_func_set(&hsv_but->but, ui_colorpicker_rna_cb, &hsv_but->but, NULL);
+ UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL);
hsv_but->but.custom_data = cpicker;
/* value */
@@ -482,12 +489,15 @@ static void ui_colorpicker_square(uiBlock *block,
0,
TIP_("Value"));
hsv_but->gradient_type = type + 3;
- UI_but_func_set(&hsv_but->but, ui_colorpicker_rna_cb, &hsv_but->but, NULL);
+ UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL);
hsv_but->but.custom_data = cpicker;
}
/* a HS circle, V slider, rgb/hsv/hex sliders */
-static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], bool show_picker)
+static void ui_block_colorpicker(uiBlock *block,
+ uiBut *from_but,
+ float rgba_scene_linear[4],
+ bool show_picker)
{
/* ePickerType */
static char colormode = 1;
@@ -497,7 +507,6 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
float softmin, softmax, hardmin, hardmax, step, precision;
int yco;
ColorPicker *cpicker = ui_block_colorpicker_create(block);
- float *hsv = cpicker->color_data;
PointerRNA *ptr = &from_but->rnapoin;
PropertyRNA *prop = from_but->rnaprop;
@@ -505,20 +514,13 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
butwidth = width - 1.5f * UI_UNIT_X;
/* sneaky way to check for alpha */
- rgba[3] = FLT_MAX;
+ rgba_scene_linear[3] = FLT_MAX;
RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
- RNA_property_float_get_array(ptr, prop, rgba);
+ RNA_property_float_get_array(ptr, prop, rgba_scene_linear);
- float rgb_perceptual[3];
- copy_v3_v3(rgb_perceptual, rgba);
- ui_scene_linear_to_color_picker_space(from_but, rgb_perceptual);
- ui_rgb_to_color_picker_v(rgb_perceptual, hsv);
- if (cpicker->is_init == false) {
- copy_v3_v3(cpicker->color_data_init, cpicker->color_data);
- cpicker->is_init = true;
- }
+ ui_color_picker_update_hsv(cpicker, from_but, rgba_scene_linear);
/* when the softmax isn't defined in the RNA,
* using very large numbers causes sRGB/linear round trip to fail. */
@@ -639,7 +641,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
0,
3,
TIP_("Red"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL);
bt->custom_data = cpicker;
bt = uiDefButR_prop(block,
UI_BTYPE_NUM_SLIDER,
@@ -657,7 +659,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
0,
3,
TIP_("Green"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL);
bt->custom_data = cpicker;
bt = uiDefButR_prop(block,
UI_BTYPE_NUM_SLIDER,
@@ -675,7 +677,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
0,
3,
TIP_("Blue"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL);
bt->custom_data = cpicker;
/* Could use:
@@ -693,14 +695,14 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
yco,
butwidth,
UI_UNIT_Y,
- hsv,
+ cpicker->hsv_scene_linear,
0.0,
1.0,
10,
3,
TIP_("Hue"));
UI_but_flag_disable(bt, UI_BUT_UNDO);
- UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
+ UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, NULL);
bt->custom_data = cpicker;
bt = uiDefButF(block,
UI_BTYPE_NUM_SLIDER,
@@ -710,14 +712,14 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
yco -= UI_UNIT_Y,
butwidth,
UI_UNIT_Y,
- hsv + 1,
+ cpicker->hsv_scene_linear + 1,
0.0,
1.0,
10,
3,
TIP_("Saturation"));
UI_but_flag_disable(bt, UI_BUT_UNDO);
- UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
+ UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, NULL);
bt->custom_data = cpicker;
if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
bt = uiDefButF(block,
@@ -728,7 +730,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
yco -= UI_UNIT_Y,
butwidth,
UI_UNIT_Y,
- hsv + 2,
+ cpicker->hsv_scene_linear + 2,
0.0,
1.0,
10,
@@ -744,7 +746,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
yco -= UI_UNIT_Y,
butwidth,
UI_UNIT_Y,
- hsv + 2,
+ cpicker->hsv_scene_linear + 2,
0.0,
softmax,
10,
@@ -754,12 +756,12 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
UI_but_flag_disable(bt, UI_BUT_UNDO);
bt->hardmax = hardmax; /* not common but rgb may be over 1.0 */
- UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
+ UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, NULL);
bt->custom_data = cpicker;
UI_block_align_end(block);
- if (rgba[3] != FLT_MAX) {
+ if (rgba_scene_linear[3] != FLT_MAX) {
bt = uiDefButR_prop(block,
UI_BTYPE_NUM_SLIDER,
0,
@@ -776,18 +778,18 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
0,
3,
TIP_("Alpha"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL);
bt->custom_data = cpicker;
}
else {
- rgba[3] = 1.0f;
+ rgba_scene_linear[3] = 1.0f;
}
/* Hex color is in sRGB space. */
float rgb_hex[3];
uchar rgb_hex_uchar[3];
- copy_v3_v3(rgb_hex, rgba);
+ copy_v3_v3(rgb_hex, rgba_scene_linear);
if (!ui_but_is_color_gamma(from_but)) {
IMB_colormanagement_scene_linear_to_srgb_v3(rgb_hex);
@@ -850,21 +852,22 @@ static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C),
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
if (but->type == UI_BTYPE_HSVCUBE && but->active == NULL) {
uiPopupBlockHandle *popup = block->handle;
- float rgb[3];
ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
+ float *hsv_perceptual = cpicker->hsv_perceptual;
- ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
- ui_rgb_to_color_picker_compat_v(rgb, hsv);
+ float rgb_perceptual[3];
+ ui_but_v3_get(but, rgb_perceptual);
+ ui_scene_linear_to_perceptual_space(but, rgb_perceptual);
+ ui_color_picker_rgb_to_hsv_compat(rgb_perceptual, hsv_perceptual);
- hsv[2] = clamp_f(hsv[2] + add, 0.0f, 1.0f);
+ hsv_perceptual[2] = clamp_f(hsv_perceptual[2] + add, 0.0f, 1.0f);
- ui_color_picker_to_rgb_v(hsv, rgb);
- ui_color_picker_to_scene_linear_space(but, rgb);
- ui_but_v3_set(but, rgb);
+ float rgb_scene_linear[3];
+ ui_color_picker_hsv_to_rgb(hsv_perceptual, rgb_scene_linear);
+ ui_perceptual_to_scene_linear_space(but, rgb_scene_linear);
+ ui_but_v3_set(but, rgb_scene_linear);
- ui_update_color_picker_buts_rgb(but, block, cpicker, rgb);
+ ui_update_color_picker_buts_rgb(but, block, cpicker, rgb_scene_linear);
if (popup) {
popup->menuretval = UI_RETURN_UPDATE;
}
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 12f3ba609f0..89515608c5b 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -534,7 +534,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
{
uiStringInfo op_keymap = {BUT_GET_OP_KEYMAP, NULL};
- UI_but_string_info_get(C, but, &op_keymap, NULL);
+ UI_but_string_info_get(C, but, NULL, &op_keymap, NULL);
shortcut = op_keymap.strinfo;
}
@@ -764,7 +764,9 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
return data;
}
-static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
+static uiTooltipData *ui_tooltip_data_from_button(bContext *C,
+ uiBut *but,
+ uiButExtraOpIcon *extra_icon)
{
uiStringInfo but_label = {BUT_GET_LABEL, NULL};
uiStringInfo but_tip = {BUT_GET_TIP, NULL};
@@ -777,20 +779,29 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
char buf[512];
+ wmOperatorType *extra_icon_optype = UI_but_extra_operator_icon_optype_get(extra_icon);
+ wmOperatorType *optype = extra_icon ? extra_icon_optype : but->optype;
+
/* create tooltip data */
uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
- UI_but_string_info_get(C,
- but,
- &but_label,
- &but_tip,
- &enum_label,
- &enum_tip,
- &op_keymap,
- &prop_keymap,
- &rna_struct,
- &rna_prop,
- NULL);
+ if (extra_icon) {
+ UI_but_string_info_get(C, but, extra_icon, &but_label, &but_tip, &op_keymap, NULL);
+ }
+ else {
+ UI_but_string_info_get(C,
+ but,
+ NULL,
+ &but_label,
+ &but_tip,
+ &enum_label,
+ &enum_tip,
+ &op_keymap,
+ &prop_keymap,
+ &rna_struct,
+ &rna_prop,
+ NULL);
+ }
/* Tip Label (only for buttons not already showing the label).
* Check prefix instead of comparing because the button may include the shortcut. */
@@ -923,15 +934,16 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
}
}
- else if (but->optype) {
- PointerRNA *opptr;
- char *str;
- opptr = UI_but_operator_ptr_get(but); /* allocated when needed, the button owns it */
+ else if (optype) {
+ PointerRNA *opptr = extra_icon_optype ?
+ UI_but_extra_operator_icon_opptr_get(extra_icon) :
+ UI_but_operator_ptr_get(
+ but); /* allocated when needed, the button owns it */
/* so the context is passed to fieldf functions (some py fieldf functions use it) */
WM_operator_properties_sanitize(opptr, false);
- str = ui_tooltip_text_python_from_op(C, but->optype, opptr);
+ char *str = ui_tooltip_text_python_from_op(C, optype, opptr);
/* operator info */
if (U.flag & USER_TOOLTIPS_PYTHON) {
@@ -958,7 +970,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
disabled_msg = CTX_wm_operator_poll_msg_get(C);
}
/* alternatively, buttons can store some reasoning too */
- else if (but->disabled_info) {
+ if (!disabled_msg && but->disabled_info) {
disabled_msg = TIP_(but->disabled_info);
}
@@ -1398,11 +1410,8 @@ static ARegion *ui_tooltip_create_with_data(bContext *C,
/** \name ToolTip Public API
* \{ */
-/**
- * \param is_label: When true, show a small tip that only shows the name,
- * otherwise show the full tooltip.
- */
-ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *but, bool is_label)
+ARegion *UI_tooltip_create_from_button_or_extra_icon(
+ bContext *C, ARegion *butregion, uiBut *but, uiButExtraOpIcon *extra_icon, bool is_label)
{
wmWindow *win = CTX_wm_window(C);
/* aspect values that shrink text are likely unreadable */
@@ -1419,7 +1428,7 @@ ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *b
}
if (data == NULL) {
- data = ui_tooltip_data_from_button(C, but);
+ data = ui_tooltip_data_from_button(C, but, extra_icon);
}
if (data == NULL) {
@@ -1457,6 +1466,15 @@ ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *b
return region;
}
+/**
+ * \param is_label: When true, show a small tip that only shows the name,
+ * otherwise show the full tooltip.
+ */
+ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *but, bool is_label)
+{
+ return UI_tooltip_create_from_button_or_extra_icon(C, butregion, but, NULL, is_label);
+}
+
ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz)
{
wmWindow *win = CTX_wm_window(C);
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index c3d528ad5c5..a37fb0dfde1 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -206,8 +206,12 @@ void UI_fontstyle_draw_ex(const uiFontStyle *fs,
BLF_disable(fs->uifont_id, font_flag);
- *r_xofs = xofs;
- *r_yofs = yofs;
+ if (r_xofs) {
+ *r_xofs = xofs;
+ }
+ if (r_yofs) {
+ *r_yofs = yofs;
+ }
}
void UI_fontstyle_draw(const uiFontStyle *fs,
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 43ead511cfe..404ae0df6a1 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -102,9 +102,16 @@
// #define USE_OP_RESET_BUT
/* defines for templateID/TemplateSearch */
-#define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 6)
+#define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 8)
#define TEMPLATE_SEARCH_TEXTBUT_HEIGHT UI_UNIT_Y
+/* Add "Make Single User" button to templateID. Users can just manually duplicate an ID, it's
+ * unclear what the use-case of this specific button is. So for now disabling it, we can bring it
+ * back or remove it later.
+ * - Julian
+ */
+//#define USE_TEMPLATE_ID_MAKE_SINGLE_USER
+
void UI_template_fix_linking(void)
{
}
@@ -308,6 +315,12 @@ typedef struct TemplateID {
ListBase *idlb;
short idcode;
+
+ const char *new_op;
+ const char *duplicate_op;
+ const char *unlink_op;
+ const char *open_op;
+
short filter;
int prv_rows, prv_cols;
bool preview;
@@ -564,80 +577,64 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
memset(&idptr, 0, sizeof(idptr));
RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
RNA_property_update(C, &template_ui->ptr, template_ui->prop);
-
- if (id && CTX_wm_window(C)->eventstate->shift) {
- /* only way to force-remove data (on save) */
- id_us_clear_real(id);
- id_fake_user_clear(id);
- id->us = 0;
- undo_push_label = "Delete Data-Block";
- }
-
break;
- case UI_ID_FAKE_USER:
+ case UI_ID_MAKE_LOCAL:
if (id) {
- if (id->flag & LIB_FAKEUSER) {
- id_us_plus(id);
- }
- else {
- id_us_min(id);
+ Main *bmain = CTX_data_main(C);
+ if (BKE_lib_id_make_local(bmain, id, false, 0)) {
+ BKE_main_id_clear_newpoins(bmain);
+
+ /* reassign to get get proper updates/notifiers */
+ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
+ RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+ undo_push_label = "Make Local";
}
- undo_push_label = "Fake User";
- }
- else {
- return;
}
break;
- case UI_ID_LOCAL:
- if (id) {
+ case UI_ID_LIB_OVERRIDE_ADD:
+ if (id && ID_IS_OVERRIDABLE_LIBRARY(id)) {
Main *bmain = CTX_data_main(C);
- if (CTX_wm_window(C)->eventstate->shift) {
- if (ID_IS_OVERRIDABLE_LIBRARY(id)) {
- /* Only remap that specific ID usage to overriding local data-block. */
- ID *override_id = BKE_lib_override_library_create_from_id(bmain, id, false);
- if (override_id != NULL) {
- BKE_main_id_clear_newpoins(bmain);
-
- if (GS(override_id->name) == ID_OB) {
- Scene *scene = CTX_data_scene(C);
- if (!BKE_collection_has_object_recursive(scene->master_collection,
- (Object *)override_id)) {
- BKE_collection_object_add_from(
- bmain, scene, (Object *)id, (Object *)override_id);
- }
- }
-
- /* Assign new pointer, takes care of updates/notifiers */
- RNA_id_pointer_create(override_id, &idptr);
+ /* Only remap that specific ID usage to overriding local data-block. */
+ ID *override_id = BKE_lib_override_library_create_from_id(bmain, id, false);
+ if (override_id != NULL) {
+ BKE_main_id_clear_newpoins(bmain);
+
+ if (GS(override_id->name) == ID_OB) {
+ Scene *scene = CTX_data_scene(C);
+ if (!BKE_collection_has_object_recursive(scene->master_collection,
+ (Object *)override_id)) {
+ BKE_collection_object_add_from(bmain, scene, (Object *)id, (Object *)override_id);
}
- undo_push_label = "Make Library Override";
}
- }
- else {
- if (BKE_lib_id_make_local(bmain, id, false, 0)) {
- BKE_main_id_clear_newpoins(bmain);
- /* reassign to get get proper updates/notifiers */
- idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
- undo_push_label = "Make Local";
- }
- }
- if (undo_push_label != NULL) {
- RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
- RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+ /* Assign new pointer, takes care of updates/notifiers */
+ RNA_id_pointer_create(override_id, &idptr);
}
+ /* reassign to get get proper updates/notifiers */
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
+ RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+ undo_push_label = "Make Library Override";
}
break;
- case UI_ID_OVERRIDE:
+ case UI_ID_LIB_OVERRIDE_RESET:
+ if (id && ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ Main *bmain = CTX_data_main(C);
+ BKE_lib_override_library_id_reset(bmain, id);
+ undo_push_label = "Reset Library Override";
+ }
+ break;
+ case UI_ID_LIB_OVERRIDE_REMOVE:
if (id && ID_IS_OVERRIDE_LIBRARY(id)) {
BKE_lib_override_library_free(&id->override_library, true);
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
RNA_property_update(C, &template_ui->ptr, template_ui->prop);
- undo_push_label = "Override Data-Block";
+ undo_push_label = "Remove Library Override";
}
break;
+#ifdef USE_TEMPLATE_ID_MAKE_SINGLE_USER
case UI_ID_ALONE:
if (id) {
const bool do_scene_obj = ((GS(id->name) == ID_OB) &&
@@ -659,6 +656,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
undo_push_label = "Make Single User";
}
break;
+#endif
#if 0
case UI_ID_AUTO_NAME:
break;
@@ -772,17 +770,221 @@ static const char *template_id_context(StructRNA *type)
# define template_id_context(type) 0
#endif
-static uiBut *template_id_def_new_but(uiBlock *block,
- const ID *id,
- const TemplateID *template_ui,
- StructRNA *type,
- const char *const newop,
- const bool editable,
- const bool id_open,
- const bool use_tab_but,
- int but_height)
-{
+static void template_id_linked_operation_button(
+ uiBlock *block, Main *bmain, ID *id, TemplateID *template_ui, int operation)
+{
+ BLI_assert(ELEM(operation, UI_ID_MAKE_LOCAL, UI_ID_LIB_OVERRIDE_ADD));
+
+ const char *label = (operation == UI_ID_MAKE_LOCAL) ?
+ CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Local") :
+ CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Library Override");
+ const char *tip = (operation == UI_ID_MAKE_LOCAL) ?
+ N_("Make library linked data-block local to this file") :
+ N_("Create a local override of this library linked data-block");
+ BIFIconID icon = (operation == UI_ID_MAKE_LOCAL) ? ICON_BLANK1 : ICON_LIBRARY_DATA_OVERRIDE;
+
+ uiBut *but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ icon,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, label),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_(tip));
+
+ bool disabled = false;
+
+ if (!ID_IS_LINKED(id)) {
+ disabled = true;
+ but->disabled_info = TIP_("Data-block is not linked");
+ }
+ else if (id->tag & LIB_TAG_INDIRECT) {
+ disabled = true;
+ but->disabled_info = TIP_("Indirect library data-block, cannot change");
+ }
+ else if (!BKE_lib_id_make_local(bmain, id, true /* test */, 0)) {
+ disabled = true;
+ but->disabled_info = TIP_("Data-blocks of this type cannot be made local");
+ }
+ else if (!RNA_property_editable_info(
+ &template_ui->ptr, template_ui->prop, &but->disabled_info)) {
+ disabled = true;
+ }
+
+ if (disabled) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ else {
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(operation));
+ }
+}
+
+static void template_id_library_overridden_button(uiBlock *block,
+ ID *id,
+ TemplateID *template_ui,
+ int operation)
+{
+ BLI_assert(ELEM(operation, UI_ID_LIB_OVERRIDE_RESET, UI_ID_LIB_OVERRIDE_REMOVE) &&
+ ID_IS_OVERRIDE_LIBRARY(id));
+
+ if (operation == UI_ID_LIB_OVERRIDE_RESET && ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ uiBut *but = uiDefIconTextBut(
+ block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_BLANK1,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Library Override"),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Reset the local override to the state of "
+ "the overridden data-block"));
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ but->disabled_info = TIP_("Data-block is a virtual, not a real override");
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ else {
+ UI_but_funcN_set(but,
+ template_id_cb,
+ MEM_dupallocN(template_ui),
+ POINTER_FROM_INT(UI_ID_LIB_OVERRIDE_RESET));
+ }
+ }
+ else if (operation == UI_ID_LIB_OVERRIDE_REMOVE) {
+ uiBut *but = uiDefIconTextBut(
+ block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_BLANK1,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Local"),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Remove library override and make the library linked data-block "
+ "fully local to this file"));
+ UI_but_funcN_set(but,
+ template_id_cb,
+ MEM_dupallocN(template_ui),
+ POINTER_FROM_INT(UI_ID_LIB_OVERRIDE_REMOVE));
+ }
+}
+
+#ifdef USE_TEMPLATE_ID_MAKE_SINGLE_USER
+static uiBut *template_id_make_single_user_button(uiBlock *block, ID *id, TemplateID *template_ui)
+{
+ uiBut *but = uiDefIconTextBut(
+ block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_BLANK1,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Single-User Copy"),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Duplicate the data-block and assign the newly created copy"));
+
+ if (ID_REAL_USERS(id) <= 1) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ but->disabled_info = TIP_("Data-block already is a single-user");
+ /* No need for further setup. */
+ return but;
+ }
+
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ALONE));
+
ID *idfrom = template_ui->ptr.owner_id;
+ bool disabled = false;
+
+ if (!RNA_property_editable_info(&template_ui->ptr, template_ui->prop, &but->disabled_info)) {
+ disabled = true;
+ }
+ if (!BKE_id_copy_is_allowed(id)) {
+ but->disabled_info = TIP_("Data-blocks of this type cannot be copied");
+ disabled = true;
+ }
+ /* object in editmode - don't change data */
+ if (idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT)) {
+ but->disabled_info = TIP_("Cannot change object data in Edit Mode");
+ disabled = true;
+ }
+
+ if (disabled) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+
+ return but;
+}
+#endif
+
+static void template_id_use_fake_user_button(uiBlock *block, PointerRNA *idptr)
+{
+ const bool use_fake_user = ID_FAKE_USERS(idptr->data) > 0;
+ uiBut *but = uiDefIconTextButR(
+ block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ ICON_FAKE_USER_OFF,
+ use_fake_user ? CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Fake User") :
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Fake User"),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ idptr,
+ "use_fake_user",
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ TIP_("When set, ensures the data-block is kept when reloading the file, even if not used at "
+ "all"));
+
+ if ((ELEM(GS(((ID *)idptr->data)->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
+ but->disabled_info = TIP_("Data-block type does not support fake user");
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+}
+
+enum TemplateIDCreateType {
+ TEMPLATE_ID_CREATE_NEW,
+ TEMPLATE_ID_CREATE_DUPLICATE,
+};
+
+static uiBut *template_id_new_button(uiBlock *block,
+ const ID *id,
+ TemplateID *template_ui,
+ enum TemplateIDCreateType create_type,
+ StructRNA *type,
+ const bool id_open,
+ const bool use_tab_but,
+ int but_height)
+{
uiBut *but;
const int w = id ? UI_UNIT_X : id_open ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
const int but_type = use_tab_but ? UI_BTYPE_TAB : UI_BTYPE_BUT;
@@ -820,54 +1022,384 @@ static uiBut *template_id_def_new_but(uiBlock *block,
BLT_I18NCONTEXT_ID_POINTCLOUD,
BLT_I18NCONTEXT_ID_VOLUME,
BLT_I18NCONTEXT_ID_SIMULATION, );
+ BLT_I18N_MSGID_MULTI_CTXT("Duplicate",
+ BLT_I18NCONTEXT_DEFAULT,
+ BLT_I18NCONTEXT_ID_SCENE,
+ BLT_I18NCONTEXT_ID_OBJECT,
+ BLT_I18NCONTEXT_ID_MESH,
+ BLT_I18NCONTEXT_ID_CURVE,
+ BLT_I18NCONTEXT_ID_METABALL,
+ BLT_I18NCONTEXT_ID_MATERIAL,
+ BLT_I18NCONTEXT_ID_TEXTURE,
+ BLT_I18NCONTEXT_ID_IMAGE,
+ BLT_I18NCONTEXT_ID_LATTICE,
+ BLT_I18NCONTEXT_ID_LIGHT,
+ BLT_I18NCONTEXT_ID_CAMERA,
+ BLT_I18NCONTEXT_ID_WORLD,
+ BLT_I18NCONTEXT_ID_SCREEN,
+ BLT_I18NCONTEXT_ID_TEXT, );
+ BLT_I18N_MSGID_MULTI_CTXT("Duplicate",
+ BLT_I18NCONTEXT_ID_SPEAKER,
+ BLT_I18NCONTEXT_ID_SOUND,
+ BLT_I18NCONTEXT_ID_ARMATURE,
+ BLT_I18NCONTEXT_ID_ACTION,
+ BLT_I18NCONTEXT_ID_NODETREE,
+ BLT_I18NCONTEXT_ID_BRUSH,
+ BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
+ BLT_I18NCONTEXT_ID_GPENCIL,
+ BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
+ BLT_I18NCONTEXT_ID_WORKSPACE,
+ BLT_I18NCONTEXT_ID_LIGHTPROBE,
+ BLT_I18NCONTEXT_ID_HAIR,
+ BLT_I18NCONTEXT_ID_POINTCLOUD,
+ BLT_I18NCONTEXT_ID_VOLUME,
+ BLT_I18NCONTEXT_ID_SIMULATION, );
/* Note: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters,
* check the definition to see if a new call must be added when the limit
* is exceeded. */
- if (newop) {
+ const char *text;
+ const char *op;
+ BIFIconID icon;
+
+ switch (create_type) {
+ case TEMPLATE_ID_CREATE_NEW:
+ icon = ICON_ADD;
+ text = CTX_IFACE_(template_id_context(type), "New");
+ op = template_ui->new_op;
+ break;
+ case TEMPLATE_ID_CREATE_DUPLICATE:
+ icon = ICON_DUPLICATE;
+ text = CTX_IFACE_(template_id_context(type), "Duplicate");
+ op = template_ui->duplicate_op;
+ break;
+ }
+
+ const bool icon_only = use_tab_but;
+ if (icon_only) {
+ text = "";
+ }
+
+ if (op) {
+ but = uiDefIconTextButO(
+ block, but_type, op, WM_OP_INVOKE_DEFAULT, icon, text, 0, 0, w, but_height, NULL);
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW));
+
+ if (!RNA_property_editable_info(&template_ui->ptr, template_ui->prop, &but->disabled_info)) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ }
+ else {
+ but = uiDefIconTextBut(block,
+ but_type,
+ 0,
+ icon,
+ text,
+ 0,
+ 0,
+ w,
+ but_height,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Create a new data-block"));
+ but->disabled_info = TIP_("Creating a new data-block is not supported here");
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ if (icon_only) {
+ UI_but_drawflag_disable(but, UI_BUT_ICON_LEFT);
+ }
+
+#ifndef WITH_INTERNATIONAL
+ UNUSED_VARS(type);
+#endif
+
+ return but;
+}
+
+static void template_id_unlink_button(uiBlock *block,
+ TemplateID *template_ui,
+ bool hide_if_disabled)
+{
+ const char *disable_info;
+ const bool is_menu = ui_block_is_menu(block);
+ const bool editable = RNA_property_editable_info(
+ &template_ui->ptr, template_ui->prop, &disable_info);
+ /* allow unlink if 'unlinkop' is passed, even when 'PROP_NEVER_UNLINK' is set */
+ uiBut *but = NULL;
+
+ if (hide_if_disabled && !editable) {
+ /* Add no button. */
+ }
+ else if (template_ui->unlink_op) {
but = uiDefIconTextButO(block,
- but_type,
- newop,
+ UI_BTYPE_BUT,
+ template_ui->unlink_op,
WM_OP_INVOKE_DEFAULT,
- (id && !use_tab_but) ? ICON_DUPLICATE : ICON_ADD,
- (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
+ ICON_X,
+ is_menu ? NULL : "",
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL);
+ /* so we can access the template from operators, font unlinking needs this */
+ UI_but_funcN_set(but, NULL, MEM_dupallocN(template_ui), NULL);
+ }
+ else {
+ const bool never_unlink = RNA_property_flag(template_ui->prop) &
+ (PROP_NEVER_UNLINK | PROP_NEVER_NULL);
+
+ if (!never_unlink || !hide_if_disabled) {
+ but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_X,
+ is_menu ? CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unlink") : "",
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Remove this usage of the data-block"));
+ if (!never_unlink) {
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_DELETE));
+ }
+ if (!is_menu) {
+ UI_but_drawflag_disable(but, UI_BUT_ICON_LEFT);
+ }
+ }
+
+ if (but && never_unlink) {
+ but->disabled_info = TIP_("Property must never be in an unlinked state");
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ }
+
+ if (but) {
+ if (!editable) {
+ but->disabled_info = disable_info;
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ }
+}
+
+static void template_id_open_button(uiBlock *block,
+ ID *id,
+ TemplateID *template_ui,
+ const bool compact)
+{
+ const bool is_menu = ui_block_is_menu(block);
+ const int w = compact ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
+ char text[UI_MAX_NAME_STR] = "";
+ const bool icon_only = !is_menu && id;
+ uiBut *but;
+
+ if (!icon_only) {
+ BLI_snprintf(text,
+ sizeof(text),
+ "%s%s",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open"),
+ is_menu ? "..." : "");
+ }
+
+ if (template_ui->open_op) {
+ but = uiDefIconTextButO(block,
+ UI_BTYPE_BUT,
+ template_ui->open_op,
+ WM_OP_INVOKE_DEFAULT,
+ ICON_FILEBROWSER,
+ text,
0,
0,
w,
- but_height,
+ UI_UNIT_Y,
NULL);
UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW));
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN));
}
else {
but = uiDefIconTextBut(block,
- but_type,
+ UI_BTYPE_BUT,
0,
- (id && !use_tab_but) ? ICON_DUPLICATE : ICON_ADD,
- (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
+ ICON_FILEBROWSER,
+ text,
0,
0,
w,
- but_height,
+ UI_UNIT_Y,
NULL,
0,
0,
0,
0,
NULL);
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW));
+ but->disabled_info = TIP_("Browsing for a new data-block is not supported here");
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
- if ((idfrom && idfrom->lib) || !editable) {
+ if (!RNA_property_editable_info(&template_ui->ptr, template_ui->prop, &but->disabled_info)) {
UI_but_flag_enable(but, UI_BUT_DISABLED);
}
+}
-#ifndef WITH_INTERNATIONAL
- UNUSED_VARS(type);
+static void template_id_unpack_button(uiBlock *block, ID *id)
+{
+ wmOperatorType *optype = WM_operatortype_find("FILE_OT_unpack_item", false);
+ uiBut *but;
+
+ but = uiDefIconTextButO_ptr(block,
+ UI_BTYPE_BUT,
+ optype,
+ WM_OP_INVOKE_REGION_WIN,
+ ICON_PACKAGE,
+ NULL,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL);
+
+ if (!BKE_packedfile_id_check(id)) {
+ but->disabled_info = TIP_("File is not packed");
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ UI_but_operator_ptr_get(but);
+
+ RNA_string_set(but->opptr, "id_name", id->name + 2);
+ RNA_int_set(but->opptr, "id_type", GS(id->name));
+}
+
+static void template_id_user_count_label(uiLayout *layout, const ID *id)
+{
+ char numstr[UI_MAX_NAME_STR];
+ BLI_snprintf(numstr,
+ sizeof(numstr),
+ "%d %s",
+ ID_REAL_USERS(id),
+ ID_REAL_USERS(id) > 1 ? IFACE_("Users") : IFACE_("User"));
+ uiItemL(layout, numstr, ICON_NONE);
+}
+
+static void template_id_menu(bContext *C, uiLayout *layout, void *arg)
+{
+ /* Button that spawned the menu. */
+ const uiBut *menu_parent_but = arg;
+ TemplateID *template_ui = menu_parent_but->func_argN;
+ PointerRNA idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ ID *id = idptr.data;
+ uiBlock *block = uiLayoutGetBlock(layout);
+
+ BLI_assert(id);
+
+ template_id_new_button(
+ block, id, template_ui, TEMPLATE_ID_CREATE_NEW, idptr.type, false, false, UI_UNIT_X);
+ template_id_new_button(
+ block, id, template_ui, TEMPLATE_ID_CREATE_DUPLICATE, idptr.type, false, false, UI_UNIT_X);
+ template_id_unlink_button(block, template_ui, false);
+
+#ifdef USE_TEMPLATE_ID_MAKE_SINGLE_USER
+ template_id_make_single_user_button(block, id, template_ui);
#endif
+ template_id_use_fake_user_button(block, &idptr);
- return but;
+ if (template_ui->open_op || BKE_packedfile_id_check(id)) {
+ uiItemS(layout);
+
+ template_id_open_button(block, id, template_ui, false);
+ template_id_unpack_button(block, id);
+ }
+
+ /* Library operators. */
+ if (ID_IS_OVERRIDE_LIBRARY(id)) {
+ uiItemS(layout);
+
+ template_id_library_overridden_button(block, id, template_ui, UI_ID_LIB_OVERRIDE_RESET);
+ template_id_library_overridden_button(block, id, template_ui, UI_ID_LIB_OVERRIDE_REMOVE);
+ }
+ else if (ID_IS_LINKED(id)) {
+ uiItemS(layout);
+
+ Main *bmain = CTX_data_main(C);
+ template_id_linked_operation_button(block, bmain, id, template_ui, UI_ID_MAKE_LOCAL);
+ template_id_linked_operation_button(block, bmain, id, template_ui, UI_ID_LIB_OVERRIDE_ADD);
+ }
+
+ uiItemS(layout);
+ template_id_user_count_label(layout, id);
+}
+
+static void template_id_name_button(
+ uiBlock *block, StructRNA *type, TemplateID *template_ui, int flag, const bool hide_extras)
+{
+ PointerRNA idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ ID *id = idptr.data;
+ BIFIconID lib_icon = UI_icon_from_library(id);
+
+ char name[UI_MAX_NAME_STR] = "";
+ uiBut *but = uiDefIconTextButR(block,
+ UI_BTYPE_TEXT,
+ 0,
+ lib_icon,
+ name,
+ 0,
+ 0,
+ TEMPLATE_SEARCH_TEXTBUT_WIDTH,
+ TEMPLATE_SEARCH_TEXTBUT_HEIGHT,
+ &idptr,
+ "name",
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ RNA_struct_ui_description(type));
+ /* Note: Also needed for the extra icons below (their operators access the TemplateID). */
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_RENAME));
+
+ const bool user_alert = (id->us <= 0);
+ if (user_alert) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+
+ if (hide_extras) {
+ return;
+ }
+
+ if (template_ui->duplicate_op && (flag & UI_ID_ADD_NEW)) {
+ UI_but_extra_operator_icon_add(
+ but, template_ui->duplicate_op, WM_OP_INVOKE_DEFAULT, ICON_DUPLICATE);
+ }
+
+ if (id && (flag & UI_ID_DELETE)) {
+ const bool never_unlink = RNA_property_flag(template_ui->prop) &
+ (PROP_NEVER_UNLINK | PROP_NEVER_NULL);
+ if (template_ui->unlink_op) {
+ UI_but_extra_operator_icon_add(but, template_ui->unlink_op, WM_OP_INVOKE_DEFAULT, ICON_X);
+ }
+ else if (!never_unlink) {
+ UI_but_extra_operator_icon_add(but, "ED_OT_lib_unlink", WM_OP_INVOKE_DEFAULT, ICON_X);
+ }
+ }
+
+ /* Disable fake user icon for now, only have it in the menu. */
+ const bool add_extra_fake_user_icon = false;
+ if (add_extra_fake_user_icon && id->lib == NULL &&
+ !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
+ UI_but_extra_operator_icon_add(but,
+ "ED_OT_lib_fake_user_toggle",
+ WM_OP_INVOKE_DEFAULT,
+ ID_FAKE_USERS(id) ? ICON_FAKE_USER_ON : ICON_FAKE_USER_OFF);
+ }
}
static void template_ID(const bContext *C,
@@ -875,9 +1407,6 @@ static void template_ID(const bContext *C,
TemplateID *template_ui,
StructRNA *type,
int flag,
- const char *newop,
- const char *openop,
- const char *unlinkop,
const char *text,
const bool live_icon,
const bool hide_buttons)
@@ -885,15 +1414,15 @@ static void template_ID(const bContext *C,
uiBut *but;
uiBlock *block;
PointerRNA idptr;
- // ListBase *lb; // UNUSED
- ID *id, *idfrom;
+ ID *id;
const bool editable = RNA_property_editable(&template_ui->ptr, template_ui->prop);
const bool use_previews = template_ui->preview = (flag & UI_ID_PREVIEWS) != 0;
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
id = idptr.data;
- idfrom = template_ui->ptr.owner_id;
- // lb = template_ui->idlb;
+
+ /* Allow opertators to take the ID from context. */
+ uiLayoutSetContextPointer(layout, "id", &idptr);
block = uiLayoutGetBlock(layout);
UI_block_align_begin(block);
@@ -923,277 +1452,39 @@ static void template_ID(const bContext *C,
/* text button with name */
if (id) {
- char name[UI_MAX_NAME_STR];
- const bool user_alert = (id->us <= 0);
-
- // text_idbutton(id, name);
- name[0] = '\0';
- but = uiDefButR(block,
- UI_BTYPE_TEXT,
- 0,
- name,
- 0,
- 0,
- TEMPLATE_SEARCH_TEXTBUT_WIDTH,
- TEMPLATE_SEARCH_TEXTBUT_HEIGHT,
- &idptr,
- "name",
- -1,
- 0,
- 0,
- -1,
- -1,
- RNA_struct_ui_description(type));
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_RENAME));
- if (user_alert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
-
- if (id->lib) {
- if (id->tag & LIB_TAG_INDIRECT) {
- but = uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_LIBRARY_DATA_INDIRECT,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Indirect library data-block, cannot change"));
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- else {
- const bool disabled = (!BKE_lib_id_make_local(CTX_data_main(C), id, true /* test */, 0) ||
- (idfrom && idfrom->lib));
- but = uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_LIBRARY_DATA_DIRECT,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Direct linked library data-block, click to make local, "
- "Shift + Click to create a library override"));
- if (disabled) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- else {
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_LOCAL));
- }
- }
- }
- else if (ID_IS_OVERRIDE_LIBRARY(id)) {
- but = uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_LIBRARY_DATA_OVERRIDE,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Library override of linked data-block, click to make fully local"));
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OVERRIDE));
- }
-
- if ((ID_REAL_USERS(id) > 1) && (hide_buttons == false)) {
- char numstr[32];
- short numstr_len;
-
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", ID_REAL_USERS(id));
-
- but = uiDefBut(
- block,
- UI_BTYPE_BUT,
- 0,
- numstr,
- 0,
- 0,
- numstr_len * 0.2f * UI_UNIT_X + UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Display number of users of this data (click to make a single-user copy)"));
- but->flag |= UI_BUT_UNDO;
-
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ALONE));
- if ((!BKE_id_copy_is_allowed(id)) || (idfrom && idfrom->lib) || (!editable) ||
- /* object in editmode - don't change data */
- (idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT))) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- }
-
- if (user_alert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
-
- if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS)) &&
- (hide_buttons == false)) {
- uiDefIconButR(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- ICON_FAKE_USER_OFF,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- &idptr,
- "use_fake_user",
- -1,
- 0,
- 0,
- -1,
- -1,
- NULL);
- }
+ template_id_name_button(block, type, template_ui, flag, hide_buttons);
}
-
- if ((flag & UI_ID_ADD_NEW) && (hide_buttons == false)) {
- template_id_def_new_but(
- block, id, template_ui, type, newop, editable, flag & UI_ID_OPEN, false, UI_UNIT_X);
+ /* If no ID is set, show a "new" button instead of a text button. */
+ else if ((flag & UI_ID_ADD_NEW) && (hide_buttons == false)) {
+ template_id_new_button(
+ block, id, template_ui, TEMPLATE_ID_CREATE_NEW, type, flag & UI_ID_OPEN, false, UI_UNIT_X);
}
- /* Due to space limit in UI - skip the "open" icon for packed data, and allow to unpack.
- * Only for images, sound and fonts */
- if (id && BKE_packedfile_id_check(id)) {
- but = uiDefIconButO(block,
- UI_BTYPE_BUT,
- "FILE_OT_unpack_item",
- WM_OP_INVOKE_REGION_WIN,
- ICON_PACKAGE,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- TIP_("Packed File, click to unpack"));
- UI_but_operator_ptr_get(but);
-
- RNA_string_set(but->opptr, "id_name", id->name + 2);
- RNA_int_set(but->opptr, "id_type", GS(id->name));
+ if ((flag & UI_ID_OPEN) && !id) {
+ template_id_open_button(block, id, template_ui, flag & UI_ID_ADD_NEW);
}
- else if (flag & UI_ID_OPEN) {
- const int w = id ? UI_UNIT_X : (flag & UI_ID_ADD_NEW) ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
-
- if (openop) {
- but = uiDefIconTextButO(block,
- UI_BTYPE_BUT,
- openop,
- WM_OP_INVOKE_DEFAULT,
- ICON_FILEBROWSER,
- (id) ? "" : IFACE_("Open"),
- 0,
- 0,
- w,
- UI_UNIT_Y,
- NULL);
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN));
- }
- else {
- but = uiDefIconTextBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_FILEBROWSER,
- (id) ? "" : IFACE_("Open"),
- 0,
- 0,
- w,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- NULL);
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN));
- }
- if ((idfrom && idfrom->lib) || !editable) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
+ if (template_ui->idcode == ID_TE) {
+ uiTemplateTextureShow(layout, C, &template_ui->ptr, template_ui->prop);
}
- /* delete button */
- /* don't use RNA_property_is_unlink here */
- if (id && (flag & UI_ID_DELETE) && (hide_buttons == false)) {
- /* allow unlink if 'unlinkop' is passed, even when 'PROP_NEVER_UNLINK' is set */
- but = NULL;
-
- if (unlinkop) {
- but = uiDefIconButO(block,
- UI_BTYPE_BUT,
- unlinkop,
- WM_OP_INVOKE_DEFAULT,
- ICON_X,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL);
- /* so we can access the template from operators, font unlinking needs this */
- UI_but_funcN_set(but, NULL, MEM_dupallocN(template_ui), NULL);
- }
- else {
- if ((RNA_property_flag(template_ui->prop) & PROP_NEVER_UNLINK) == 0) {
- but = uiDefIconBut(
- block,
- UI_BTYPE_BUT,
- 0,
- ICON_X,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Unlink data-block "
- "(Shift + Click to set users to zero, data will then not be saved)"));
- UI_but_funcN_set(
- but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_DELETE));
-
- if (RNA_property_flag(template_ui->prop) & PROP_NEVER_NULL) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- }
- }
-
- if (but) {
- if ((idfrom && idfrom->lib) || !editable) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- }
+ if (id && !hide_buttons) {
+ /* Additional operations menu ("Make Local", overrides, etc). */
+ but = uiDefIconMenuBut(block,
+ template_id_menu,
+ NULL,
+ ICON_DOWNARROW_HLT,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ TIP_("Show more operations for the selected data-block"));
+ UI_but_type_set_menu_from_pulldown(but);
+ /* Same hack as ui_item_menu() to allow allocated arg. */
+ but->poin = (char *)but;
+ but->func_argN = MEM_dupallocN(template_ui);
}
- if (template_ui->idcode == ID_TE) {
- uiTemplateTextureShow(layout, C, &template_ui->ptr, template_ui->prop);
- }
UI_block_align_end(block);
}
@@ -1212,7 +1503,6 @@ static void template_ID_tabs(const bContext *C,
TemplateID *template,
StructRNA *type,
int flag,
- const char *newop,
const char *menu)
{
const ARegion *region = CTX_wm_region(C);
@@ -1260,22 +1550,20 @@ static void template_ID_tabs(const bContext *C,
BLI_freelistN(&ordered);
if (flag & UI_ID_ADD_NEW) {
- const bool editable = RNA_property_editable(&template->ptr, template->prop);
uiBut *but;
if (active_ptr.type) {
type = active_ptr.type;
}
- but = template_id_def_new_but(block,
- active_ptr.data,
- template,
- type,
- newop,
- editable,
- flag & UI_ID_OPEN,
- true,
- but_height);
+ but = template_id_new_button(block,
+ active_ptr.data,
+ template,
+ TEMPLATE_ID_CREATE_NEW,
+ type,
+ flag & UI_ID_OPEN,
+ true,
+ but_height);
UI_but_drawflag_enable(but, but_align);
}
}
@@ -1285,6 +1573,7 @@ static void ui_template_id(uiLayout *layout,
PointerRNA *ptr,
const char *propname,
const char *newop,
+ const char *duplicateop,
const char *openop,
const char *unlinkop,
/* Only respected by tabs (use_tabs). */
@@ -1314,6 +1603,10 @@ static void ui_template_id(uiLayout *layout,
template_ui = MEM_callocN(sizeof(TemplateID), "TemplateID");
template_ui->ptr = *ptr;
template_ui->prop = prop;
+ template_ui->new_op = newop;
+ template_ui->duplicate_op = duplicateop;
+ template_ui->unlink_op = unlinkop;
+ template_ui->open_op = openop;
template_ui->prv_rows = prv_rows;
template_ui->prv_cols = prv_cols;
template_ui->scale = scale;
@@ -1325,7 +1618,7 @@ static void ui_template_id(uiLayout *layout,
template_ui->filter = 0;
}
- if (newop) {
+ if (newop || duplicateop) {
flag |= UI_ID_ADD_NEW;
}
if (openop) {
@@ -1343,21 +1636,11 @@ static void ui_template_id(uiLayout *layout,
if (template_ui->idlb) {
if (use_tabs) {
layout = uiLayoutRow(layout, true);
- template_ID_tabs(C, layout, template_ui, type, flag, newop, menu);
+ template_ID_tabs(C, layout, template_ui, type, flag, menu);
}
else {
layout = uiLayoutRow(layout, true);
- template_ID(C,
- layout,
- template_ui,
- type,
- flag,
- newop,
- openop,
- unlinkop,
- text,
- live_icon,
- hide_buttons);
+ template_ID(C, layout, template_ui, type, flag, text, live_icon, hide_buttons);
}
}
@@ -1369,6 +1652,7 @@ void uiTemplateID(uiLayout *layout,
PointerRNA *ptr,
const char *propname,
const char *newop,
+ const char *duplicateop,
const char *openop,
const char *unlinkop,
int filter,
@@ -1380,6 +1664,7 @@ void uiTemplateID(uiLayout *layout,
ptr,
propname,
newop,
+ duplicateop,
openop,
unlinkop,
NULL,
@@ -1409,6 +1694,7 @@ void uiTemplateIDBrowse(uiLayout *layout,
ptr,
propname,
newop,
+ NULL,
openop,
unlinkop,
NULL,
@@ -1440,6 +1726,7 @@ void uiTemplateIDPreview(uiLayout *layout,
ptr,
propname,
newop,
+ NULL,
openop,
unlinkop,
NULL,
@@ -1472,6 +1759,7 @@ void uiTemplateGpencilColorPreview(uiLayout *layout,
NULL,
NULL,
NULL,
+ NULL,
UI_ID_BROWSE | UI_ID_PREVIEWS | UI_ID_DELETE,
rows,
cols,
@@ -1500,6 +1788,7 @@ void uiTemplateIDTabs(uiLayout *layout,
newop,
NULL,
NULL,
+ NULL,
menu,
NULL,
UI_ID_BROWSE | UI_ID_RENAME,
@@ -1659,35 +1948,25 @@ static void template_search_add_button_searchmenu(const bContext *C,
static void template_search_add_button_name(uiBlock *block,
PointerRNA *active_ptr,
- const StructRNA *type)
+ const StructRNA *type,
+ const char *newop,
+ const char *unlinkop)
{
- uiDefAutoButR(block,
- active_ptr,
- RNA_struct_name_property(type),
- 0,
- "",
- ICON_NONE,
- 0,
- 0,
- TEMPLATE_SEARCH_TEXTBUT_WIDTH,
- TEMPLATE_SEARCH_TEXTBUT_HEIGHT);
-}
-
-static void template_search_add_button_operator(uiBlock *block,
- const char *const operator_name,
- const int opcontext,
- const int icon,
- const bool editable)
-{
- if (!operator_name) {
- return;
+ uiBut *but = uiDefAutoButR(block,
+ active_ptr,
+ RNA_struct_name_property(type),
+ 0,
+ "",
+ ICON_NONE,
+ 0,
+ 0,
+ TEMPLATE_SEARCH_TEXTBUT_WIDTH,
+ TEMPLATE_SEARCH_TEXTBUT_HEIGHT);
+ if (newop) {
+ UI_but_extra_operator_icon_add(but, newop, WM_OP_INVOKE_DEFAULT, ICON_DUPLICATE);
}
-
- uiBut *but = uiDefIconButO(
- block, UI_BTYPE_BUT, operator_name, opcontext, icon, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
-
- if (!editable) {
- UI_but_drawflag_enable(but, UI_BUT_DISABLED);
+ if (unlinkop) {
+ UI_but_extra_operator_icon_add(but, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X);
}
}
@@ -1713,10 +1992,7 @@ static void template_search_buttons(const bContext *C,
UI_block_align_begin(block);
template_search_add_button_searchmenu(C, layout, block, template_search, editable, false);
- template_search_add_button_name(block, &active_ptr, type);
- template_search_add_button_operator(
- block, newop, WM_OP_INVOKE_DEFAULT, ICON_DUPLICATE, editable);
- template_search_add_button_operator(block, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, editable);
+ template_search_add_button_name(block, &active_ptr, type, newop, unlinkop);
UI_block_align_end(block);
}
@@ -2011,7 +2287,7 @@ static void set_constraint_expand_flag(const bContext *UNUSED(C), Panel *panel,
/**
* Function with void * argument for #uiListPanelIDFromDataFunc.
*
- * \note: Constraint panel types are assumed to be named with the struct name field
+ * \note Constraint panel types are assumed to be named with the struct name field
* concatenated to the defined prefix.
*/
static void object_constraint_panel_id(void *md_link, char *r_name)
@@ -2639,7 +2915,7 @@ static void draw_constraint_header(uiLayout *layout, Object *ob, bConstraint *co
}
else {
/* enabled */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
uiItemR(layout, &ptr, "mute", 0, "", 0);
UI_block_emboss_set(block, UI_EMBOSS);
@@ -6170,6 +6446,10 @@ void uiTemplateList(uiLayout *layout,
org_i,
flt_flag);
+ /* Items should be able to set context pointers for the layout. But the list-row button
+ * swallows events, so it needs the context storage too for handlers to see it. */
+ but->context = uiLayoutGetContextStore(sub);
+
/* If we are "drawing" active item, set all labels as active. */
if (i == activei) {
ui_layout_list_set_labels_active(sub);
@@ -7184,6 +7464,7 @@ void uiTemplateCacheFile(uiLayout *layout,
ptr,
propname,
NULL,
+ NULL,
"CACHEFILE_OT_open",
NULL,
UI_TEMPLATE_ID_FILTER_ALL,
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 9c7b112855f..4d81b1edf0c 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -264,7 +264,7 @@ typedef struct uiWidgetType {
/* converted colors for state */
uiWidgetColors wcol;
- void (*state)(struct uiWidgetType *, int state, int drawflag, char emboss);
+ void (*state)(struct uiWidgetType *, int state, int drawflag, eUIEmbossType emboss);
void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign);
void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign);
void (*text)(const uiFontStyle *, const uiWidgetColors *, uiBut *, rcti *);
@@ -2520,8 +2520,14 @@ static void widget_active_color(uiWidgetColors *wcol)
static const uchar *widget_color_blend_from_flags(const uiWidgetStateColors *wcol_state,
int state,
- int drawflag)
+ int drawflag,
+ const eUIEmbossType emboss)
{
+ /* Explicitly require #UI_EMBOSS_NONE_OR_STATUS for color blending with no emboss. */
+ if (emboss == UI_EMBOSS_NONE) {
+ return NULL;
+ }
+
if (drawflag & UI_BUT_ANIMATED_CHANGED) {
return wcol_state->inner_changed_sel;
}
@@ -2541,7 +2547,7 @@ static const uchar *widget_color_blend_from_flags(const uiWidgetStateColors *wco
}
/* copy colors from theme, and set changes in it based on state */
-static void widget_state(uiWidgetType *wt, int state, int drawflag, char emboss)
+static void widget_state(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
{
uiWidgetStateColors *wcol_state = wt->wcol_state;
@@ -2557,7 +2563,7 @@ static void widget_state(uiWidgetType *wt, int state, int drawflag, char emboss)
wt->wcol = *(wt->wcol_theme);
- const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, drawflag);
+ const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, drawflag, emboss);
if (state & UI_SELECT) {
copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel);
@@ -2619,14 +2625,14 @@ static void widget_state(uiWidgetType *wt, int state, int drawflag, char emboss)
* \{ */
/* sliders use special hack which sets 'item' as inner when drawing filling */
-static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag, char emboss)
+static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
{
uiWidgetStateColors *wcol_state = wt->wcol_state;
/* call this for option button */
widget_state(wt, state, drawflag, emboss);
- const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, drawflag);
+ const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, drawflag, emboss);
if (color_blend != NULL) {
/* Set the slider 'item' so that it reflects state settings too.
* De-saturate so the color of the slider doesn't conflict with the blend color,
@@ -2642,7 +2648,10 @@ static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag, ch
}
/* labels use theme colors for text */
-static void widget_state_option_menu(uiWidgetType *wt, int state, int drawflag, char emboss)
+static void widget_state_option_menu(uiWidgetType *wt,
+ int state,
+ int drawflag,
+ eUIEmbossType emboss)
{
const bTheme *btheme = UI_GetTheme();
@@ -2662,7 +2671,7 @@ static void widget_state_option_menu(uiWidgetType *wt, int state, int drawflag,
static void widget_state_nothing(uiWidgetType *wt,
int UNUSED(state),
int UNUSED(drawflag),
- char UNUSED(emboss))
+ eUIEmbossType UNUSED(emboss))
{
wt->wcol = *(wt->wcol_theme);
}
@@ -2671,7 +2680,7 @@ static void widget_state_nothing(uiWidgetType *wt,
static void widget_state_pulldown(uiWidgetType *wt,
int UNUSED(state),
int UNUSED(drawflag),
- char UNUSED(emboss))
+ eUIEmbossType UNUSED(emboss))
{
wt->wcol = *(wt->wcol_theme);
}
@@ -2680,7 +2689,7 @@ static void widget_state_pulldown(uiWidgetType *wt,
static void widget_state_pie_menu_item(uiWidgetType *wt,
int state,
int UNUSED(drawflag),
- char UNUSED(emboss))
+ eUIEmbossType UNUSED(emboss))
{
wt->wcol = *(wt->wcol_theme);
@@ -2715,7 +2724,7 @@ static void widget_state_pie_menu_item(uiWidgetType *wt,
static void widget_state_menu_item(uiWidgetType *wt,
int state,
int UNUSED(drawflag),
- char UNUSED(emboss))
+ eUIEmbossType UNUSED(emboss))
{
wt->wcol = *(wt->wcol_theme);
@@ -2906,12 +2915,12 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const
const bool is_color_gamma = ui_but_is_color_gamma(but);
/* Initialize for compatibility. */
- copy_v3_v3(hsv, cpicker->color_data);
+ copy_v3_v3(hsv, cpicker->hsv_perceptual);
/* Compute current hue. */
ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
- ui_rgb_to_color_picker_compat_v(rgb, hsv);
+ ui_scene_linear_to_perceptual_space(but, rgb);
+ ui_color_picker_rgb_to_hsv_compat(rgb, hsv);
CLAMP(hsv[2], 0.0f, 1.0f); /* for display only */
@@ -2928,8 +2937,8 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const
}
const float hsv_center[3] = {0.0f, 0.0f, hsv[2]};
- ui_color_picker_to_rgb_v(hsv_center, rgb_center);
- ui_color_picker_to_scene_linear_space(but, rgb_center);
+ ui_color_picker_hsv_to_rgb(hsv_center, rgb_center);
+ ui_perceptual_to_scene_linear_space(but, rgb_center);
if (!is_color_gamma) {
ui_block_cm_to_display_space_v3(but->block, rgb_center);
@@ -2956,8 +2965,8 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const
rect, centx + co * radius, centy + si * radius, hsv_ang, hsv_ang + 1);
hsv_ang[2] = hsv[2];
- ui_color_picker_to_rgb_v(hsv_ang, rgb_ang);
- ui_color_picker_to_scene_linear_space(but, rgb_ang);
+ ui_color_picker_hsv_to_rgb(hsv_ang, rgb_ang);
+ ui_perceptual_to_scene_linear_space(but, rgb_ang);
if (!is_color_gamma) {
ui_block_cm_to_display_space_v3(but->block, rgb_ang);
@@ -2987,10 +2996,10 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const
GPU_line_smooth(false);
/* cursor */
- copy_v3_v3(hsv, cpicker->color_data);
+ copy_v3_v3(hsv, cpicker->hsv_perceptual);
ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
- ui_rgb_to_color_picker_compat_v(rgb, hsv);
+ ui_scene_linear_to_perceptual_space(but, rgb);
+ ui_color_picker_rgb_to_hsv_compat(rgb, hsv);
float xpos, ypos;
ui_hsvcircle_pos_from_vals(cpicker, rect, hsv, &xpos, &ypos);
@@ -3212,14 +3221,14 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
float rgb[3];
float x = 0.0f, y = 0.0f;
ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
+ float *hsv = cpicker->hsv_perceptual;
float hsv_n[3];
/* Initialize for compatibility. */
copy_v3_v3(hsv_n, hsv);
ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
+ ui_scene_linear_to_perceptual_space(but, rgb);
rgb_to_hsv_compat_v(rgb, hsv_n);
ui_draw_gradient(rect, hsv_n, hsv_but->gradient_type, 1.0f);
@@ -3251,7 +3260,7 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
float rgb[3], hsv[3], v;
ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
+ ui_scene_linear_to_perceptual_space(but, rgb);
if (hsv_but->gradient_type == UI_GRAD_L_ALT) {
rgb_to_hsl_v(rgb, hsv);
@@ -4064,7 +4073,7 @@ static void widget_optionbut(uiWidgetColors *wcol,
}
/* labels use Editor theme colors for text */
-static void widget_state_label(uiWidgetType *wt, int state, int drawflag, char emboss)
+static void widget_state_label(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
{
if (state & UI_BUT_LIST_ITEM) {
/* Override default label theme's colors. */
@@ -4524,8 +4533,9 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu
break;
}
}
- else if (but->emboss == UI_EMBOSS_NONE) {
- /* "nothing" */
+ else if (ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS)) {
+ /* Use the same widget types for both no emboss types. Later on,
+ * #UI_EMBOSS_NONE_OR_STATUS will blend state colors if they apply. */
switch (but->type) {
case UI_BTYPE_LABEL:
wt = widget_type(UI_WTYPE_ICON_LABEL);
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index a5999962e09..7de0ec0255f 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -109,14 +109,13 @@ typedef struct v2dViewPanData {
static bool view_pan_poll(bContext *C)
{
ARegion *region = CTX_wm_region(C);
- View2D *v2d;
/* check if there's a region in context to work with */
if (region == NULL) {
return false;
}
- v2d = &region->v2d;
+ View2D *v2d = &region->v2d;
/* check that 2d-view can pan */
if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y)) {
@@ -191,10 +190,7 @@ static void view_pan_apply(bContext *C, wmOperator *op)
/* cleanup temp customdata */
static void view_pan_exit(wmOperator *op)
{
- if (op->customdata) {
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ MEM_SAFE_FREE(op->customdata);
}
/** \} */
@@ -216,14 +212,12 @@ static int view_pan_exec(bContext *C, wmOperator *op)
static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *window = CTX_wm_window(C);
- v2dViewPanData *vpd;
- View2D *v2d;
/* set up customdata */
view_pan_init(C, op);
- vpd = op->customdata;
- v2d = vpd->v2d;
+ v2dViewPanData *vpd = op->customdata;
+ View2D *v2d = vpd->v2d;
/* set initial settings */
vpd->startx = vpd->lastx = event->x;
@@ -787,7 +781,6 @@ static void view_zoom_axis_lock_defaults(bContext *C, bool r_do_zoom_xy[2])
static bool view_zoom_poll(bContext *C)
{
ARegion *region = CTX_wm_region(C);
- View2D *v2d;
/* check if there's a region in context to work with */
if (region == NULL) {
@@ -799,7 +792,7 @@ static bool view_zoom_poll(bContext *C)
return false;
}
- v2d = &region->v2d;
+ View2D *v2d = &region->v2d;
/* check that 2d-view is zoomable */
if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y)) {
@@ -836,12 +829,12 @@ static void view_zoomstep_apply_ex(bContext *C,
ARegion *region = CTX_wm_region(C);
View2D *v2d = &region->v2d;
const rctf cur_old = v2d->cur;
- float dx, dy;
const int snap_test = ED_region_snap_size_test(region);
/* calculate amount to move view by, ensuring symmetry so the
* old zoom level is restored after zooming back the same amount
*/
+ float dx, dy;
if (facx >= 0.0f) {
dx = BLI_rctf_size_x(&v2d->cur) * facx;
dy = BLI_rctf_size_y(&v2d->cur) * facy;
@@ -955,10 +948,7 @@ static void view_zoomstep_exit(wmOperator *op)
{
UI_view2d_zoom_cache_reset();
- if (op->customdata) {
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ MEM_SAFE_FREE(op->customdata);
}
/* this operator only needs this single callback, where it calls the view_zoom_*() methods */
@@ -1107,15 +1097,14 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
{
v2dViewZoomData *vzd = op->customdata;
View2D *v2d = vzd->v2d;
- float dx, dy;
const int snap_test = ED_region_snap_size_test(vzd->region);
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
const bool zoom_to_pos = use_cursor_init && vzd->zoom_to_mouse_pos;
/* get amount to move view by */
- dx = RNA_float_get(op->ptr, "deltax") / U.dpi_fac;
- dy = RNA_float_get(op->ptr, "deltay") / U.dpi_fac;
+ float dx = RNA_float_get(op->ptr, "deltax") / U.dpi_fac;
+ float dy = RNA_float_get(op->ptr, "deltay") / U.dpi_fac;
if (U.uiflag & USER_ZOOM_INVERT) {
dx *= -1;
@@ -1223,14 +1212,12 @@ static int view_zoomdrag_exec(bContext *C, wmOperator *op)
static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *window = CTX_wm_window(C);
- v2dViewZoomData *vzd;
- View2D *v2d;
/* set up customdata */
view_zoomdrag_init(C, op);
- vzd = op->customdata;
- v2d = vzd->v2d;
+ v2dViewZoomData *vzd = op->customdata;
+ View2D *v2d = vzd->v2d;
if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
ARegion *region = CTX_wm_region(C);
@@ -1242,20 +1229,18 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even
}
if (ELEM(event->type, MOUSEZOOM, MOUSEPAN)) {
- float dx, dy, fac;
-
vzd->lastx = event->prevx;
vzd->lasty = event->prevy;
/* As we have only 1D information (magnify value), feed both axes
* with magnify information that is stored in x axis
*/
- fac = 0.01f * (event->prevx - event->x);
- dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f;
+ float fac = 0.01f * (event->prevx - event->x);
+ float dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f;
if (event->type == MOUSEPAN) {
fac = 0.01f * (event->prevy - event->y);
}
- dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f;
+ float dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f;
/* support trackpad zoom to always zoom entirely - the v2d code uses portrait or
* landscape exceptions */
@@ -1491,11 +1476,11 @@ static int view_borderzoom_exec(bContext *C, wmOperator *op)
{
ARegion *region = CTX_wm_region(C);
View2D *v2d = &region->v2d;
- rctf rect;
rctf cur_new = v2d->cur;
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* convert coordinates of rect to 'tot' rect coordinates */
+ rctf rect;
WM_operator_properties_border_to_rctf(op, &rect);
UI_view2d_region_to_view_rctf(v2d, &rect, &rect);
@@ -1766,13 +1751,13 @@ static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w
ARegion *region = CTX_wm_region(C);
View2D *v2d = &region->v2d;
struct SmoothView2DStore *sms = v2d->sms;
- float step;
/* escape if not our timer */
if (v2d->smooth_timer == NULL || v2d->smooth_timer != event->customdata) {
return OPERATOR_PASS_THROUGH;
}
+ float step;
if (sms->time_allowed != 0.0) {
step = (float)((v2d->smooth_timer->duration) / sms->time_allowed);
}
@@ -1978,15 +1963,11 @@ static void scroller_activate_init(bContext *C,
const wmEvent *event,
const char in_scroller)
{
- v2dScrollerMove *vsm;
- View2DScrollers scrollers;
ARegion *region = CTX_wm_region(C);
View2D *v2d = &region->v2d;
- rctf tot_cur_union;
- float mask_size;
/* set custom-data for operator */
- vsm = MEM_callocN(sizeof(v2dScrollerMove), "v2dScrollerMove");
+ v2dScrollerMove *vsm = MEM_callocN(sizeof(v2dScrollerMove), "v2dScrollerMove");
op->customdata = vsm;
/* set general data */
@@ -2000,16 +1981,17 @@ static void scroller_activate_init(bContext *C,
/* 'zone' depends on where mouse is relative to bubble
* - zooming must be allowed on this axis, otherwise, default to pan
*/
+ View2DScrollers scrollers;
UI_view2d_scrollers_calc(v2d, NULL, &scrollers);
/* Use a union of 'cur' & 'tot' in case the current view is far outside 'tot'. In this cases
* moving the scroll bars has far too little effect and the view can get stuck T31476. */
- tot_cur_union = v2d->tot;
+ rctf tot_cur_union = v2d->tot;
BLI_rctf_union(&tot_cur_union, &v2d->cur);
if (in_scroller == 'h') {
/* horizontal scroller - calculate adjustment factor first */
- mask_size = (float)BLI_rcti_size_x(&v2d->hor);
+ float mask_size = (float)BLI_rcti_size_x(&v2d->hor);
vsm->fac = BLI_rctf_size_x(&tot_cur_union) / mask_size;
/* pixel rounding */
@@ -2029,7 +2011,7 @@ static void scroller_activate_init(bContext *C,
}
else {
/* vertical scroller - calculate adjustment factor first */
- mask_size = (float)BLI_rcti_size_y(&v2d->vert);
+ float mask_size = (float)BLI_rcti_size_y(&v2d->vert);
vsm->fac = BLI_rctf_size_y(&tot_cur_union) / mask_size;
/* pixel rounding */
@@ -2076,10 +2058,9 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
{
v2dScrollerMove *vsm = op->customdata;
View2D *v2d = vsm->v2d;
- float temp;
/* calculate amount to move view by */
- temp = vsm->fac * vsm->delta;
+ float temp = vsm->fac * vsm->delta;
/* round to pixel */
temp = roundf(temp / vsm->fac_round) * vsm->fac_round;
@@ -2219,11 +2200,9 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent *
/* if in a scroller, init customdata then set modal handler which will
* catch mouse-down to start doing useful stuff */
if (in_scroller) {
- v2dScrollerMove *vsm;
-
/* initialize customdata */
scroller_activate_init(C, op, event, in_scroller);
- vsm = (v2dScrollerMove *)op->customdata;
+ v2dScrollerMove *vsm = (v2dScrollerMove *)op->customdata;
/* support for quick jump to location - gtk and qt do this on linux */
if (event->type == MIDDLEMOUSE) {
@@ -2324,12 +2303,11 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op))
const uiStyle *style = UI_style_get();
ARegion *region = CTX_wm_region(C);
View2D *v2d = &region->v2d;
- int winx, winy;
const int snap_test = ED_region_snap_size_test(region);
/* zoom 1.0 */
- winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
- winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
+ const int winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
+ const int winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
v2d->cur.xmax = v2d->cur.xmin + winx;
v2d->cur.ymax = v2d->cur.ymin + winy;
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index b8badd207fe..e788b28d3b4 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -1129,7 +1129,7 @@ void MESH_OT_bevel(wmOperatorType *ot)
prop_affect_items,
BEVEL_AFFECT_EDGES,
"Affect",
- "Affect Edges or Vertices");
+ "Affect edges or vertices");
RNA_def_boolean(ot->srna,
"clamp_overlap",
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index ef78d31a6bb..aa144dd3f3c 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -177,6 +177,6 @@ void MESH_OT_knife_project(wmOperatorType *ot)
RNA_def_boolean(ot->srna,
"cut_through",
false,
- "Cut through",
+ "Cut Through",
"Cut through all faces, not just visible ones");
}
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index a2fe949b6c5..d3eaa9048d3 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -4552,7 +4552,8 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot)
/* edges */
RNA_def_boolean(ot->srna, "use_wire", true, "Wire", "Wire edges");
RNA_def_boolean(ot->srna, "use_boundary", true, "Boundaries", "Boundary edges");
- RNA_def_boolean(ot->srna, "use_multi_face", true, "Multiple Faces", "Edges shared by 3+ faces");
+ RNA_def_boolean(
+ ot->srna, "use_multi_face", true, "Multiple Faces", "Edges shared by more than two faces");
RNA_def_boolean(ot->srna,
"use_non_contiguous",
true,
diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c
index 00349983c57..d762eede079 100644
--- a/source/blender/editors/mesh/editmesh_select_similar.c
+++ b/source/blender/editors/mesh/editmesh_select_similar.c
@@ -34,6 +34,7 @@
#include "BKE_material.h"
#include "BKE_report.h"
+#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "WM_api.h"
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index aab17d6da61..59ce9140ab8 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -180,7 +180,7 @@ void MESH_OT_subdivide(wmOperatorType *ot)
"ngon",
true,
"Create N-Gons",
- "When disabled, newly created faces are limited to 3-4 sided faces");
+ "When disabled, newly created faces are limited to 3 and 4 sided faces");
RNA_def_enum(
ot->srna,
"quadcorner",
@@ -395,7 +395,7 @@ void MESH_OT_unsubdivide(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Un-Subdivide";
- ot->description = "UnSubdivide selected edges & faces";
+ ot->description = "Un-subdivide selected edges and faces";
ot->idname = "MESH_OT_unsubdivide";
/* api callbacks */
@@ -698,7 +698,7 @@ void MESH_OT_edge_collapse(wmOperatorType *ot)
/* identifiers */
ot->name = "Collapse Edges & Faces";
ot->description =
- "Collapse isolated edges & faces regions, merging data such as UV's and vertex colors. "
+ "Collapse isolated edge and face regions, merging data such as UV's and vertex colors. "
"This can collapse edge-rings as well as regions of connected faces into vertices";
ot->idname = "MESH_OT_edge_collapse";
@@ -1904,7 +1904,7 @@ void MESH_OT_edge_split(wmOperatorType *ot)
"VERT",
0,
"Faces & Edges by Vertices",
- "Split faces & edges connected to selected vertices"},
+ "Split faces and edges connected to selected vertices"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 99f7992c2a9..b16b2809e51 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -27,6 +27,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BLI_array_utils.h"
#include "BLI_listbase.h"
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 138e394a4d8..ce77f90c5fe 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -1140,8 +1140,10 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em,
if (use_topology) {
v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i);
- if (respecthide && BM_elem_flag_test(v_mirr, BM_ELEM_HIDDEN)) {
- v_mirr = NULL;
+ if (v_mirr != NULL) {
+ if (respecthide && BM_elem_flag_test(v_mirr, BM_ELEM_HIDDEN)) {
+ v_mirr = NULL;
+ }
}
}
else {
diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c
index 552e459acb1..b4030ad269b 100644
--- a/source/blender/editors/metaball/editmball_undo.c
+++ b/source/blender/editors/metaball/editmball_undo.c
@@ -30,8 +30,10 @@
#include "BLI_utildefines.h"
#include "DNA_defs.h"
+#include "DNA_layer_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BKE_context.h"
#include "BKE_layer.h"
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index a1be9b9df61..77b5379ddd4 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -31,8 +31,8 @@ set(INC
../../makesrna
../../modifiers
../../python
- ../../shader_fx
../../render
+ ../../shader_fx
../../windowmanager
../../../../intern/clog
../../../../intern/glew-mx
@@ -88,6 +88,7 @@ endif()
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_GEOMETRY_NODES)
+ add_definitions(-DWITH_POINT_CLOUD)
add_definitions(-DWITH_HAIR_NODES)
endif()
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 4e0f6211c18..a64033bc63a 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1618,6 +1618,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
Object *ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits);
+ const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ob);
/* to make it easier to start using this immediately in NLA, a default sound clip is created
* ready to be moved around to retime the sound and/or make new sound clips
@@ -1625,13 +1626,13 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op)
{
/* create new data for NLA hierarchy */
AnimData *adt = BKE_animdata_add_id(&ob->id);
- NlaTrack *nlt = BKE_nlatrack_add(adt, NULL);
+ NlaTrack *nlt = BKE_nlatrack_add(adt, NULL, is_liboverride);
NlaStrip *strip = BKE_nla_add_soundstrip(bmain, scene, ob->data);
strip->start = CFRA;
strip->end += strip->start;
/* hook them up */
- BKE_nlatrack_add_strip(nlt, strip);
+ BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
/* auto-name the strip, and give the track an interesting name */
BLI_strncpy(nlt->name, DATA_("SoundTrack"), sizeof(nlt->name));
@@ -1713,6 +1714,9 @@ void OBJECT_OT_hair_add(wmOperatorType *ot)
static bool object_pointcloud_add_poll(bContext *C)
{
+ if (!U.experimental.use_new_point_cloud_type) {
+ return false;
+ }
return ED_operator_objectmode(C);
}
@@ -2315,17 +2319,23 @@ static const EnumPropertyItem convert_target_items[] = {
"MESH",
ICON_OUTLINER_OB_MESH,
"Mesh",
+#ifdef WITH_POINT_CLOUD
"Mesh from Curve, Surface, Metaball, Text, or Pointcloud objects"},
+#else
+ "Mesh from Curve, Surface, Metaball, or Text objects"},
+#endif
{OB_GPENCIL,
"GPENCIL",
ICON_OUTLINER_OB_GREASEPENCIL,
"Grease Pencil",
"Grease Pencil from Curve or Mesh objects"},
+#ifdef WITH_POINT_CLOUD
{OB_POINTCLOUD,
"POINTCLOUD",
ICON_OUTLINER_OB_POINTCLOUD,
"Pointcloud",
"Pointcloud from Mesh objects"},
+#endif
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index 008498a1735..9618774eea8 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -25,6 +25,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index e684ad03f53..dd015f59e8d 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -706,8 +706,9 @@ static bool edit_constraint_poll_generic(bContext *C,
return false;
}
- if (!is_liboverride_allowed && !BKE_constraint_is_local_in_liboverride(ob, con)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit constraints coming from library override");
+ if (!is_liboverride_allowed && BKE_constraint_is_nonlocal_in_liboverride(ob, con)) {
+ CTX_wm_operator_poll_msg_set(
+ C, "Cannot edit constraints coming from linked data in a library override");
return false;
}
diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c
index d3f165678c3..e5feb74df26 100644
--- a/source/blender/editors/object/object_gpencil_modifier.c
+++ b/source/blender/editors/object/object_gpencil_modifier.c
@@ -443,9 +443,9 @@ static bool gpencil_edit_modifier_poll_generic(bContext *C,
return false;
}
- if (!is_liboverride_allowed &&
- (mod == NULL || !BKE_gpencil_modifier_is_local_in_liboverride(ob, mod))) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override");
+ if (!is_liboverride_allowed && BKE_gpencil_modifier_is_nonlocal_in_liboverride(ob, mod)) {
+ CTX_wm_operator_poll_msg_set(
+ C, "Cannot edit modifiers coming from linked data in a library override");
return false;
}
@@ -461,7 +461,7 @@ static bool gpencil_edit_modifier_poll(bContext *C)
* (not only from added 'local' ones). */
static bool gpencil_edit_modifier_liboverride_allowed_poll(bContext *C)
{
- return gpencil_edit_modifier_poll_generic(C, &RNA_Modifier, 0, true);
+ return gpencil_edit_modifier_poll_generic(C, &RNA_GpencilModifier, 0, true);
}
static void gpencil_edit_modifier_properties(wmOperatorType *ot)
@@ -789,7 +789,7 @@ void OBJECT_OT_gpencil_modifier_apply(wmOperatorType *ot)
"apply_as",
gpencil_modifier_apply_as_items,
MODIFIER_APPLY_DATA,
- "Apply as",
+ "Apply As",
"How to apply the modifier to the geometry");
gpencil_edit_modifier_properties(ot);
gpencil_edit_modifier_report_property(ot);
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index e6ef53a3d65..89ade5cc49d 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -206,6 +206,7 @@ void OBJECT_OT_gpencil_modifier_copy(struct wmOperatorType *ot);
/* object_shader_fx.c */
void OBJECT_OT_shaderfx_add(struct wmOperatorType *ot);
+void OBJECT_OT_shaderfx_copy(struct wmOperatorType *ot);
void OBJECT_OT_shaderfx_remove(struct wmOperatorType *ot);
void OBJECT_OT_shaderfx_move_up(struct wmOperatorType *ot);
void OBJECT_OT_shaderfx_move_down(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index bb4581b0ee8..3111003703f 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -1052,8 +1052,9 @@ bool edit_modifier_poll_generic(bContext *C,
return false;
}
- if (!is_liboverride_allowed && !BKE_modifier_is_local_in_liboverride(ob, mod)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override");
+ if (!is_liboverride_allowed && BKE_modifier_is_nonlocal_in_liboverride(ob, mod)) {
+ CTX_wm_operator_poll_msg_set(
+ C, "Cannot edit modifiers coming from linked data in a library override");
return false;
}
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 8ba0ce5fd08..2e5a75ffa7d 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -166,6 +166,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_shaderfx_move_up);
WM_operatortype_append(OBJECT_OT_shaderfx_move_down);
WM_operatortype_append(OBJECT_OT_shaderfx_move_to_index);
+ WM_operatortype_append(OBJECT_OT_shaderfx_copy);
WM_operatortype_append(OBJECT_OT_correctivesmooth_bind);
WM_operatortype_append(OBJECT_OT_meshdeform_bind);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 8841b1955bf..ee9ef192d18 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -484,7 +484,7 @@ void OBJECT_OT_proxy_make(wmOperatorType *ot)
DummyRNA_DEFAULT_items,
0,
"Proxy Object",
- "Name of lib-linked/collection object to make a proxy for");
+ "Name of library-linked/collection object to make a proxy for");
RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
@@ -1554,6 +1554,7 @@ enum {
MAKE_LINKS_DUPLICOLLECTION = 5,
MAKE_LINKS_MODIFIERS = 6,
MAKE_LINKS_FONTS = 7,
+ MAKE_LINKS_SHADERFX = 8,
};
/* Return true if make link data is allowed, false otherwise */
@@ -1589,6 +1590,11 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst
return true;
}
break;
+ case MAKE_LINKS_SHADERFX:
+ if ((ob_src->type == OB_GPENCIL) && (ob_dst->type == OB_GPENCIL)) {
+ return true;
+ }
+ break;
}
return false;
}
@@ -1720,6 +1726,11 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
break;
}
+ case MAKE_LINKS_SHADERFX:
+ ED_object_shaderfx_link(ob_dst, ob_src);
+ DEG_id_tag_update(&ob_dst->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ break;
}
}
}
@@ -1782,6 +1793,7 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
{MAKE_LINKS_DUPLICOLLECTION, "DUPLICOLLECTION", 0, "Instance Collection", ""},
{MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""},
{MAKE_LINKS_FONTS, "FONTS", 0, "Fonts", ""},
+ {MAKE_LINKS_SHADERFX, "EFFECTS", 0, "Effects", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -2515,7 +2527,7 @@ static bool convert_proxy_to_override_poll(bContext *C)
return obact != NULL && obact->proxy != NULL;
}
-static int convert_proxy_to_override_exec(bContext *C, wmOperator *UNUSED(op))
+static int convert_proxy_to_override_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -2529,6 +2541,15 @@ static int convert_proxy_to_override_exec(bContext *C, wmOperator *UNUSED(op))
const bool success = BKE_lib_override_library_proxy_convert(bmain, scene, view_layer, ob_proxy);
+ if (!success) {
+ BKE_reportf(
+ op->reports,
+ RPT_ERROR_INVALID_INPUT,
+ "Could not create a library override from proxy '%s' (might use already local data?)",
+ ob_proxy->id.name + 2);
+ return OPERATOR_CANCELLED;
+ }
+
/* Remove the instance empty from this scene, the items now have an overridden collection
* instead. */
if (success && is_override_instancing_object) {
@@ -2544,7 +2565,7 @@ static int convert_proxy_to_override_exec(bContext *C, wmOperator *UNUSED(op))
void OBJECT_OT_convert_proxy_to_override(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Convert Proxy To Override";
+ ot->name = "Convert Proxy to Override";
ot->description = "Convert a proxy to a local library override";
ot->idname = "OBJECT_OT_convert_proxy_to_override";
diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c
index c5caee5ba08..2b1ac08ec2e 100644
--- a/source/blender/editors/object/object_shader_fx.c
+++ b/source/blender/editors/object/object_shader_fx.c
@@ -640,3 +640,57 @@ void OBJECT_OT_shaderfx_move_to_index(wmOperatorType *ot)
RNA_def_int(
ot->srna, "index", 0, 0, INT_MAX, "Index", "The index to move the effect to", 0, INT_MAX);
}
+
+/************************ copy shader operator *********************/
+
+static int shaderfx_copy_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+ ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
+
+ ShaderFxData *nfx = BKE_shaderfx_new(fx->type);
+ if (!nfx) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BLI_strncpy(nfx->name, fx->name, sizeof(nfx->name));
+ /* Make sure effect data has unique name. */
+ BKE_shaderfx_unique_name(&ob->shader_fx, nfx);
+
+ BKE_shaderfx_copydata(fx, nfx);
+ BLI_insertlinkafter(&ob->shader_fx, fx, nfx);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_OBJECT | ND_SHADERFX, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int shaderfx_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int retval;
+ if (edit_shaderfx_invoke_properties(C, op, event, &retval)) {
+ return shaderfx_copy_exec(C, op);
+ }
+ return retval;
+}
+
+static bool shaderfx_copy_poll(bContext *C)
+{
+ return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0);
+}
+
+void OBJECT_OT_shaderfx_copy(wmOperatorType *ot)
+{
+ ot->name = "Copy Effect";
+ ot->description = "Duplicate effect at the same position in the stack";
+ ot->idname = "OBJECT_OT_shaderfx_copy";
+
+ ot->invoke = shaderfx_copy_invoke;
+ ot->exec = shaderfx_copy_exec;
+ ot->poll = shaderfx_copy_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_shaderfx_properties(ot);
+}
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 3d6a6abfe0d..fc4969019b5 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -736,14 +736,19 @@ const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(const bContext *
RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ACTIVE);
}
- if (BKE_object_pose_armature_get(ob)) {
- if (selection_mask & (1 << WT_VGROUP_BONE_SELECT)) {
- RNA_enum_items_add_value(
- &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_SELECT);
+ if (ob) {
+ if (BKE_object_pose_armature_get(ob)) {
+ if (selection_mask & (1 << WT_VGROUP_BONE_SELECT)) {
+ RNA_enum_items_add_value(
+ &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_SELECT);
+ }
}
- if (selection_mask & (1 << WT_VGROUP_BONE_DEFORM)) {
- RNA_enum_items_add_value(
- &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_DEFORM);
+
+ if (BKE_modifiers_is_deformed_by_armature(ob)) {
+ if (selection_mask & (1 << WT_VGROUP_BONE_DEFORM)) {
+ RNA_enum_items_add_value(
+ &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_DEFORM);
+ }
}
}
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 017cd63d9d5..f5c3fc17552 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -1203,6 +1203,9 @@ static bool copy_particle_systems_to_object(const bContext *C,
#undef PSYS_FROM_FIRST
#undef PSYS_FROM_NEXT
+ if (duplicate_settings) {
+ DEG_relations_tag_update(bmain);
+ }
DEG_id_tag_update(&ob_to->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to);
return true;
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index 4939bf0086b..cb7ca5bd5d1 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <string.h>
+#include "DNA_collection_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index cb25363d2b2..4fd304ea71d 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <string.h>
+#include "DNA_collection_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index e1d03e6f3be..e60455667e9 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -38,8 +38,11 @@ void OBJECT_OT_material_slot_move(struct wmOperatorType *ot);
void OBJECT_OT_material_slot_remove_unused(struct wmOperatorType *ot);
void MATERIAL_OT_new(struct wmOperatorType *ot);
+void MATERIAL_OT_duplicate(struct wmOperatorType *ot);
void TEXTURE_OT_new(struct wmOperatorType *ot);
+void TEXTURE_OT_duplicate(struct wmOperatorType *ot);
void WORLD_OT_new(struct wmOperatorType *ot);
+void WORLD_OT_duplicate(struct wmOperatorType *ot);
void MATERIAL_OT_copy(struct wmOperatorType *ot);
void MATERIAL_OT_paste(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 3dbf70aa4bc..10cf4131584 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -29,6 +29,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_rect.h"
#include "BLI_threads.h"
#include "BLI_timecode.h"
#include "BLI_utildefines.h"
@@ -82,7 +83,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "SEQ_sequencer.h"
+#include "SEQ_relations.h"
#include "BLO_undofile.h"
@@ -121,72 +122,90 @@ typedef struct RenderJob {
} RenderJob;
/* called inside thread! */
-static void image_buffer_rect_update(RenderJob *rj,
- RenderResult *rr,
- ImBuf *ibuf,
- ImageUser *iuser,
- volatile rcti *renrect,
- const char *viewname)
+static bool image_buffer_calc_tile_rect(const RenderResult *rr,
+ const ImBuf *ibuf,
+ volatile rcti *renrect,
+ rcti *r_ibuf_rect,
+ int *r_offset_x,
+ int *r_offset_y)
{
- Scene *scene = rj->scene;
- const float *rectf = NULL;
- int ymin, ymax, xmin, xmax;
- int rymin, rxmin;
- int linear_stride, linear_offset_x, linear_offset_y;
- ColorManagedViewSettings *view_settings;
- ColorManagedDisplaySettings *display_settings;
-
- if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) {
- /* The whole image buffer it so be color managed again anyway. */
- return;
- }
+ int tile_y, tile_height, tile_x, tile_width;
/* if renrect argument, we only refresh scanlines */
if (renrect) {
- /* if (ymax == recty), rendering of layer is ready,
+ /* if (tile_height == recty), rendering of layer is ready,
* we should not draw, other things happen... */
if (rr->renlay == NULL || renrect->ymax >= rr->recty) {
- return;
+ return false;
}
- /* xmin here is first subrect x coord, xmax defines subrect width */
- xmin = renrect->xmin + rr->crop;
- xmax = renrect->xmax - xmin + rr->crop;
- if (xmax < 2) {
- return;
+ /* tile_x here is first subrect x coord, tile_width defines subrect width */
+ tile_x = renrect->xmin;
+ tile_width = renrect->xmax - tile_x;
+ if (tile_width < 2) {
+ return false;
}
- ymin = renrect->ymin + rr->crop;
- ymax = renrect->ymax - ymin + rr->crop;
- if (ymax < 2) {
- return;
+ tile_y = renrect->ymin;
+ tile_height = renrect->ymax - tile_y;
+ if (tile_height < 2) {
+ return false;
}
renrect->ymin = renrect->ymax;
}
else {
- xmin = ymin = rr->crop;
- xmax = rr->rectx - 2 * rr->crop;
- ymax = rr->recty - 2 * rr->crop;
+ tile_x = tile_y = 0;
+ tile_width = rr->rectx;
+ tile_height = rr->recty;
}
- /* xmin ymin is in tile coords. transform to ibuf */
- rxmin = rr->tilerect.xmin + xmin;
- if (rxmin >= ibuf->x) {
- return;
+ /* tile_x tile_y is in tile coords. transform to ibuf */
+ int offset_x = rr->tilerect.xmin;
+ if (offset_x >= ibuf->x) {
+ return false;
}
- rymin = rr->tilerect.ymin + ymin;
- if (rymin >= ibuf->y) {
- return;
+ int offset_y = rr->tilerect.ymin;
+ if (offset_y >= ibuf->y) {
+ return false;
}
- if (rxmin + xmax > ibuf->x) {
- xmax = ibuf->x - rxmin;
+ if (offset_x + tile_width > ibuf->x) {
+ tile_width = ibuf->x - offset_x;
}
- if (rymin + ymax > ibuf->y) {
- ymax = ibuf->y - rymin;
+ if (offset_y + tile_height > ibuf->y) {
+ tile_height = ibuf->y - offset_y;
}
- if (xmax < 1 || ymax < 1) {
+ if (tile_width < 1 || tile_height < 1) {
+ return false;
+ }
+
+ r_ibuf_rect->xmax = tile_x + tile_width;
+ r_ibuf_rect->ymax = tile_y + tile_height;
+ r_ibuf_rect->xmin = tile_x;
+ r_ibuf_rect->ymin = tile_y;
+ *r_offset_x = offset_x;
+ *r_offset_y = offset_y;
+ return true;
+}
+
+static void image_buffer_rect_update(RenderJob *rj,
+ RenderResult *rr,
+ ImBuf *ibuf,
+ ImageUser *iuser,
+ const rcti *tile_rect,
+ int offset_x,
+ int offset_y,
+ const char *viewname)
+{
+ Scene *scene = rj->scene;
+ const float *rectf = NULL;
+ int linear_stride, linear_offset_x, linear_offset_y;
+ ColorManagedViewSettings *view_settings;
+ ColorManagedDisplaySettings *display_settings;
+
+ if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) {
+ /* The whole image buffer is to be color managed again anyway. */
return;
}
@@ -230,10 +249,10 @@ static void image_buffer_rect_update(RenderJob *rj,
return;
}
- rectf += 4 * (rr->rectx * ymin + xmin);
+ rectf += 4 * (rr->rectx * tile_rect->ymin + tile_rect->xmin);
linear_stride = rr->rectx;
- linear_offset_x = rxmin;
- linear_offset_y = rymin;
+ linear_offset_x = offset_x;
+ linear_offset_y = offset_y;
}
else {
rectf = ibuf->rect_float;
@@ -253,10 +272,10 @@ static void image_buffer_rect_update(RenderJob *rj,
linear_offset_y,
view_settings,
display_settings,
- rxmin,
- rymin,
- rxmin + xmax,
- rymin + ymax);
+ offset_x,
+ offset_y,
+ offset_x + BLI_rcti_size_x(tile_rect),
+ offset_y + BLI_rcti_size_y(tile_rect));
}
/* ****************************** render invoking ***************** */
@@ -344,7 +363,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
* otherwise, invalidated cache entries can make their way into
* the output rendering. We can't put that into RE_RenderFrame,
* since sequence rendering can call that recursively... (peter) */
- BKE_sequencer_cache_cleanup(scene);
+ SEQ_cache_cleanup(scene);
RE_SetReports(re, op->reports);
@@ -578,8 +597,16 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
/* update part of render */
render_image_update_pass_and_layer(rj, rr, &rj->iuser);
+ rcti tile_rect;
+ int offset_x;
+ int offset_y;
ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
if (ibuf) {
+ if (!image_buffer_calc_tile_rect(rr, ibuf, renrect, &tile_rect, &offset_x, &offset_y)) {
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ return;
+ }
+
/* Don't waste time on CPU side color management if
* image will be displayed using GLSL.
*
@@ -589,9 +616,10 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
*/
if (!rj->supports_glsl_draw || ibuf->channels == 1 ||
ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL) {
- image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname);
+ image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, &tile_rect, offset_x, offset_y, viewname);
}
- ima->gpuflag |= IMA_GPU_REFRESH;
+ BKE_image_update_gputexture_delayed(
+ ima, ibuf, offset_x, offset_y, BLI_rcti_size_x(&tile_rect), BLI_rcti_size_y(&tile_rect));
/* make jobs timer to send notifier */
*(rj->do_update) = true;
@@ -907,7 +935,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
/* Reports are done inside check function, and it will return false if there are other strips to
* render. */
- if ((scene->r.scemode & R_DOSEQ) && BKE_sequencer_check_scene_recursion(scene, op->reports)) {
+ if ((scene->r.scemode & R_DOSEQ) && SEQ_relations_check_scene_recursion(scene, op->reports)) {
return OPERATOR_CANCELLED;
}
@@ -929,7 +957,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
* otherwise, invalidated cache entries can make their way into
* the output rendering. We can't put that into RE_RenderFrame,
* since sequence rendering can call that recursively... (peter) */
- BKE_sequencer_cache_cleanup(scene);
+ SEQ_cache_cleanup(scene);
/* store spare
* get view3d layer, local layer, make this nice api call to render
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index f7275b06804..1069f942a7a 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -77,7 +77,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "SEQ_sequencer.h"
+#include "SEQ_render.h"
#include "GPU_framebuffer.h"
#include "GPU_matrix.h"
diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c
index e0aa02b354d..48e894036d9 100644
--- a/source/blender/editors/render/render_ops.c
+++ b/source/blender/editors/render/render_ops.c
@@ -45,8 +45,11 @@ void ED_operatortypes_render(void)
WM_operatortype_append(OBJECT_OT_material_slot_remove_unused);
WM_operatortype_append(MATERIAL_OT_new);
+ WM_operatortype_append(MATERIAL_OT_duplicate);
WM_operatortype_append(TEXTURE_OT_new);
+ WM_operatortype_append(TEXTURE_OT_duplicate);
WM_operatortype_append(WORLD_OT_new);
+ WM_operatortype_append(WORLD_OT_duplicate);
WM_operatortype_append(MATERIAL_OT_copy);
WM_operatortype_append(MATERIAL_OT_paste);
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 095deccada0..579fd86077e 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -68,6 +68,7 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
+#include "BKE_object.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
#include "BKE_world.h"
@@ -94,12 +95,16 @@
#include "ED_datafiles.h"
#include "ED_render.h"
#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_view3d_offscreen.h"
#ifndef NDEBUG
/* Used for database init assert(). */
# include "BLI_threads.h"
#endif
+static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect);
+
ImBuf *get_brush_icon(Brush *brush)
{
static const int flags = IB_rect | IB_multilayer | IB_metadata;
@@ -184,7 +189,7 @@ typedef struct IconPreview {
Main *bmain;
Scene *scene;
void *owner;
- ID *id, *id_copy;
+ ID *id, *id_copy; /* May be NULL! (see ICON_TYPE_PREVIEW case in #ui_icon_ensure_deferred()) */
ListBase sizes;
} IconPreview;
@@ -336,7 +341,7 @@ static World *preview_get_localized_world(ShaderPreview *sp, World *world)
return sp->worldcopy;
}
-static ID *duplicate_ids(ID *id)
+static ID *duplicate_ids(ID *id, const bool allow_failure)
{
if (id == NULL) {
/* Non-ID preview render. */
@@ -344,20 +349,25 @@ static ID *duplicate_ids(ID *id)
}
switch (GS(id->name)) {
+ case ID_OB:
case ID_MA:
case ID_TE:
case ID_LA:
case ID_WO: {
+ BLI_assert(BKE_previewimg_id_supports_jobs(id));
ID *id_copy = BKE_id_copy_ex(
NULL, id, NULL, LIB_ID_CREATE_LOCAL | LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA);
return id_copy;
}
+ /* These support threading, but don't need duplicating. */
case ID_IM:
case ID_BR:
- case ID_SCR:
+ BLI_assert(BKE_previewimg_id_supports_jobs(id));
return NULL;
default:
- BLI_assert(!"ID type preview not supported.");
+ if (!allow_failure) {
+ BLI_assert(!"ID type preview not supported.");
+ }
return NULL;
}
}
@@ -698,6 +708,132 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
}
}
+/* **************************** Object preview ****************** */
+
+struct ObjectPreviewData {
+ /* The main for the preview, not of the current file. */
+ Main *pr_main;
+ /* Copy of the object to create the preview for. The copy is for thread safety (and to insert it
+ * into an own main). */
+ Object *object;
+ int sizex;
+ int sizey;
+};
+
+static Object *object_preview_camera_create(
+ Main *preview_main, ViewLayer *view_layer, Object *preview_object, int sizex, int sizey)
+{
+ Object *camera = BKE_object_add(preview_main, view_layer, OB_CAMERA, "Preview Camera");
+
+ float rotmat[3][3];
+ float dummyscale[3];
+ mat4_to_loc_rot_size(camera->loc, rotmat, dummyscale, preview_object->obmat);
+
+ /* Camera is Y up, so needs additional 90deg rotation around X to match object's Z up. */
+ float drotmat[3][3];
+ axis_angle_to_mat3_single(drotmat, 'X', M_PI_2);
+ mul_m3_m3_post(rotmat, drotmat);
+
+ camera->rotmode = ROT_MODE_QUAT;
+ mat3_to_quat(camera->quat, rotmat);
+
+ /* shader_preview_render() does this too. */
+ if (sizex > sizey) {
+ ((Camera *)camera->data)->lens *= (float)sizey / (float)sizex;
+ }
+
+ return camera;
+}
+
+static Scene *object_preview_scene_create(const struct ObjectPreviewData *preview_data,
+ Depsgraph **r_depsgraph)
+{
+ Scene *scene = BKE_scene_add(preview_data->pr_main, "Object preview scene");
+ ViewLayer *view_layer = scene->view_layers.first;
+ Depsgraph *depsgraph = DEG_graph_new(
+ preview_data->pr_main, scene, view_layer, DAG_EVAL_VIEWPORT);
+
+ BLI_assert(preview_data->object != NULL);
+ BLI_addtail(&preview_data->pr_main->objects, preview_data->object);
+
+ BKE_collection_object_add(preview_data->pr_main, scene->master_collection, preview_data->object);
+
+ Object *camera_object = object_preview_camera_create(preview_data->pr_main,
+ view_layer,
+ preview_data->object,
+ preview_data->sizex,
+ preview_data->sizey);
+
+ scene->camera = camera_object;
+ scene->r.xsch = preview_data->sizex;
+ scene->r.ysch = preview_data->sizey;
+ scene->r.size = 100;
+
+ Base *preview_base = BKE_view_layer_base_find(view_layer, preview_data->object);
+ /* For 'view selected' below. */
+ preview_base->flag |= BASE_SELECTED;
+
+ DEG_graph_build_from_view_layer(depsgraph);
+ DEG_evaluate_on_refresh(depsgraph);
+
+ ED_view3d_camera_to_view_selected(preview_data->pr_main, depsgraph, scene, camera_object);
+
+ BKE_scene_graph_update_tagged(depsgraph, preview_data->pr_main);
+
+ *r_depsgraph = depsgraph;
+ return scene;
+}
+
+static void object_preview_render(IconPreview *preview, IconPreviewSize *preview_sized)
+{
+ Main *preview_main = BKE_main_new();
+ const float pixelsize_old = U.pixelsize;
+ char err_out[256] = "unknown";
+
+ BLI_assert(preview->id_copy && (preview->id_copy != preview->id));
+
+ struct ObjectPreviewData preview_data = {
+ .pr_main = preview_main,
+ /* Act on a copy. */
+ .object = (Object *)preview->id_copy,
+ .sizex = preview_sized->sizex,
+ .sizey = preview_sized->sizey,
+ };
+ Depsgraph *depsgraph;
+ Scene *scene = object_preview_scene_create(&preview_data, &depsgraph);
+
+ /* Ownership is now ours. */
+ preview->id_copy = NULL;
+
+ U.pixelsize = 2.0f;
+
+ ImBuf *ibuf = ED_view3d_draw_offscreen_imbuf_simple(
+ depsgraph,
+ DEG_get_evaluated_scene(depsgraph),
+ NULL,
+ OB_SOLID,
+ DEG_get_evaluated_object(depsgraph, scene->camera),
+ preview_sized->sizex,
+ preview_sized->sizey,
+ IB_rect,
+ V3D_OFSDRAW_NONE,
+ R_ALPHAPREMUL,
+ NULL,
+ NULL,
+ err_out);
+ /* TODO color-management? */
+
+ U.pixelsize = pixelsize_old;
+
+ if (ibuf) {
+ icon_copy_rect(ibuf, preview_sized->sizex, preview_sized->sizey, preview_sized->rect);
+ IMB_freeImBuf(ibuf);
+ }
+
+ DEG_graph_free(depsgraph);
+ BKE_main_free(preview_main);
+}
+
/* **************************** new shader preview system ****************** */
/* inside thread, called by renderer, sets job update value */
@@ -1101,6 +1237,8 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat
ID *id = sp->id;
short idtype = GS(id->name);
+ BLI_assert(id != NULL);
+
if (idtype == ID_IM) {
Image *ima = (Image *)id;
ImBuf *ibuf = NULL;
@@ -1188,27 +1326,72 @@ static void common_preview_startjob(void *customdata,
}
}
-/* exported functions */
-
-static void icon_preview_add_size(IconPreview *ip, uint *rect, int sizex, int sizey)
+/**
+ * Some ID types already have their own, more focused rendering (only objects right now). This is
+ * for the other ones, which all share #ShaderPreview and some functions.
+ */
+static void other_id_types_preview_render(IconPreview *ip,
+ IconPreviewSize *cur_size,
+ const bool is_deferred,
+ short *stop,
+ short *do_update,
+ float *progress)
{
- IconPreviewSize *cur_size = ip->sizes.first, *new_size;
+ ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
+ const bool is_render = !is_deferred;
+
+ /* These types don't use the ShaderPreview mess, they have their own types and functions. */
+ BLI_assert(!ip->id || !ELEM(GS(ip->id->name), ID_OB));
+
+ /* construct shader preview from image size and previewcustomdata */
+ sp->scene = ip->scene;
+ sp->owner = ip->owner;
+ sp->sizex = cur_size->sizex;
+ sp->sizey = cur_size->sizey;
+ sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED;
+ sp->pr_rect = cur_size->rect;
+ sp->id = ip->id;
+ sp->id_copy = ip->id_copy;
+ sp->bmain = ip->bmain;
+ sp->own_id_copy = false;
+ Material *ma = NULL;
- while (cur_size) {
- if (cur_size->sizex == sizex && cur_size->sizey == sizey) {
- /* requested size is already in list, no need to add it again */
- return;
+ if (is_render) {
+ BLI_assert(ip->id);
+
+ /* grease pencil use its own preview file */
+ if (GS(ip->id->name) == ID_MA) {
+ ma = (Material *)ip->id;
}
- cur_size = cur_size->next;
+ if ((ma == NULL) || (ma->gp_style == NULL)) {
+ sp->pr_main = G_pr_main;
+ }
+ else {
+ sp->pr_main = G_pr_main_grease_pencil;
+ }
}
- new_size = MEM_callocN(sizeof(IconPreviewSize), "IconPreviewSize");
- new_size->sizex = sizex;
- new_size->sizey = sizey;
- new_size->rect = rect;
+ common_preview_startjob(sp, stop, do_update, progress);
+ shader_preview_free(sp);
+}
- BLI_addtail(&ip->sizes, new_size);
+/* exported functions */
+
+/**
+ * Find the index to map \a icon_size to data in \a preview_image.
+ */
+static int icon_previewimg_size_index_get(const IconPreviewSize *icon_size,
+ const PreviewImage *preview_image)
+{
+ for (int i = 0; i < NUM_ICON_SIZES; i++) {
+ if ((preview_image->w[i] == icon_size->sizex) && (preview_image->h[i] == icon_size->sizey)) {
+ return i;
+ }
+ }
+
+ BLI_assert(!"The searched icon size does not match any in the preview image");
+ return -1;
}
static void icon_preview_startjob_all_sizes(void *customdata,
@@ -1235,41 +1418,43 @@ static void icon_preview_startjob_all_sizes(void *customdata,
continue;
}
- ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
- const bool is_render = !(prv->tag & PRV_TAG_DEFFERED);
-
- /* construct shader preview from image size and previewcustomdata */
- sp->scene = ip->scene;
- sp->owner = ip->owner;
- sp->sizex = cur_size->sizex;
- sp->sizey = cur_size->sizey;
- sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED;
- sp->pr_rect = cur_size->rect;
- sp->id = ip->id;
- sp->id_copy = ip->id_copy;
- sp->bmain = ip->bmain;
- sp->own_id_copy = false;
- Material *ma = NULL;
-
- if (is_render) {
- BLI_assert(ip->id);
-
- /* grease pencil use its own preview file */
- if (GS(ip->id->name) == ID_MA) {
- ma = (Material *)ip->id;
- }
+#ifndef NDEBUG
+ {
+ int size_index = icon_previewimg_size_index_get(cur_size, prv);
+ BLI_assert(!BKE_previewimg_is_finished(prv, size_index));
+ }
+#endif
- if ((ma == NULL) || (ma->gp_style == NULL)) {
- sp->pr_main = G_pr_main;
- }
- else {
- sp->pr_main = G_pr_main_grease_pencil;
- }
+ if (ip->id && ELEM(GS(ip->id->name), ID_OB)) {
+ /* Much simpler than the ShaderPreview mess used for other ID types. */
+ object_preview_render(ip, cur_size);
+ }
+ else {
+ other_id_types_preview_render(
+ ip, cur_size, (prv->tag & PRV_TAG_DEFFERED), stop, do_update, progress);
+ }
+ }
+}
+
+static void icon_preview_add_size(IconPreview *ip, uint *rect, int sizex, int sizey)
+{
+ IconPreviewSize *cur_size = ip->sizes.first, *new_size;
+
+ while (cur_size) {
+ if (cur_size->sizex == sizex && cur_size->sizey == sizey) {
+ /* requested size is already in list, no need to add it again */
+ return;
}
- common_preview_startjob(sp, stop, do_update, progress);
- shader_preview_free(sp);
+ cur_size = cur_size->next;
}
+
+ new_size = MEM_callocN(sizeof(IconPreviewSize), "IconPreviewSize");
+ new_size->sizex = sizex;
+ new_size->sizey = sizey;
+ new_size->rect = rect;
+
+ BLI_addtail(&ip->sizes, new_size);
}
static void icon_preview_endjob(void *customdata)
@@ -1302,9 +1487,15 @@ static void icon_preview_endjob(void *customdata)
if (ip->owner) {
PreviewImage *prv_img = ip->owner;
prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING;
+
+ LISTBASE_FOREACH (IconPreviewSize *, icon_size, &ip->sizes) {
+ int size_index = icon_previewimg_size_index_get(icon_size, prv_img);
+ BKE_previewimg_finish(prv_img, size_index);
+ }
+
if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) {
BLI_assert(prv_img->tag & PRV_TAG_DEFFERED);
- BKE_previewimg_cached_release_pointer(prv_img);
+ BKE_previewimg_deferred_release(prv_img);
}
}
}
@@ -1333,7 +1524,9 @@ void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, uint *rect, int s
ip.scene = scene;
ip.owner = BKE_previewimg_id_ensure(id);
ip.id = id;
- ip.id_copy = duplicate_ids(id);
+ /* Control isn't given back to the caller until the preview is done. So we don't need to copy
+ * the ID to avoid thread races. */
+ ip.id_copy = duplicate_ids(id, true);
icon_preview_add_size(&ip, rect, sizex, sizey);
@@ -1376,7 +1569,7 @@ void ED_preview_icon_job(
ip->scene = CTX_data_scene(C);
ip->owner = owner;
ip->id = id;
- ip->id_copy = duplicate_ids(id);
+ ip->id_copy = duplicate_ids(id, false);
icon_preview_add_size(ip, rect, sizex, sizey);
@@ -1416,6 +1609,8 @@ void ED_preview_shader_job(const bContext *C,
Scene *scene = CTX_data_scene(C);
short id_type = GS(id->name);
+ BLI_assert(BKE_previewimg_id_supports_jobs(id));
+
/* Use workspace render only for buttons Window,
* since the other previews are related to the datablock. */
@@ -1445,7 +1640,7 @@ void ED_preview_shader_job(const bContext *C,
sp->sizey = sizey;
sp->pr_method = method;
sp->id = id;
- sp->id_copy = duplicate_ids(id);
+ sp->id_copy = duplicate_ids(id, false);
sp->own_id_copy = true;
sp->parent = parent;
sp->slot = slot;
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index b69337b1621..cac01bdc048 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -735,45 +735,40 @@ void OBJECT_OT_material_slot_remove_unused(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name New Material Operator
+/** \name Create Material Operators
* \{ */
-static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
+struct MaterialCreationData {
+ Object *ob;
+ PropertyPointerRNA pprop;
+};
+
+static void material_creation_data_init_from_UI_context(bContext *C,
+ struct MaterialCreationData *r_create_data)
{
- Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr, idptr;
+ PointerRNA ptr;
PropertyRNA *prop;
/* hook into UI */
UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
- Object *ob = (prop && RNA_struct_is_a(ptr.type, &RNA_Object)) ? ptr.data : NULL;
+ r_create_data->ob = (prop && RNA_struct_is_a(ptr.type, &RNA_Object)) ? ptr.data : NULL;
+ r_create_data->pprop.ptr = ptr;
+ r_create_data->pprop.prop = prop;
+}
- /* add or copy material */
- if (ma) {
- Material *new_ma = (Material *)BKE_id_copy_ex(
- bmain, &ma->id, NULL, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
- ma = new_ma;
- }
- else {
- const char *name = DATA_("Material");
- if (!(ob != NULL && ob->type == OB_GPENCIL)) {
- ma = BKE_material_add(bmain, name);
- }
- else {
- ma = BKE_gpencil_material_add(bmain, name);
- }
- ED_node_shader_default(C, &ma->id);
- ma->use_nodes = true;
- }
+static void material_creation_assign(bContext *C,
+ Material *ma,
+ struct MaterialCreationData *create_data)
+{
+ Main *bmain = CTX_data_main(C);
- if (prop) {
- if (ob != NULL) {
+ if (create_data->pprop.prop) {
+ if (create_data->ob != NULL) {
/* Add slot follows user-preferences for creating new slots,
* RNA pointer assignment doesn't, see: T60014. */
- if (BKE_object_material_get_p(ob, ob->actcol) == NULL) {
- BKE_object_material_slot_add(bmain, ob);
+ if (BKE_object_material_get_p(create_data->ob, create_data->ob->actcol) == NULL) {
+ BKE_object_material_slot_add(bmain, create_data->ob);
}
}
@@ -781,10 +776,32 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
* pointer use also increases user, so this compensates it */
id_us_min(&ma->id);
+ PointerRNA idptr;
RNA_id_pointer_create(&ma->id, &idptr);
- RNA_property_pointer_set(&ptr, prop, idptr, NULL);
- RNA_property_update(C, &ptr, prop);
+ RNA_property_pointer_set(&create_data->pprop.ptr, create_data->pprop.prop, idptr, NULL);
+ RNA_property_update(C, &create_data->pprop.ptr, create_data->pprop.prop);
+ }
+}
+
+static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ struct MaterialCreationData create_data;
+
+ material_creation_data_init_from_UI_context(C, &create_data);
+
+ const char *name = DATA_("Material");
+ Material *ma;
+ if ((create_data.ob == NULL) || (create_data.ob->type != OB_GPENCIL)) {
+ ma = BKE_material_add(bmain, name);
+ }
+ else {
+ ma = BKE_gpencil_material_add(bmain, name);
}
+ ED_node_shader_default(C, &ma->id);
+ ma->use_nodes = true;
+
+ material_creation_assign(C, ma, &create_data);
WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, ma);
@@ -806,27 +823,57 @@ void MATERIAL_OT_new(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
-/** \} */
+static int duplicate_material_exec(bContext *C, wmOperator *op)
+{
+ Material *old_ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
+
+ if (!old_ma) {
+ BKE_report(
+ op->reports,
+ RPT_ERROR,
+ "Incorrect context for duplicating a material (did not find material to duplicate)");
+ return OPERATOR_CANCELLED;
+ }
+
+ Main *bmain = CTX_data_main(C);
+ struct MaterialCreationData create_data;
+
+ material_creation_data_init_from_UI_context(C, &create_data);
+
+ Material *new_ma = (Material *)BKE_id_copy_ex(
+ bmain, &old_ma->id, NULL, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
+
+ material_creation_assign(C, new_ma, &create_data);
+
+ WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, new_ma);
+
+ return OPERATOR_FINISHED;
+}
+
+void MATERIAL_OT_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate Material";
+ ot->idname = "MATERIAL_OT_duplicate";
+ ot->description = "Duplicate an existing material";
+
+ /* api callbacks */
+ ot->exec = duplicate_material_exec;
+ ot->poll = object_materials_supported_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
/* -------------------------------------------------------------------- */
-/** \name New Texture Operator
+/** \name Create Texture Operators
* \{ */
-static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
+static void texture_creation_assign(bContext *C, Tex *tex)
{
- Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
- Main *bmain = CTX_data_main(C);
PointerRNA ptr, idptr;
PropertyRNA *prop;
- /* add or copy texture */
- if (tex) {
- tex = (Tex *)BKE_id_copy(bmain, &tex->id);
- }
- else {
- tex = BKE_texture_add(bmain, DATA_("Texture"));
- }
-
/* hook into UI */
UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
@@ -839,6 +886,14 @@ static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
RNA_property_pointer_set(&ptr, prop, idptr, NULL);
RNA_property_update(C, &ptr, prop);
}
+}
+
+static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ Tex *tex = BKE_texture_add(bmain, DATA_("Texture"));
+
+ texture_creation_assign(C, tex);
WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex);
@@ -859,31 +914,53 @@ void TEXTURE_OT_new(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
+static int duplicate_texture_exec(bContext *C, wmOperator *op)
+{
+ Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
+
+ if (!tex) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Incorrect context for duplicating a texture (did not find texture to duplicate)");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* add or copy texture */
+ Main *bmain = CTX_data_main(C);
+ tex = (Tex *)BKE_id_copy(bmain, &tex->id);
+
+ texture_creation_assign(C, tex);
+
+ WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXTURE_OT_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate Texture";
+ ot->idname = "TEXTURE_OT_duplicate";
+ ot->description = "Duplicate an existing texture";
+
+ /* api callbacks */
+ ot->exec = duplicate_texture_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
-/** \name new world operator
+/** \name Create world operators
* \{ */
-static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
+static void world_creation_assign(bContext *C, World *wo)
{
- World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
- Main *bmain = CTX_data_main(C);
PointerRNA ptr, idptr;
PropertyRNA *prop;
- /* add or copy world */
- if (wo) {
- World *new_wo = (World *)BKE_id_copy_ex(
- bmain, &wo->id, NULL, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
- wo = new_wo;
- }
- else {
- wo = BKE_world_add(bmain, DATA_("World"));
- ED_node_shader_default(C, &wo->id);
- wo->use_nodes = true;
- }
-
/* hook into UI */
UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
@@ -896,6 +973,17 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
RNA_property_pointer_set(&ptr, prop, idptr, NULL);
RNA_property_update(C, &ptr, prop);
}
+}
+
+static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+
+ World *wo = BKE_world_add(bmain, DATA_("World"));
+ ED_node_shader_default(C, &wo->id);
+ wo->use_nodes = true;
+
+ world_creation_assign(C, wo);
WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo);
@@ -907,7 +995,7 @@ void WORLD_OT_new(wmOperatorType *ot)
/* identifiers */
ot->name = "New World";
ot->idname = "WORLD_OT_new";
- ot->description = "Create a new world Data-Block";
+ ot->description = "Create a new world data-block";
/* api callbacks */
ot->exec = new_world_exec;
@@ -916,6 +1004,36 @@ void WORLD_OT_new(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
+static int duplicate_world_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
+
+ if (wo) {
+ Main *bmain = CTX_data_main(C);
+ wo = (World *)BKE_id_copy(bmain, &wo->id);
+ }
+
+ world_creation_assign(C, wo);
+
+ WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo);
+
+ return OPERATOR_FINISHED;
+}
+
+void WORLD_OT_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate World";
+ ot->idname = "WORLD_OT_duplicate";
+ ot->description = "Duplicate an existing world data-block";
+
+ /* api callbacks */
+ ot->exec = duplicate_world_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index 244ebea5bbe..1dfe606be78 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -604,7 +604,7 @@ static eContextResult screen_ctx_sequences(const bContext *C, bContextDataResult
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (ed) {
LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
@@ -618,7 +618,7 @@ static eContextResult screen_ctx_selected_sequences(const bContext *C, bContextD
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (ed) {
LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
if (seq->flag & SELECT) {
@@ -635,7 +635,7 @@ static eContextResult screen_ctx_selected_editable_sequences(const bContext *C,
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = WM_window_get_active_scene(win);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (ed) {
LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
if (seq->flag & SELECT && !(seq->flag & SEQ_LOCK)) {
@@ -649,8 +649,6 @@ static eContextResult screen_ctx_selected_editable_sequences(const bContext *C,
}
static eContextResult screen_ctx_selected_nla_strips(const bContext *C, bContextDataResult *result)
{
- wmWindow *win = CTX_wm_window(C);
- Scene *scene = WM_window_get_active_scene(win);
bAnimContext ac;
if (ANIM_animdata_get_context(C, &ac) != 0) {
ListBase anim_data = {NULL, NULL};
@@ -663,7 +661,7 @@ static eContextResult screen_ctx_selected_nla_strips(const bContext *C, bContext
NlaTrack *nlt = (NlaTrack *)ale->data;
LISTBASE_FOREACH (NlaStrip *, strip, &nlt->strips) {
if (strip->flag & NLASTRIP_FLAG_SELECT) {
- CTX_data_list_add(result, &scene->id, &RNA_NlaStrip, strip);
+ CTX_data_list_add(result, ale->id, &RNA_NlaStrip, strip);
}
}
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 6be2fb8004b..be52874ed0b 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1133,12 +1133,11 @@ void ED_screen_scene_change(bContext *C, wmWindow *win, Scene *scene)
ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *area, int type)
{
- wmWindow *win = CTX_wm_window(C);
ScrArea *newsa = NULL;
SpaceLink *newsl;
if (!area || area->full == NULL) {
- newsa = ED_screen_state_toggle(C, win, area, SCREENMAXIMIZED);
+ newsa = ED_screen_state_maximized_create(C);
}
if (!newsa) {
@@ -1149,11 +1148,11 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *area, int type)
newsl = newsa->spacedata.first;
/* Tag the active space before changing, so we can identify it when user wants to go back. */
- if ((newsl->link_flag & SPACE_FLAG_TYPE_TEMPORARY) == 0) {
+ if (newsl && (newsl->link_flag & SPACE_FLAG_TYPE_TEMPORARY) == 0) {
newsl->link_flag |= SPACE_FLAG_TYPE_WAS_ACTIVE;
}
- ED_area_newspace(C, newsa, type, newsl->link_flag & SPACE_FLAG_TYPE_TEMPORARY);
+ ED_area_newspace(C, newsa, type, (newsl && newsl->link_flag & SPACE_FLAG_TYPE_TEMPORARY));
return newsa;
}
@@ -1217,13 +1216,108 @@ void ED_screen_full_restore(bContext *C, ScrArea *area)
}
/**
- * this function toggles: if area is maximized/full then the parent will be restored
+ * \param toggle_area: If this is set, its space data will be swapped with the one of the new emtpy
+ * area, when toggling back it can be swapped back again.
+ * \return The newly created screen with the non-normal area.
+ */
+static bScreen *screen_state_to_nonnormal(bContext *C,
+ wmWindow *win,
+ ScrArea *toggle_area,
+ int state)
+{
+ Main *bmain = CTX_data_main(C);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+
+ /* change from SCREENNORMAL to new state */
+ WorkSpaceLayout *layout_new;
+ ScrArea *newa;
+ char newname[MAX_ID_NAME - 2];
+
+ BLI_assert(ELEM(state, SCREENMAXIMIZED, SCREENFULL));
+
+ bScreen *oldscreen = WM_window_get_active_screen(win);
+
+ oldscreen->state = state;
+ BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal");
+
+ layout_new = ED_workspace_layout_add(bmain, workspace, win, newname);
+
+ bScreen *screen = BKE_workspace_layout_screen_get(layout_new);
+ screen->state = state;
+ screen->redraws_flag = oldscreen->redraws_flag;
+ screen->temp = oldscreen->temp;
+ screen->flag = oldscreen->flag;
+
+ /* timer */
+ screen->animtimer = oldscreen->animtimer;
+ oldscreen->animtimer = NULL;
+
+ newa = (ScrArea *)screen->areabase.first;
+
+ /* swap area */
+ if (toggle_area) {
+ ED_area_data_swap(newa, toggle_area);
+ newa->flag = toggle_area->flag; /* mostly for AREA_FLAG_WASFULLSCREEN */
+ }
+
+ if (state == SCREENFULL) {
+ /* temporarily hide global areas */
+ LISTBASE_FOREACH (ScrArea *, glob_area, &win->global_areas.areabase) {
+ glob_area->global->flag |= GLOBAL_AREA_IS_HIDDEN;
+ }
+ /* temporarily hide the side panels/header */
+ LISTBASE_FOREACH (ARegion *, region, &newa->regionbase) {
+ region->flagfullscreen = region->flag;
+
+ if (ELEM(region->regiontype,
+ RGN_TYPE_UI,
+ RGN_TYPE_HEADER,
+ RGN_TYPE_TOOL_HEADER,
+ RGN_TYPE_FOOTER,
+ RGN_TYPE_TOOLS,
+ RGN_TYPE_NAV_BAR,
+ RGN_TYPE_EXECUTE)) {
+ region->flag |= RGN_FLAG_HIDDEN;
+ }
+ }
+ }
+
+ if (toggle_area) {
+ toggle_area->full = oldscreen;
+ }
+ newa->full = oldscreen;
+
+ ED_screen_change(C, screen);
+ ED_area_tag_refresh(newa);
+
+ return screen;
+}
+
+/**
+ * Create a new temporary screen with a maximized, empty area.
+ * This can be closed with #ED_screen_state_toggle().
+ *
+ * Use this to just create a new maximized screen/area, rather than maximizing an existing one.
+ * Otherwise, maximize with #ED_screen_state_toggle().
+ */
+ScrArea *ED_screen_state_maximized_create(bContext *C)
+{
+ bScreen *screen = screen_state_to_nonnormal(C, CTX_wm_window(C), NULL, SCREENMAXIMIZED);
+ return screen->areabase.first;
+}
+
+/**
+ * This function toggles: if area is maximized/full then the parent will be restored.
+ *
+ * Use #ED_screen_state_maximized_create() if you do not want the toggle behavior when changing to
+ * a maximized area. I.e. if you just want to open a new maximized screen/area, not maximize a
+ * specific area. In the former case, space data of the maximized and non-maximized area should be
+ * independent, in the latter it should be the same.
*
* \warning \a area may be freed.
*/
ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const short state)
{
- Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
WorkSpace *workspace = WM_window_get_active_workspace(win);
@@ -1257,7 +1351,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const
screen->state = SCREENNORMAL;
screen->flag = oldscreen->flag;
- /* find old area to restore from */
+ /* Find old area we may have swapped dummy space data to. It's swapped back here. */
ScrArea *fullsa = NULL;
LISTBASE_FOREACH (ScrArea *, old, &screen->areabase) {
/* area to restore from is always first */
@@ -1271,13 +1365,6 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const
area->full = NULL;
- if (fullsa == NULL) {
- if (G.debug & G_DEBUG) {
- printf("%s: something wrong in areafullscreen\n", __func__);
- }
- return NULL;
- }
-
if (state == SCREENFULL) {
/* unhide global areas */
LISTBASE_FOREACH (ScrArea *, glob_area, &win->global_areas.areabase) {
@@ -1289,14 +1376,16 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const
}
}
- ED_area_data_swap(fullsa, area);
+ if (fullsa) {
+ ED_area_data_swap(fullsa, area);
+ ED_area_tag_refresh(fullsa);
+ }
/* animtimer back */
screen->animtimer = oldscreen->animtimer;
oldscreen->animtimer = NULL;
ED_screen_change(C, screen);
- ED_area_tag_refresh(fullsa);
BKE_workspace_layout_remove(CTX_data_main(C), workspace, layout_old);
@@ -1307,68 +1396,16 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const
screen->skip_handling = true;
}
else {
- /* change from SCREENNORMAL to new state */
- WorkSpaceLayout *layout_new;
- ScrArea *newa;
- char newname[MAX_ID_NAME - 2];
-
- BLI_assert(ELEM(state, SCREENMAXIMIZED, SCREENFULL));
-
- bScreen *oldscreen = WM_window_get_active_screen(win);
-
- oldscreen->state = state;
- BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal");
-
- layout_new = ED_workspace_layout_add(bmain, workspace, win, newname);
-
- screen = BKE_workspace_layout_screen_get(layout_new);
- screen->state = state;
- screen->redraws_flag = oldscreen->redraws_flag;
- screen->temp = oldscreen->temp;
- screen->flag = oldscreen->flag;
-
- /* timer */
- screen->animtimer = oldscreen->animtimer;
- oldscreen->animtimer = NULL;
+ ScrArea *toggle_area = area;
/* use random area when we have no active one, e.g. when the
* mouse is outside of the window and we open a file browser */
- if (!area || area->global) {
- area = oldscreen->areabase.first;
+ if (!toggle_area || toggle_area->global) {
+ bScreen *oldscreen = WM_window_get_active_screen(win);
+ toggle_area = oldscreen->areabase.first;
}
- newa = (ScrArea *)screen->areabase.first;
-
- /* copy area */
- ED_area_data_swap(newa, area);
- newa->flag = area->flag; /* mostly for AREA_FLAG_WASFULLSCREEN */
-
- if (state == SCREENFULL) {
- /* temporarily hide global areas */
- LISTBASE_FOREACH (ScrArea *, glob_area, &win->global_areas.areabase) {
- glob_area->global->flag |= GLOBAL_AREA_IS_HIDDEN;
- }
- /* temporarily hide the side panels/header */
- LISTBASE_FOREACH (ARegion *, region, &newa->regionbase) {
- region->flagfullscreen = region->flag;
-
- if (ELEM(region->regiontype,
- RGN_TYPE_UI,
- RGN_TYPE_HEADER,
- RGN_TYPE_TOOL_HEADER,
- RGN_TYPE_FOOTER,
- RGN_TYPE_TOOLS,
- RGN_TYPE_NAV_BAR,
- RGN_TYPE_EXECUTE)) {
- region->flag |= RGN_FLAG_HIDDEN;
- }
- }
- }
-
- area->full = oldscreen;
- newa->full = oldscreen;
-
- ED_screen_change(C, screen);
+ screen = screen_state_to_nonnormal(C, win, toggle_area, state);
}
/* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */
@@ -1412,9 +1449,6 @@ ScrArea *ED_screen_temp_space_open(bContext *C,
area->flag |= AREA_FLAG_STACKED_FULLSCREEN;
((SpaceLink *)area->spacedata.first)->link_flag |= SPACE_FLAG_TYPE_TEMPORARY;
}
- else if (ctx_area != NULL && ctx_area->spacetype == space_type) {
- area = ED_screen_state_toggle(C, CTX_wm_window(C), ctx_area, SCREENMAXIMIZED);
- }
else {
area = ED_screen_full_newspace(C, ctx_area, (int)space_type);
((SpaceLink *)area->spacedata.first)->link_flag |= SPACE_FLAG_TYPE_TEMPORARY;
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 72b3b344813..8768404d74f 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -3918,7 +3918,7 @@ static void SCREEN_OT_region_quadview(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Toggle Quad View";
- ot->description = "Split selected area into camera, front, right & top views";
+ ot->description = "Split selected area into camera, front, right, and top views";
ot->idname = "SCREEN_OT_region_quadview";
/* api callbacks */
@@ -5509,7 +5509,8 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(ED_OT_undo_redo);
WM_operatortype_append(ED_OT_undo_history);
- WM_operatortype_append(ED_OT_flush_edits);
+ WM_operatortype_append(ED_OT_lib_id_load_custom_preview);
+ WM_operatortype_append(ED_OT_lib_id_generate_preview);
}
/** \} */
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 9bf3d2610d8..fff8d27ef5b 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -32,6 +32,7 @@ set(INC
../../windowmanager
../../../../intern/atomic
../../../../intern/clog
+ ../../../../intern/eigen
../../../../intern/glew-mx
../../../../intern/guardedalloc
)
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 3a6b91443a0..324fd5d3075 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -40,6 +40,7 @@
#include "IMB_imbuf_types.h"
#include "DNA_brush_types.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
@@ -934,7 +935,7 @@ void PAINT_OT_grab_clone(wmOperatorType *ot)
-FLT_MAX,
FLT_MAX,
"Delta",
- "Delta offset of clone image in 0.0..1.0 coordinates",
+ "Delta offset of clone image in 0.0 to 1.0 coordinates",
-1.0f,
1.0f);
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 8c16300a047..cca4ffd4d78 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -6748,7 +6748,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
"Generated Type",
"Fill the image with a grid for UV map testing");
RNA_def_boolean(
- ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
+ ot->srna, "float", 0, "32-bit Float", "Create image with 32-bit floating-point bit depth");
}
static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
@@ -6781,7 +6781,7 @@ static bool add_simple_uvs_poll(bContext *C)
void PAINT_OT_add_simple_uvs(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add simple UVs";
+ ot->name = "Add Simple UVs";
ot->description = "Add cube map uvs on mesh";
ot->idname = "PAINT_OT_add_simple_uvs";
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 175d98ba9aa..3ca0d853d6a 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -43,7 +43,6 @@ struct wmEvent;
struct wmKeyConfig;
struct wmOperator;
struct wmOperatorType;
-struct wmWindowManager;
enum ePaintMode;
enum ePaintSymmetryFlags;
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 4bfb4f140bc..713049137ce 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -1554,6 +1554,11 @@ static int sculpt_trim_gesture_box_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ if (ss->totvert == 0) {
+ /* No geometry to trim or to detect a valid position for the trimming shape. */
+ return OPERATOR_CANCELLED;
+ }
+
SculptGestureContext *sgcontext = sculpt_gesture_init_from_box(C, op);
if (!sgcontext) {
return OPERATOR_CANCELLED;
@@ -1591,6 +1596,11 @@ static int sculpt_trim_gesture_lasso_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ if (ss->totvert == 0) {
+ /* No geometry to trim or to detect a valid position for the trimming shape. */
+ return OPERATOR_CANCELLED;
+ }
+
SculptGestureContext *sgcontext = sculpt_gesture_init_from_lasso(C, op);
if (!sgcontext) {
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
index b831687ca67..96d22fe4a21 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
@@ -401,7 +401,7 @@ void PAINT_OT_vertex_color_brightness_contrast(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "Vertex Paint Bright/Contrast";
+ ot->name = "Vertex Paint Brightness/Contrast";
ot->idname = "PAINT_OT_vertex_color_brightness_contrast";
ot->description = "Adjust vertex color brightness/contrast";
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index dd654b41ffa..bf55d6a323e 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1539,6 +1539,7 @@ static bool sculpt_tool_is_proxy_used(const char sculpt_tool)
SCULPT_TOOL_SMOOTH,
SCULPT_TOOL_LAYER,
SCULPT_TOOL_POSE,
+ SCULPT_TOOL_DISPLACEMENT_SMEAR,
SCULPT_TOOL_BOUNDARY,
SCULPT_TOOL_CLOTH,
SCULPT_TOOL_PAINT,
@@ -2703,6 +2704,7 @@ static float brush_strength(const Sculpt *sd,
final_pressure = pressure * pressure;
return final_pressure * overlap * feather;
case SCULPT_TOOL_SMEAR:
+ case SCULPT_TOOL_DISPLACEMENT_SMEAR:
return alpha * pressure * overlap * feather;
case SCULPT_TOOL_CLAY_STRIPS:
/* Clay Strips needs less strength to compensate the curve. */
@@ -3446,6 +3448,151 @@ static void do_displacement_eraser_brush(Sculpt *sd, Object *ob, PBVHNode **node
/** \} */
+/** \name Sculpt Multires Displacement Smear Brush
+ * \{ */
+
+static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float bstrength = clamp_f(ss->cache->bstrength, 0.0f, 1.0f);
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
+ continue;
+ }
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.vertex,
+ thread_id);
+
+ float current_disp[3];
+ float current_disp_norm[3];
+ float interp_limit_surface_disp[3];
+
+ copy_v3_v3(interp_limit_surface_disp, ss->cache->prev_displacement[vd.index]);
+
+ switch (brush->smear_deform_type) {
+ case BRUSH_SMEAR_DEFORM_DRAG:
+ sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location);
+ break;
+ case BRUSH_SMEAR_DEFORM_PINCH:
+ sub_v3_v3v3(current_disp, ss->cache->location, vd.co);
+ break;
+ case BRUSH_SMEAR_DEFORM_EXPAND:
+ sub_v3_v3v3(current_disp, vd.co, ss->cache->location);
+ break;
+ }
+
+ normalize_v3_v3(current_disp_norm, current_disp);
+ mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength);
+
+ float weights_accum = 1.0f;
+
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
+ float vertex_disp[3];
+ float vertex_disp_norm[3];
+ float neighbor_limit_co[3];
+ SCULPT_vertex_limit_surface_get(ss, ni.vertex, neighbor_limit_co);
+ sub_v3_v3v3(vertex_disp,
+ ss->cache->limit_surface_co[ni.index],
+ ss->cache->limit_surface_co[vd.index]);
+ const float *neighbor_limit_surface_disp = ss->cache->prev_displacement[ni.index];
+ normalize_v3_v3(vertex_disp_norm, vertex_disp);
+ if (dot_v3v3(current_disp_norm, vertex_disp_norm) < 0.0f) {
+ const float disp_interp = clamp_f(
+ -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f);
+ madd_v3_v3fl(interp_limit_surface_disp, neighbor_limit_surface_disp, disp_interp);
+ weights_accum += disp_interp;
+ }
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+ mul_v3_fl(interp_limit_surface_disp, 1.0f / weights_accum);
+
+ float new_co[3];
+ add_v3_v3v3(new_co, ss->cache->limit_surface_co[vd.index], interp_limit_surface_disp);
+ interp_v3_v3v3(vd.co, vd.co, new_co, fade);
+
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_displacement_smear_store_prev_disp_task_cb_ex(
+ void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ sub_v3_v3v3(ss->cache->prev_displacement[vd.index],
+ SCULPT_vertex_co_get(ss, vd.vertex),
+ ss->cache->limit_surface_co[vd.index]);
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_displacement_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ SculptSession *ss = ob->sculpt;
+
+ BKE_curvemapping_init(brush->curve);
+ SCULPT_vertex_random_access_ensure(ss);
+
+ const int totvert = SCULPT_vertex_count_get(ss);
+ if (!ss->cache->prev_displacement) {
+ ss->cache->prev_displacement = MEM_malloc_arrayN(
+ totvert, sizeof(float[3]), "prev displacement");
+ ss->cache->limit_surface_co = MEM_malloc_arrayN(totvert, sizeof(float[3]), "limit surface co");
+
+ for (int i = 0; i < totvert; i++) {
+ SculptVertRef vref = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ SCULPT_vertex_limit_surface_get(ss, vref, ss->cache->limit_surface_co[i]);
+ sub_v3_v3v3(ss->cache->prev_displacement[i],
+ SCULPT_vertex_co_get(ss, vref),
+ ss->cache->limit_surface_co[i]);
+ }
+ }
+ /* Threaded loop over nodes. */
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+ BLI_task_parallel_range(
+ 0, totnode, &data, do_displacement_smear_store_prev_disp_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_displacement_smear_brush_task_cb_ex, &settings);
+}
+
+/** \} */
+
static void do_draw_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
@@ -4578,6 +4725,8 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
(len_v3(grab_delta) / ss->cache->radius)) :
0.0f;
+ const bool do_elastic = brush->snake_hook_deform_type == BRUSH_SNAKE_HOOK_DEFORM_ELASTIC;
+
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
@@ -4585,18 +4734,28 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ KelvinletParams params;
+ BKE_kelvinlet_init_params(&params, ss->cache->radius, bstrength, 1.0f, 0.4f);
+
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const float fade = bstrength * SCULPT_brush_strength_factor(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.vertex,
- thread_id);
+ if (do_elastic || sculpt_brush_test_sq_fn(&test, vd.co)) {
+
+ float fade;
+ if (do_elastic) {
+ fade = 1.0f;
+ }
+ else {
+ fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.vertex,
+ thread_id);
+ }
mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
@@ -4635,6 +4794,17 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
add_v3_v3(proxy[vd.i], delta_rotate);
}
+ if (do_elastic) {
+ float disp[3];
+ BKE_kelvinlet_grab_triscale(disp, &params, vd.co, ss->cache->location, proxy[vd.i]);
+ mul_v3_fl(disp, bstrength * 20.0f);
+ if (vd.mask) {
+ mul_v3_fl(disp, 1.0f - *vd.mask);
+ }
+ mul_v3_fl(disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.vertex));
+ copy_v3_v3(proxy[vd.i], disp);
+ }
+
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
@@ -6021,7 +6191,8 @@ static void sculpt_topology_update(Sculpt *sd,
ss->cache->radius,
(brush->flag & BRUSH_FRONTFACE) != 0,
(brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE),
- symidx, brush->sculpt_tool != SCULPT_TOOL_DRAW_SHARP);
+ symidx,
+ brush->sculpt_tool != SCULPT_TOOL_DRAW_SHARP);
}
MEM_SAFE_FREE(nodes);
@@ -6086,45 +6257,12 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
/* Build a list of all nodes that are potentially within the brush's area of influence */
- /* These brushes need to update all nodes as they are not constrained by the brush radius */
- /* Elastic deform needs all nodes to avoid artifacts as the effect of the brush is not
- * constrained by the radius. */
- /* Pose needs all nodes because it applies all symmetry iterations at the same time and the IK
- * chain can grow to any area of the model. */
- /* This can be optimized by filtering the nodes after calculating the chain. */
- if (ELEM(brush->sculpt_tool,
- SCULPT_TOOL_ELASTIC_DEFORM,
- SCULPT_TOOL_POSE,
- SCULPT_TOOL_BOUNDARY)) {
+ if (SCULPT_tool_needs_all_pbvh_nodes(brush)) {
+ /* These brushes need to update all nodes as they are not constrained by the brush radius */
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
}
else if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
- if (brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL) {
- SculptSearchSphereData data = {
- .ss = ss,
- .sd = sd,
- .radius_squared = square_f(ss->cache->initial_radius * (1.0 + brush->cloth_sim_limit)),
- .original = false,
- .ignore_fully_ineffective = false,
- .center = ss->cache->initial_location,
- };
- BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
- }
- if (brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC) {
- SculptSearchSphereData data = {
- .ss = ss,
- .sd = sd,
- .radius_squared = square_f(ss->cache->radius * (1.0 + brush->cloth_sim_limit)),
- .original = false,
- .ignore_fully_ineffective = false,
- .center = ss->cache->location,
- };
- BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
- }
- else {
- /* Gobal simulation, get all nodes. */
- BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
- }
+ nodes = SCULPT_cloth_brush_affected_nodes_gather(ss, brush, &totnode);
}
else {
const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true :
@@ -6160,6 +6298,17 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
}
}
+ /* Initialize automasking cache. For anchored brushes with spherical falloff, we start off with
+ * zero radius, thus we have no pbvh nodes on the first brush step. */
+ if (totnode ||
+ ((brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) && (brush->flag & BRUSH_ANCHORED))) {
+ if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
+ if (SCULPT_is_automasking_enabled(sd, ss, brush)) {
+ ss->cache->automasking = SCULPT_automasking_cache_init(sd, brush, ob);
+ }
+ }
+ }
+
/* Only act if some verts are inside the brush area. */
if (totnode) {
float location[3];
@@ -6223,12 +6372,6 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
update_brush_local_mat(sd, ob);
}
- if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
- if (SCULPT_is_automasking_enabled(sd, ss, brush)) {
- ss->cache->automasking = SCULPT_automasking_cache_init(sd, brush, ob);
- }
- }
-
if (brush->sculpt_tool == SCULPT_TOOL_POSE && SCULPT_stroke_is_first_brush_step(ss->cache)) {
SCULPT_pose_brush_init(sd, ob, ss, brush);
}
@@ -6347,6 +6490,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
case SCULPT_TOOL_DISPLACEMENT_ERASER:
do_displacement_eraser_brush(sd, ob, nodes, totnode);
break;
+ case SCULPT_TOOL_DISPLACEMENT_SMEAR:
+ do_displacement_smear_brush(sd, ob, nodes, totnode);
+ break;
case SCULPT_TOOL_PAINT:
SCULPT_do_paint_brush(sd, ob, nodes, totnode);
break;
@@ -6936,6 +7082,8 @@ static const char *sculpt_tool_name(Sculpt *sd)
return "Draw Face Sets";
case SCULPT_TOOL_DISPLACEMENT_ERASER:
return "Multires Displacement Eraser";
+ case SCULPT_TOOL_DISPLACEMENT_SMEAR:
+ return "Multires Displacement Smear";
case SCULPT_TOOL_PAINT:
return "Paint Brush";
case SCULPT_TOOL_SMEAR:
@@ -6958,6 +7106,8 @@ void SCULPT_cache_free(StrokeCache *cache)
MEM_SAFE_FREE(cache->layer_displacement_factor);
MEM_SAFE_FREE(cache->prev_colors);
MEM_SAFE_FREE(cache->detail_directions);
+ MEM_SAFE_FREE(cache->prev_displacement);
+ MEM_SAFE_FREE(cache->limit_surface_co);
if (cache->pose_ik_chain) {
SCULPT_pose_ik_chain_free(cache->pose_ik_chain);
@@ -7129,6 +7279,7 @@ static void sculpt_update_cache_invariants(
SCULPT_TOOL_MASK,
SCULPT_TOOL_SMOOTH,
SCULPT_TOOL_SIMPLIFY,
+ SCULPT_TOOL_DISPLACEMENT_SMEAR,
SCULPT_TOOL_DISPLACEMENT_ERASER) &&
(sd->gravity_factor > 0.0f));
/* Get gravity vector in world space. */
@@ -9160,7 +9311,7 @@ static int sculpt_sample_color_invoke(bContext *C,
static void SCULPT_OT_sample_color(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Sample color";
+ ot->name = "Sample Color";
ot->idname = "SCULPT_OT_sample_color";
ot->description = "Sample the vertex color of the active vertex";
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index cd8f609b598..1eab35ae0e5 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -119,6 +119,43 @@ static void cloth_brush_simulation_location_get(SculptSession *ss,
copy_v3_v3(r_location, ss->cache->location);
}
+PBVHNode **SCULPT_cloth_brush_affected_nodes_gather(SculptSession *ss,
+ Brush *brush,
+ int *r_totnode)
+{
+ BLI_assert(ss->cache);
+ BLI_assert(brush->sculpt_tool == SCULPT_TOOL_CLOTH);
+ PBVHNode **nodes = NULL;
+
+ switch (brush->cloth_simulation_area_type) {
+ case BRUSH_CLOTH_SIMULATION_AREA_LOCAL: {
+ SculptSearchSphereData data = {
+ .ss = ss,
+ .radius_squared = square_f(ss->cache->initial_radius * (1.0 + brush->cloth_sim_limit)),
+ .original = false,
+ .ignore_fully_ineffective = false,
+ .center = ss->cache->initial_location,
+ };
+ BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode);
+ } break;
+ case BRUSH_CLOTH_SIMULATION_AREA_GLOBAL:
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, r_totnode);
+ break;
+ case BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC: {
+ SculptSearchSphereData data = {
+ .ss = ss,
+ .radius_squared = square_f(ss->cache->radius * (1.0 + brush->cloth_sim_limit)),
+ .original = false,
+ .ignore_fully_ineffective = false,
+ .center = ss->cache->location,
+ };
+ BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode);
+ } break;
+ }
+
+ return nodes;
+}
+
static float cloth_brush_simulation_falloff_get(const Brush *brush,
const float radius,
const float location[3],
diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c
index c044fec0d7b..0ee8114aba2 100644
--- a/source/blender/editors/sculpt_paint/sculpt_detail.c
+++ b/source/blender/editors/sculpt_paint/sculpt_detail.c
@@ -363,7 +363,7 @@ void SCULPT_OT_sample_detail_size(wmOperatorType *ot)
0,
SHRT_MAX,
"Location",
- "Screen Coordinates of sampling",
+ "Screen coordinates of sampling",
0,
SHRT_MAX);
RNA_def_enum(ot->srna,
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c
index 4227c14df76..0a02f8b543b 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.c
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c
@@ -42,6 +42,7 @@
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_fair.h"
#include "BKE_mesh_mapping.h"
#include "BKE_multires.h"
#include "BKE_node.h"
@@ -1067,6 +1068,8 @@ typedef enum eSculptFaceSetEditMode {
SCULPT_FACE_SET_EDIT_GROW = 0,
SCULPT_FACE_SET_EDIT_SHRINK = 1,
SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY = 2,
+ SCULPT_FACE_SET_EDIT_FAIR_POSITIONS = 3,
+ SCULPT_FACE_SET_EDIT_FAIR_TANGENCY = 4,
} eSculptFaceSetEditMode;
static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = {
@@ -1091,6 +1094,22 @@ static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = {
"Delete Geometry",
"Deletes the faces that are assigned to the Face Set",
},
+ {
+ SCULPT_FACE_SET_EDIT_FAIR_POSITIONS,
+ "FAIR_POSITIONS",
+ 0,
+ "Fair Positions",
+ "Creates a smooth as possible geometry patch from the Face Set minimizing changes in "
+ "vertex positions",
+ },
+ {
+ SCULPT_FACE_SET_EDIT_FAIR_TANGENCY,
+ "FAIR_TANGENCY",
+ 0,
+ "Fair Tangency",
+ "Creates a smooth as possible geometry patch from the Face Set minimizing changes in "
+ "vertex tangents",
+ },
{0, NULL, 0, NULL, NULL},
};
@@ -1177,7 +1196,7 @@ static void sculpt_face_set_shrink(Object *ob,
const bool modify_hidden)
{
if (ss && ss->bm) {
- //XXX implement me
+ // XXX implement me
return;
}
@@ -1279,6 +1298,33 @@ static void sculpt_face_set_delete_geometry(Object *ob,
BM_mesh_free(bm);
}
+static void sculpt_face_set_edit_fair_face_set(Object *ob,
+ const int active_face_set_id,
+ const int fair_order)
+{
+ SculptSession *ss = ob->sculpt;
+
+ const int totvert = SCULPT_vertex_count_get(ss);
+
+ Mesh *mesh = ob->data;
+ bool *fair_vertices = MEM_malloc_arrayN(sizeof(bool), totvert, "fair vertices");
+
+ SCULPT_vertex_random_access_ensure(ss);
+ SCULPT_boundary_info_ensure(ob);
+
+ for (int i = 0; i < totvert; i++) {
+ SculptVertRef vref = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ fair_vertices[i] = !SCULPT_vertex_is_boundary(ss, vref) &&
+ SCULPT_vertex_has_face_set(ss, vref, active_face_set_id) &&
+ SCULPT_vertex_has_unique_face_set(ss, vref);
+ }
+
+ MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss);
+ BKE_mesh_prefair_and_fair_vertices(mesh, mvert, fair_vertices, fair_order);
+ MEM_freeN(fair_vertices);
+}
+
static void sculpt_face_set_apply_edit(Object *ob,
const int active_face_set_id,
const int mode,
@@ -1302,6 +1348,12 @@ static void sculpt_face_set_apply_edit(Object *ob,
case SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY:
sculpt_face_set_delete_geometry(ob, ss, active_face_set_id, modify_hidden);
break;
+ case SCULPT_FACE_SET_EDIT_FAIR_POSITIONS:
+ sculpt_face_set_edit_fair_face_set(ob, active_face_set_id, MESH_FAIRING_DEPTH_POSITION);
+ break;
+ case SCULPT_FACE_SET_EDIT_FAIR_TANGENCY:
+ sculpt_face_set_edit_fair_face_set(ob, active_face_set_id, MESH_FAIRING_DEPTH_TANGENCY);
+ break;
}
}
@@ -1328,6 +1380,16 @@ static bool sculpt_face_set_edit_is_operation_valid(SculptSession *ss,
return false;
}
}
+
+ if (ELEM(mode, SCULPT_FACE_SET_EDIT_FAIR_POSITIONS, SCULPT_FACE_SET_EDIT_FAIR_TANGENCY)) {
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
+ /* TODO: Multires topology representation using grids and duplicates can't be used directly
+ * by the fair algorithm. Multires topology needs to be exposed in a different way or
+ * converted to a mesh for this operation. */
+ return false;
+ }
+ }
+
return true;
}
@@ -1385,11 +1447,38 @@ static void sculpt_face_set_edit_modify_face_sets(Object *ob,
MEM_freeN(nodes);
}
+static void sculpt_face_set_edit_modify_coordinates(bContext *C,
+ Object *ob,
+ const int active_face_set,
+ const eSculptFaceSetEditMode mode)
+{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ SculptSession *ss = ob->sculpt;
+ PBVH *pbvh = ss->pbvh;
+ PBVHNode **nodes;
+ int totnode;
+ BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ SCULPT_undo_push_begin(ob, "face set edit");
+ for (int i = 0; i < totnode; i++) {
+ BKE_pbvh_node_mark_update(nodes[i]);
+ SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_COORDS);
+ }
+ sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, false);
+
+ if (ss->deform_modifiers_active || ss->shapekey_active) {
+ SCULPT_flush_stroke_deform(sd, ob, true);
+ }
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS);
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
+ SCULPT_undo_push_end();
+ MEM_freeN(nodes);
+}
+
static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
const int mode = RNA_enum_get(op->ptr, "mode");
const bool modify_hidden = RNA_boolean_get(op->ptr, "modify_hidden");
@@ -1418,6 +1507,10 @@ static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEven
case SCULPT_FACE_SET_EDIT_SHRINK:
sculpt_face_set_edit_modify_face_sets(ob, active_face_set, mode, modify_hidden);
break;
+ case SCULPT_FACE_SET_EDIT_FAIR_POSITIONS:
+ case SCULPT_FACE_SET_EDIT_FAIR_TANGENCY:
+ sculpt_face_set_edit_modify_coordinates(C, ob, active_face_set, mode);
+ break;
}
SCULPT_tag_update_overlays(C);
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
index ab910e3e0eb..38d2904e98a 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
@@ -328,9 +328,9 @@ void SCULPT_OT_color_filter(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* rna */
- RNA_def_enum(ot->srna, "type", prop_color_filter_types, COLOR_FILTER_HUE, "Filter type", "");
+ RNA_def_enum(ot->srna, "type", prop_color_filter_types, COLOR_FILTER_HUE, "Filter Type", "");
RNA_def_float(
- ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f);
+ ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f);
PropertyRNA *prop = RNA_def_float_color(
ot->srna, "fill_color", 3, NULL, 0.0f, FLT_MAX, "Fill Color", "", 0.0f, 1.0f);
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
index 92142625e7b..5ce5a862cbe 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
@@ -80,12 +80,12 @@ static EnumPropertyItem prop_mask_filter_types[] = {
{MASK_FILTER_CONTRAST_INCREASE,
"CONTRAST_INCREASE",
0,
- "Increase contrast",
+ "Increase Contrast",
"Increase the contrast of the paint mask"},
{MASK_FILTER_CONTRAST_DECREASE,
"CONTRAST_DECREASE",
0,
- "Decrease contrast",
+ "Decrease Contrast",
"Decrease the contrast of the paint mask"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index 0001c15a31d..b8b6ebae25f 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -778,15 +778,15 @@ void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
"type",
prop_mesh_filter_types,
MESH_FILTER_INFLATE,
- "Filter type",
+ "Filter Type",
"Operation that is going to be applied to the mesh");
RNA_def_float(
- ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f);
+ ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f);
RNA_def_enum_flag(ot->srna,
"deform_axis",
prop_mesh_filter_deform_axis_items,
MESH_FILTER_DEFORM_X | MESH_FILTER_DEFORM_Y | MESH_FILTER_DEFORM_Z,
- "Deform axis",
+ "Deform Axis",
"Apply the deformation in the selected axis");
RNA_def_enum(ot->srna,
"orientation",
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 57a0a47df97..7aef6f71154 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -39,7 +39,6 @@
struct AutomaskingCache;
struct KeyBlock;
struct Object;
-struct SculptPoseIKChainSegment;
struct SculptUndoNode;
struct bContext;
@@ -436,6 +435,10 @@ void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr,
const float outline_col[3],
float outline_alpha);
+PBVHNode **SCULPT_cloth_brush_affected_nodes_gather(SculptSession *ss,
+ Brush *brush,
+ int *r_totnode);
+
BLI_INLINE bool SCULPT_is_cloth_deform_brush(const Brush *brush)
{
return (brush->sculpt_tool == SCULPT_TOOL_CLOTH && ELEM(brush->cloth_deform_type,
@@ -447,6 +450,38 @@ BLI_INLINE bool SCULPT_is_cloth_deform_brush(const Brush *brush)
brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM);
}
+BLI_INLINE bool SCULPT_tool_needs_all_pbvh_nodes(const Brush *brush)
+{
+ if (brush->sculpt_tool == SCULPT_TOOL_ELASTIC_DEFORM) {
+ /* Elastic deformations in any brush need all nodes to avoid artifacts as the effect
+ * of the Kelvinlet is not constrained by the radius. */
+ return true;
+ }
+
+ if (brush->sculpt_tool == SCULPT_TOOL_POSE) {
+ /* Pose needs all nodes because it applies all symmetry iterations at the same time
+ * and the IK chain can grow to any area of the model. */
+ /* TODO: This can be optimized by filtering the nodes after calculating the chain. */
+ return true;
+ }
+
+ if (brush->sculpt_tool == SCULPT_TOOL_BOUNDARY) {
+ /* Boundary needs all nodes because it is not possible to know where the boundary
+ * deformation is going to be propagated before calculating it. */
+ /* TODO: after calculating the boundary info in the first iteration, it should be
+ * possible to get the nodes that have vertices included in any boundary deformation
+ * and cache them. */
+ return true;
+ }
+
+ if (brush->sculpt_tool == SCULPT_TOOL_SNAKE_HOOK &&
+ brush->snake_hook_deform_type == BRUSH_SNAKE_HOOK_DEFORM_ELASTIC) {
+ /* Snake hook in elastic deform type has same requirements as the elastic deform tool. */
+ return true;
+ }
+ return false;
+}
+
/* Pose Brush. */
void SCULPT_do_pose_brush(struct Sculpt *sd,
struct Object *ob,
@@ -912,6 +947,10 @@ typedef struct StrokeCache {
float (*prev_colors)[4];
+ /* Multires Displacement Smear. */
+ float (*prev_displacement)[3];
+ float (*limit_surface_co)[3];
+
/* The rest is temporary storage that isn't saved as a property */
bool first_time; /* Beginning of stroke may do some things special */
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index c6961cc9d4b..34617804888 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -52,7 +52,7 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-#include "SEQ_sequencer.h"
+#include "SEQ_iterator.h"
#include "UI_interface.h"
@@ -259,7 +259,7 @@ static void sound_update_animation_flags(Scene *scene)
scene->id.tag |= LIB_TAG_DOIT;
SEQ_ALL_BEGIN (scene->ed, seq) {
- BKE_sequencer_recursive_apply(seq, sound_update_animation_flags_fn, scene);
+ SEQ_iterator_recursive_apply(seq, sound_update_animation_flags_fn, scene);
}
SEQ_ALL_END;
@@ -518,27 +518,27 @@ static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr),
static void sound_mixdown_draw(bContext *C, wmOperator *op)
{
static const EnumPropertyItem pcm_format_items[] = {
- {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"},
- {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
+ {AUD_FORMAT_U8, "U8", 0, "U8", "8-bit unsigned"},
+ {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"},
# ifdef WITH_SNDFILE
- {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
+ {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"},
# endif
- {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
- {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"},
- {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"},
+ {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"},
+ {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32-bit floating-point"},
+ {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64-bit floating-point"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem mp3_format_items[] = {
- {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
- {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
+ {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"},
+ {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"},
{0, NULL, 0, NULL, NULL},
};
# ifdef WITH_SNDFILE
static const EnumPropertyItem flac_format_items[] = {
- {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
- {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
+ {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"},
+ {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"},
{0, NULL, 0, NULL, NULL},
};
# endif
@@ -672,12 +672,12 @@ static void SOUND_OT_mixdown(wmOperatorType *ot)
{
#ifdef WITH_AUDASPACE
static const EnumPropertyItem format_items[] = {
- {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"},
- {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
- {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
- {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
- {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"},
- {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"},
+ {AUD_FORMAT_U8, "U8", 0, "U8", "8-bit unsigned"},
+ {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"},
+ {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"},
+ {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"},
+ {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32-bit floating-point"},
+ {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64-bit floating-point"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index e20be9c8328..4d5a93f75e0 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -158,7 +158,78 @@ static void actedit_change_action(bContext *C, bAction *act)
RNA_property_update(C, &ptr, prop);
}
-/* ******************** New Action Operator *********************** */
+/* ******************** New Action Operators *********************** */
+
+static void action_creation_assign(bContext *C,
+ bAction *action,
+ PointerRNA *ptr,
+ PropertyRNA *prop)
+{
+ PointerRNA idptr;
+ /* Set the new action.
+ * NOTE: we can't use actedit_change_action, as this function is also called from the NLA. */
+ RNA_id_pointer_create(&action->id, &idptr);
+ RNA_property_pointer_set(ptr, prop, idptr, NULL);
+ RNA_property_update(C, ptr, prop);
+}
+
+/**
+ * Stash the previously active action to prevent it from being lost.
+ * \return The old action if any.
+ */
+static bAction *action_creation_stash_old(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
+{
+ bAction *oldact = NULL;
+ AnimData *adt = NULL;
+
+ if (prop) {
+ /* The operator was called from a button. */
+ PointerRNA oldptr;
+
+ oldptr = RNA_property_pointer_get(ptr, prop);
+ oldact = (bAction *)oldptr.owner_id;
+
+ /* stash the old action to prevent it from being lost */
+ if (ptr->type == &RNA_AnimData) {
+ adt = ptr->data;
+ }
+ else if (ptr->type == &RNA_SpaceDopeSheetEditor) {
+ adt = ED_actedit_animdata_from_context(C);
+ }
+ }
+ else {
+ adt = ED_actedit_animdata_from_context(C);
+ oldact = adt->action;
+ }
+
+ if (!adt || !oldact) {
+ /* Found nothing to stash in current context. */
+ return NULL;
+ }
+
+ /* Perform stashing operation. */
+ if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ptr->owner_id))) {
+ /* The stash operation will remove the user already
+ * (and unlink the action from the AnimData action slot).
+ * Hence, we must unset the ref to the action in the
+ * action editor too (if this is where we're being called from)
+ * first before setting the new action once it is created,
+ * or else the user gets decremented twice!
+ */
+ if (ptr->type == &RNA_SpaceDopeSheetEditor) {
+ SpaceAction *saction = ptr->data;
+ saction->action = NULL;
+ }
+ }
+ else {
+#if 0
+ printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n",
+ oldact->id.name);
+#endif
+ }
+
+ return oldact;
+}
/* Criteria:
* 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions...
@@ -207,71 +278,17 @@ static bool action_new_poll(bContext *C)
static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr, idptr;
+ PointerRNA ptr;
PropertyRNA *prop;
- bAction *oldact = NULL;
- AnimData *adt = NULL;
/* hook into UI */
UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
- if (prop) {
- /* The operator was called from a button. */
- PointerRNA oldptr;
-
- oldptr = RNA_property_pointer_get(&ptr, prop);
- oldact = (bAction *)oldptr.owner_id;
-
- /* stash the old action to prevent it from being lost */
- if (ptr.type == &RNA_AnimData) {
- adt = ptr.data;
- }
- else if (ptr.type == &RNA_SpaceDopeSheetEditor) {
- adt = ED_actedit_animdata_from_context(C);
- }
- }
- else {
- adt = ED_actedit_animdata_from_context(C);
- oldact = adt->action;
- }
- {
- bAction *action = NULL;
-
- /* Perform stashing operation - But only if there is an action */
- if (adt && oldact) {
- /* stash the action */
- if (BKE_nla_action_stash(adt)) {
- /* The stash operation will remove the user already
- * (and unlink the action from the AnimData action slot).
- * Hence, we must unset the ref to the action in the
- * action editor too (if this is where we're being called from)
- * first before setting the new action once it is created,
- * or else the user gets decremented twice!
- */
- if (ptr.type == &RNA_SpaceDopeSheetEditor) {
- SpaceAction *saction = ptr.data;
- saction->action = NULL;
- }
- }
- else {
-#if 0
- printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n",
- oldact->id.name);
-#endif
- }
- }
-
- /* create action */
- action = action_create_new(C, oldact);
+ action_creation_stash_old(C, &ptr, prop);
- if (prop) {
- /* set this new action
- * NOTE: we can't use actedit_change_action, as this function is also called from the NLA
- */
- RNA_id_pointer_create(&action->id, &idptr);
- RNA_property_pointer_set(&ptr, prop, idptr, NULL);
- RNA_property_update(C, &ptr, prop);
- }
+ bAction *action = action_create_new(C, NULL);
+ if (prop) {
+ action_creation_assign(C, action, &ptr, prop);
}
/* set notifier that keyframes have changed */
@@ -285,7 +302,7 @@ void ACTION_OT_new(wmOperatorType *ot)
/* identifiers */
ot->name = "New Action";
ot->idname = "ACTION_OT_new";
- ot->description = "Create new action";
+ ot->description = "Create a new action";
/* api callbacks */
ot->exec = action_new_exec;
@@ -295,6 +312,45 @@ void ACTION_OT_new(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+static int action_duplicate_assign_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ /* hook into UI */
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
+
+ bAction *old_action = action_creation_stash_old(C, &ptr, prop);
+
+ bAction *new_action = action_create_new(C, old_action);
+ if (prop) {
+ action_creation_assign(C, new_action, &ptr, prop);
+ }
+
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+/**
+ * Duplicate an action assigned to a templateID and update it's assignment - based on UI context.
+ */
+void ACTION_OT_duplicate_assign(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate & Assign Action";
+ ot->idname = "ACTION_OT_duplicate_assign";
+ ot->description = "Create a copy of an existing action and assign it";
+
+ /* api callbacks */
+ ot->exec = action_duplicate_assign_exec;
+ ot->poll = action_new_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
/* ******************* Action Push-Down Operator ******************** */
/* Criteria:
@@ -339,7 +395,8 @@ static int action_pushdown_exec(bContext *C, wmOperator *op)
}
/* action can be safely added */
- BKE_nla_action_pushdown(adt);
+ const Object *ob = CTX_data_active_object(C);
+ BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(ob));
/* Stop displaying this action in this editor
* NOTE: The editor itself doesn't set a user...
@@ -384,7 +441,8 @@ static int action_stash_exec(bContext *C, wmOperator *op)
}
/* stash the action */
- if (BKE_nla_action_stash(adt)) {
+ Object *ob = CTX_data_active_object(C);
+ if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ob))) {
/* The stash operation will remove the user already,
* so the flushing step later shouldn't double up
* the user-count fixes. Hence, we must unset this ref
@@ -486,7 +544,8 @@ static int action_stash_create_exec(bContext *C, wmOperator *op)
}
/* stash the action */
- if (BKE_nla_action_stash(adt)) {
+ Object *ob = CTX_data_active_object(C);
+ if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ob))) {
bAction *new_action = NULL;
/* Create new action not based on the old one
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index 167215b3813..d186cafb857 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -1827,7 +1827,7 @@ static const EnumPropertyItem prop_actkeys_mirror_types[] = {
{ACTKEYS_MIRROR_XAXIS,
"XAXIS",
0,
- "By Values Over Value=0",
+ "By Values Over Zero Value",
"Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"},
{ACTKEYS_MIRROR_MARKER,
"MARKER",
diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h
index ffe0606c98f..4bce6c62a1a 100644
--- a/source/blender/editors/space_action/action_intern.h
+++ b/source/blender/editors/space_action/action_intern.h
@@ -106,6 +106,7 @@ void ACTION_OT_snap(struct wmOperatorType *ot);
void ACTION_OT_mirror(struct wmOperatorType *ot);
void ACTION_OT_new(struct wmOperatorType *ot);
+void ACTION_OT_duplicate_assign(struct wmOperatorType *ot);
void ACTION_OT_unlink(struct wmOperatorType *ot);
void ACTION_OT_push_down(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c
index 7422c05511c..329c3a9f6f6 100644
--- a/source/blender/editors/space_action/action_ops.c
+++ b/source/blender/editors/space_action/action_ops.c
@@ -73,7 +73,9 @@ void action_operatortypes(void)
WM_operatortype_append(ACTION_OT_copy);
WM_operatortype_append(ACTION_OT_paste);
+ /* UI-context based operators. */
WM_operatortype_append(ACTION_OT_new);
+ WM_operatortype_append(ACTION_OT_duplicate_assign);
WM_operatortype_append(ACTION_OT_unlink);
WM_operatortype_append(ACTION_OT_push_down);
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index ab5f1e0ab22..98e39520e99 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -1325,8 +1325,8 @@ void ACTION_OT_select_less(wmOperatorType *ot)
/* defines for left-right select tool */
static const EnumPropertyItem prop_actkeys_leftright_select_types[] = {
{ACTKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
- {ACTKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
- {ACTKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
+ {ACTKEYS_LRSEL_LEFT, "LEFT", 0, "Before Current Frame", ""},
+ {ACTKEYS_LRSEL_RIGHT, "RIGHT", 0, "After Current Frame", ""},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 10ce7b81954..10fa2c19919 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -40,6 +40,7 @@
#include "ED_anim_api.h"
#include "ED_armature.h"
+#include "ED_asset.h"
#include "ED_clip.h"
#include "ED_curve.h"
#include "ED_fileselect.h"
@@ -64,6 +65,7 @@
#include "ED_space_api.h"
#include "ED_transform.h"
#include "ED_userpref.h"
+#include "ED_util.h"
#include "ED_uvedit.h"
#include "io_ops.h"
@@ -105,6 +107,7 @@ void ED_spacetypes_init(void)
ED_operatortypes_screen();
ED_operatortypes_anim();
ED_operatortypes_animchannels();
+ ED_operatortypes_asset();
ED_operatortypes_gpencil();
ED_operatortypes_object();
ED_operatortypes_lattice();
@@ -122,6 +125,7 @@ void ED_spacetypes_init(void)
ED_operatortypes_render();
ED_operatortypes_mask();
ED_operatortypes_io();
+ ED_operatortypes_edutils();
ED_operatortypes_view2d();
ED_operatortypes_ui();
diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt
index fa3e6a51036..c71e5e49d8d 100644
--- a/source/blender/editors/space_buttons/CMakeLists.txt
+++ b/source/blender/editors/space_buttons/CMakeLists.txt
@@ -51,6 +51,7 @@ endif()
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_GEOMETRY_NODES)
+ add_definitions(-DWITH_POINT_CLOUD)
add_definitions(-DWITH_HAIR_NODES)
endif()
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 8b39995a5c9..c1f29231f96 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -246,9 +246,11 @@ static bool buttons_context_path_data(ButsContextPath *path, int type)
return true;
}
#endif
+#ifdef WITH_POINT_CLOUD
if (RNA_struct_is_a(ptr->type, &RNA_PointCloud) && (type == -1 || type == OB_POINTCLOUD)) {
return true;
}
+#endif
if (RNA_struct_is_a(ptr->type, &RNA_Volume) && (type == -1 || type == OB_VOLUME)) {
return true;
}
@@ -812,7 +814,9 @@ const char *buttons_context_dir[] = {
#ifdef WITH_HAIR_NODES
"hair",
#endif
+#ifdef WITH_POINT_CLOUD
"pointcloud",
+#endif
"volume",
NULL,
};
@@ -822,6 +826,11 @@ int /*eContextResult*/ buttons_context(const bContext *C,
bContextDataResult *result)
{
SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ if (sbuts && sbuts->path == NULL) {
+ /* path is cleared for SCREEN_OT_redo_last, when global undo does a file-read which clears the
+ * path (see lib_link_workspace_layout_restore). */
+ buttons_context_compute(C, sbuts);
+ }
ButsContextPath *path = sbuts ? sbuts->path : NULL;
if (!path) {
@@ -899,10 +908,12 @@ int /*eContextResult*/ buttons_context(const bContext *C,
return CTX_RESULT_OK;
}
#endif
+#ifdef WITH_POINT_CLOUD
if (CTX_data_equals(member, "pointcloud")) {
set_pointer_type(path, result, &RNA_PointCloud);
return CTX_RESULT_OK;
}
+#endif
if (CTX_data_equals(member, "volume")) {
set_pointer_type(path, result, &RNA_Volume);
return CTX_RESULT_OK;
diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h
index 0a0846cf216..74e7bc11c26 100644
--- a/source/blender/editors/space_buttons/buttons_intern.h
+++ b/source/blender/editors/space_buttons/buttons_intern.h
@@ -35,7 +35,6 @@ struct bContext;
struct bContextDataResult;
struct bNode;
struct bNodeTree;
-struct uiLayout;
struct wmOperatorType;
struct SpaceProperties_Runtime {
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index 8bdc2ed993f..8f57abf83ae 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -338,7 +338,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
is_relative = BLI_path_is_rel(str);
}
- if (UNLIKELY(ptr.data == &U)) {
+ if (UNLIKELY(ptr.data == &U || is_userdef)) {
is_relative = false;
}
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index a95d0e3ea88..e0f603eb3d1 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -140,6 +140,7 @@ void uiTemplateMovieClip(
ptr,
propname,
NULL,
+ NULL,
"CLIP_OT_open",
NULL,
UI_TEMPLATE_ID_FILTER_ALL,
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 3f00e3114a5..8f36ccb019a 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -859,7 +859,7 @@ void CLIP_OT_view_zoom_out(wmOperatorType *ot)
-FLT_MAX,
FLT_MAX,
"Location",
- "Cursor location in normalized (0.0-1.0) coordinates",
+ "Cursor location in normalized (0.0 to 1.0) coordinates",
-10.0f,
10.0f);
RNA_def_property_flag(prop, PROP_HIDDEN);
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index a54faa41122..9b8e9e0e871 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -164,12 +164,12 @@ static bool id_drop_poll(bContext *UNUSED(C),
const wmEvent *UNUSED(event),
const char **UNUSED(tooltip))
{
- return WM_drag_ID(drag, 0) != NULL;
+ return WM_drag_get_local_ID(drag, 0) != NULL;
}
static void id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, 0);
+ ID *id = WM_drag_get_local_ID(drag, 0);
/* copy drag path to properties */
char *text = RNA_path_full_ID_py(G_MAIN, id);
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 4b277435f63..f2f7f9d82f9 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -25,6 +25,7 @@
#include <math.h>
#include <string.h>
+#include "BLI_alloca.h"
#include "BLI_blenlib.h"
#include "BLI_fileops_types.h"
#include "BLI_math.h"
@@ -134,6 +135,7 @@ static void draw_tile(int sx, int sy, int width, int height, int colorid, int sh
}
static void file_draw_icon(uiBlock *block,
+ const FileDirEntry *file,
const char *path,
int sx,
int sy,
@@ -157,8 +159,29 @@ static void file_draw_icon(uiBlock *block,
UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path));
if (drag) {
- /* path is no more static, cannot give it directly to but... */
- UI_but_drag_set_path(but, BLI_strdup(path), true);
+ /* TODO duplicated from file_draw_preview(). */
+ ID *id;
+
+ if ((id = filelist_file_get_id(file))) {
+ UI_but_drag_set_id(but, id);
+ }
+ else if (file->typeflag & FILE_TYPE_ASSET) {
+ ImBuf *preview_image = filelist_file_getimage(file);
+ char blend_path[FILE_MAX_LIBEXTRA];
+ if (BLO_library_path_explode(path, blend_path, NULL, NULL)) {
+ UI_but_drag_set_asset(but,
+ file->name,
+ BLI_strdup(blend_path),
+ file->blentype,
+ icon,
+ preview_image,
+ UI_DPI_FAC);
+ }
+ }
+ else {
+ /* path is no more static, cannot give it directly to but... */
+ UI_but_drag_set_path(but, BLI_strdup(path), true);
+ }
}
}
@@ -200,6 +223,65 @@ static void file_draw_string(int sx,
});
}
+/**
+ * \param r_sx, r_sy: The lower right corner of the last line drawn. AKA the cursor position on
+ * completion.
+ */
+static void file_draw_string_multiline(int sx,
+ int sy,
+ const char *string,
+ int wrap_width,
+ int line_height,
+ const uchar text_col[4],
+ int *r_sx,
+ int *r_sy)
+{
+ rcti rect;
+
+ if (string[0] == '\0' || wrap_width < 1) {
+ return;
+ }
+
+ const uiStyle *style = UI_style_get();
+ int font_id = style->widgetlabel.uifont_id;
+ int len = strlen(string);
+
+ rctf textbox;
+ BLF_wordwrap(font_id, wrap_width);
+ BLF_enable(font_id, BLF_WORD_WRAP);
+ BLF_boundbox(font_id, string, len, &textbox);
+ BLF_disable(font_id, BLF_WORD_WRAP);
+
+ /* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict
+ * (for buttons it works) */
+ rect.xmin = sx;
+ rect.xmax = sx + wrap_width;
+ /* Need to increase the clipping rect by one more line, since the #UI_fontstyle_draw_ex() will
+ * actually start drawing at (ymax - line-height). */
+ rect.ymin = sy - round_fl_to_int(BLI_rctf_size_y(&textbox)) - line_height;
+ rect.ymax = sy;
+
+ struct ResultBLF result;
+ UI_fontstyle_draw_ex(&style->widget,
+ &rect,
+ string,
+ text_col,
+ &(struct uiFontStyleDraw_Params){
+ .align = UI_STYLE_TEXT_LEFT,
+ .word_wrap = true,
+ },
+ len,
+ NULL,
+ NULL,
+ &result);
+ if (r_sx) {
+ *r_sx = result.width;
+ }
+ if (r_sy) {
+ *r_sy = rect.ymin + line_height;
+ }
+}
+
void file_calc_previews(const bContext *C, ARegion *region)
{
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -210,6 +292,7 @@ void file_calc_previews(const bContext *C, ARegion *region)
}
static void file_draw_preview(uiBlock *block,
+ const FileDirEntry *file,
const char *path,
int sx,
int sy,
@@ -218,7 +301,6 @@ static void file_draw_preview(uiBlock *block,
const int icon,
FileLayout *layout,
const bool is_icon,
- const int typeflags,
const bool drag,
const bool dimmed,
const bool is_link)
@@ -232,7 +314,7 @@ static void file_draw_preview(uiBlock *block,
float scale;
int ex, ey;
bool show_outline = !is_icon &&
- (typeflags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_BLENDER));
+ (file->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_BLENDER));
BLI_assert(imb != NULL);
@@ -273,14 +355,14 @@ static void file_draw_preview(uiBlock *block,
float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
if (is_icon) {
- if (typeflags & FILE_TYPE_DIR) {
+ if (file->typeflag & FILE_TYPE_DIR) {
UI_GetThemeColor4fv(TH_ICON_FOLDER, col);
}
else {
UI_GetThemeColor4fv(TH_TEXT, col);
}
}
- else if (typeflags & FILE_TYPE_FTFONT) {
+ else if (file->typeflag & FILE_TYPE_FTFONT) {
UI_GetThemeColor4fv(TH_TEXT, col);
}
@@ -288,7 +370,7 @@ static void file_draw_preview(uiBlock *block,
col[3] *= 0.3f;
}
- if (!is_icon && typeflags & FILE_TYPE_BLENDERLIB) {
+ if (!is_icon && file->typeflag & FILE_TYPE_BLENDERLIB) {
/* Datablock preview images use premultiplied alpha. */
GPU_blend(GPU_BLEND_ALPHA_PREMULT);
}
@@ -324,7 +406,7 @@ static void file_draw_preview(uiBlock *block,
icon_color[2] = 255;
}
icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f);
- icon_y = yco + (ey / 2.0f) - (icon_size * ((typeflags & FILE_TYPE_DIR) ? 0.78f : 0.75f));
+ icon_y = yco + (ey / 2.0f) - (icon_size * ((file->typeflag & FILE_TYPE_DIR) ? 0.78f : 0.75f));
UI_icon_draw_ex(
icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false);
}
@@ -346,13 +428,13 @@ static void file_draw_preview(uiBlock *block,
/* Link to folder or non-previewed file. */
uchar icon_color[4];
UI_GetThemeColor4ubv(TH_BACK, icon_color);
- icon_x = xco + ((typeflags & FILE_TYPE_DIR) ? 0.14f : 0.23f) * scaledx;
- icon_y = yco + ((typeflags & FILE_TYPE_DIR) ? 0.24f : 0.14f) * scaledy;
+ icon_x = xco + ((file->typeflag & FILE_TYPE_DIR) ? 0.14f : 0.23f) * scaledx;
+ icon_y = yco + ((file->typeflag & FILE_TYPE_DIR) ? 0.24f : 0.14f) * scaledy;
UI_icon_draw_ex(
icon_x, icon_y, arrow, icon_aspect / U.dpi_fac * 1.8, 0.3f, 0.0f, icon_color, false);
}
}
- else if (icon && !is_icon && !(typeflags & FILE_TYPE_FTFONT)) {
+ else if (icon && !is_icon && !(file->typeflag & FILE_TYPE_FTFONT)) {
/* Smaller, fainter icon at bottom-left for preview image thumbnail, but not for fonts. */
float icon_x, icon_y;
const uchar dark[4] = {0, 0, 0, 255};
@@ -385,8 +467,22 @@ static void file_draw_preview(uiBlock *block,
/* dragregion */
if (drag) {
+ ID *id;
+
+ if ((id = filelist_file_get_id(file))) {
+ UI_but_drag_set_id(but, id);
+ }
/* path is no more static, cannot give it directly to but... */
- UI_but_drag_set_image(but, BLI_strdup(path), icon, imb, scale, true);
+ else if (file->typeflag & FILE_TYPE_ASSET) {
+ char blend_path[FILE_MAX_LIBEXTRA];
+ if (BLO_library_path_explode(path, blend_path, NULL, NULL)) {
+ UI_but_drag_set_asset(
+ but, file->name, BLI_strdup(blend_path), file->blentype, icon, imb, scale);
+ }
+ }
+ else {
+ UI_but_drag_set_image(but, BLI_strdup(path), icon, imb, scale, true);
+ }
}
GPU_blend(GPU_BLEND_NONE);
@@ -400,11 +496,12 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
ARegion *region = CTX_wm_region(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
- BLI_join_dirfile(orgname, sizeof(orgname), sfile->params->dir, oldname);
- BLI_strncpy(filename, sfile->params->renamefile, sizeof(filename));
+ BLI_join_dirfile(orgname, sizeof(orgname), params->dir, oldname);
+ BLI_strncpy(filename, params->renamefile, sizeof(filename));
BLI_filename_make_safe(filename);
- BLI_join_dirfile(newname, sizeof(newname), sfile->params->dir, filename);
+ BLI_join_dirfile(newname, sizeof(newname), params->dir, filename);
if (!STREQ(orgname, newname)) {
if (!BLI_exists(newname)) {
@@ -415,8 +512,8 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
}
else {
/* If rename is successful, scroll to newly renamed entry. */
- BLI_strncpy(sfile->params->renamefile, filename, sizeof(sfile->params->renamefile));
- sfile->params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING;
+ BLI_strncpy(params->renamefile, filename, sizeof(params->renamefile));
+ params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING;
if (sfile->smoothscroll_timer != NULL) {
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
@@ -688,7 +785,7 @@ static void draw_details_columns(const FileSelectParams *params,
void file_draw_list(const bContext *C, ARegion *region)
{
SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
FileLayout *layout = ED_fileselect_get_layout(sfile, region);
View2D *v2d = &region->v2d;
struct FileList *files = sfile->files;
@@ -820,6 +917,7 @@ void file_draw_list(const bContext *C, ARegion *region)
}
file_draw_preview(block,
+ file,
path,
sx,
sy,
@@ -828,13 +926,13 @@ void file_draw_list(const bContext *C, ARegion *region)
icon,
layout,
is_icon,
- file->typeflag,
do_drag,
is_hidden,
is_link);
}
else {
file_draw_icon(block,
+ file,
path,
sx,
sy - layout->tile_border_y,
@@ -847,26 +945,25 @@ void file_draw_list(const bContext *C, ARegion *region)
}
if (file_selflag & FILE_SEL_EDITING) {
- uiBut *but;
const short width = (params->display == FILE_IMGDISPLAY) ?
textwidth :
layout->attribute_columns[COLUMN_NAME].width -
ATTRIBUTE_COLUMN_PADDING;
- but = uiDefBut(block,
- UI_BTYPE_TEXT,
- 1,
- "",
- sx + icon_ofs,
- sy - layout->tile_h - 0.15f * UI_UNIT_X,
- width - icon_ofs,
- textheight,
- sfile->params->renamefile,
- 1.0f,
- (float)sizeof(sfile->params->renamefile),
- 0,
- 0,
- "");
+ uiBut *but = uiDefBut(block,
+ UI_BTYPE_TEXT,
+ 1,
+ "",
+ sx + icon_ofs,
+ sy - layout->tile_h - 0.15f * UI_UNIT_X,
+ width - icon_ofs,
+ textheight,
+ params->renamefile,
+ 1.0f,
+ (float)sizeof(params->renamefile),
+ 0,
+ 0,
+ "");
UI_but_func_rename_set(but, renamebutton_cb, file);
UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* allow non utf8 names */
UI_but_flag_disable(but, UI_BUT_UNDO);
@@ -906,3 +1003,66 @@ void file_draw_list(const bContext *C, ARegion *region)
layout->curr_size = params->thumbnail_size;
}
+
+static void file_draw_invalid_library_hint(const SpaceFile *sfile, const ARegion *region)
+{
+ const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
+
+ char library_ui_path[PATH_MAX];
+ file_path_to_ui_path(asset_params->base_params.dir, library_ui_path, sizeof(library_ui_path));
+
+ uchar text_col[4];
+ uchar text_alert_col[4];
+ UI_GetThemeColor4ubv(TH_TEXT, text_col);
+ UI_GetThemeColor4ubv(TH_REDALERT, text_alert_col);
+
+ const View2D *v2d = &region->v2d;
+ const int pad = sfile->layout->tile_border_x;
+ const int width = BLI_rctf_size_x(&v2d->tot) - (2 * pad);
+ const int line_height = sfile->layout->textheight;
+ int sx = v2d->tot.xmin + pad;
+ /* For some reason no padding needed. */
+ int sy = v2d->tot.ymax;
+
+ {
+ const char *message = TIP_("Library not found");
+ const int draw_string_str_len = strlen(message) + 2 + sizeof(library_ui_path);
+ char *draw_string = alloca(draw_string_str_len);
+ BLI_snprintf(draw_string, draw_string_str_len, "%s: %s", message, library_ui_path);
+ file_draw_string_multiline(sx, sy, draw_string, width, line_height, text_alert_col, NULL, &sy);
+ }
+
+ /* Next line, but separate it a bit further. */
+ sy -= line_height;
+
+ {
+ UI_icon_draw(sx, sy - UI_UNIT_Y, ICON_INFO);
+
+ const char *suggestion = TIP_(
+ "Set up the library or edit libraries in the Preferences, File Paths section.");
+ file_draw_string_multiline(
+ sx + UI_UNIT_X, sy, suggestion, width - UI_UNIT_X, line_height, text_col, NULL, NULL);
+ }
+}
+
+/**
+ * Draw a string hint if the file list is invalid.
+ * \return true if the list is invalid and a hint was drawn.
+ */
+bool file_draw_hint_if_invalid(const SpaceFile *sfile, const ARegion *region)
+{
+ FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
+ /* Only for asset browser. */
+ if (!ED_fileselect_is_asset_browser(sfile)) {
+ return false;
+ }
+ /* Check if the library exists. */
+ if ((asset_params->asset_library.type == FILE_ASSET_LIBRARY_LOCAL) ||
+ filelist_is_dir(sfile->files, asset_params->base_params.dir)) {
+ return false;
+ }
+
+ file_draw_invalid_library_hint(sfile, region);
+
+ return true;
+}
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index b459c02d9e5..56fb588776e 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -38,6 +38,7 @@ struct View2D;
void file_calc_previews(const bContext *C, ARegion *region);
void file_draw_list(const bContext *C, ARegion *region);
+bool file_draw_hint_if_invalid(const SpaceFile *sfile, const ARegion *region);
void file_draw_check_ex(bContext *C, struct ScrArea *area);
void file_draw_check(bContext *C);
@@ -90,6 +91,7 @@ void file_sfile_to_operator(struct Main *bmain, struct wmOperator *op, struct Sp
void file_operator_to_sfile(struct Main *bmain, struct SpaceFile *sfile, struct wmOperator *op);
/* filesel.c */
+void fileselect_refresh_params(struct SpaceFile *sfile);
void fileselect_file_set(SpaceFile *sfile, const int index);
bool file_attribute_column_type_enabled(const FileSelectParams *params,
FileAttributeColumnType column);
@@ -116,3 +118,5 @@ void file_execute_region_panels_register(struct ARegionType *art);
/* file_utils.c */
void file_tile_boundbox(const ARegion *region, FileLayout *layout, const int file, rcti *r_bounds);
+
+void file_path_to_ui_path(const char *path, char *r_pathi, int max_size);
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 93367ad3d3c..88dd82bb9ea 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -40,6 +40,7 @@
# include "BLI_winstuff.h"
#endif
+#include "ED_asset.h"
#include "ED_fileselect.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
@@ -188,7 +189,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
Main *bmain = CTX_data_main(C);
FileSelect retval = FILE_SELECT_NOTHING;
SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
int numfiles = filelist_files_ensure(sfile->files);
const FileDirEntry *file;
@@ -302,10 +303,10 @@ static FileSelect file_select(
bContext *C, const rcti *rect, FileSelType select, bool fill, bool do_diropen)
{
SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
FileSelect retval = FILE_SELECT_NOTHING;
FileSelection sel = file_selection_get(C, rect, fill); /* get the selection */
- const FileCheckType check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS :
- CHECK_ALL;
+ const FileCheckType check_type = (params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_ALL;
/* flag the files as selected in the filelist */
filelist_entries_select_index_range_set(
@@ -325,7 +326,7 @@ static FileSelect file_select(
}
if (select != FILE_SEL_ADD && !file_is_any_selected(sfile->files)) {
- sfile->params->active_file = -1;
+ params->active_file = -1;
}
else if (sel.last >= 0) {
ARegion *region = CTX_wm_region(C);
@@ -390,7 +391,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve
{
ARegion *region = CTX_wm_region(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
FileSelection sel;
rcti rect;
@@ -521,8 +522,9 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
- if (sfile && sfile->params) {
- int idx = sfile->params->highlight_file;
+ const FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+ if (sfile && params) {
+ int idx = params->highlight_file;
int numfiles = filelist_files_ensure(sfile->files);
if ((idx >= 0) && (idx < numfiles)) {
@@ -613,7 +615,7 @@ static bool file_walk_select_selection_set(wmWindow *win,
const bool extend,
const bool fill)
{
- FileSelectParams *params = sfile->params;
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
struct FileList *files = sfile->files;
const int last_sel = params->active_file; /* store old value */
int active = active_old; /* could use active_old instead, just for readability */
@@ -804,7 +806,7 @@ static bool file_walk_select_do(bContext *C,
static int file_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
- FileSelectParams *params = sfile->params;
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
const int direction = RNA_enum_get(op->ptr, "direction");
const bool extend = RNA_boolean_get(op->ptr, "extend");
const bool fill = RNA_boolean_get(op->ptr, "fill");
@@ -853,6 +855,7 @@ static int file_select_all_exec(bContext *C, wmOperator *op)
{
ScrArea *area = CTX_wm_area(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
FileSelection sel;
const int numfiles = filelist_files_ensure(sfile->files);
int action = RNA_enum_get(op->ptr, "action");
@@ -870,7 +873,7 @@ static int file_select_all_exec(bContext *C, wmOperator *op)
switch (action) {
case SEL_SELECT:
case SEL_INVERT: {
- check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_FILES;
+ check_type = (params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_FILES;
filesel_type = (action == SEL_INVERT) ? FILE_SEL_TOGGLE : FILE_SEL_ADD;
break;
}
@@ -888,11 +891,11 @@ static int file_select_all_exec(bContext *C, wmOperator *op)
filelist_entries_select_index_range_set(
sfile->files, &sel, filesel_type, FILE_SEL_SELECTED, check_type);
- sfile->params->active_file = -1;
+ params->active_file = -1;
if (action != SEL_DESELECT) {
for (int i = 0; i < numfiles; i++) {
if (filelist_entry_select_index_get(sfile->files, i, check_type)) {
- sfile->params->active_file = i;
+ params->active_file = i;
break;
}
}
@@ -928,6 +931,7 @@ void FILE_OT_select_all(wmOperatorType *ot)
/* Note we could get rid of this one, but it's used by some addon so...
* Does not hurt keeping it around for now. */
+/* TODO disallow bookmark editing in assets mode? */
static int bookmark_select_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -935,8 +939,8 @@ static int bookmark_select_exec(bContext *C, wmOperator *op)
PropertyRNA *prop;
if ((prop = RNA_struct_find_property(op->ptr, "dir"))) {
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
char entry[256];
- FileSelectParams *params = sfile->params;
RNA_property_string_get(op->ptr, prop, entry);
BLI_strncpy(params->dir, entry, sizeof(params->dir));
@@ -963,7 +967,7 @@ void FILE_OT_select_bookmark(wmOperatorType *ot)
ot->poll = ED_operator_file_active;
/* properties */
- prop = RNA_def_string(ot->srna, "dir", NULL, FILE_MAXDIR, "Dir", "");
+ prop = RNA_def_string(ot->srna, "dir", NULL, FILE_MAXDIR, "Directory", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
@@ -978,7 +982,7 @@ static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op))
ScrArea *area = CTX_wm_area(C);
SpaceFile *sfile = CTX_wm_space_file(C);
struct FSMenu *fsmenu = ED_fsmenu_get();
- struct FileSelectParams *params = ED_fileselect_get_params(sfile);
+ struct FileSelectParams *params = ED_fileselect_get_active_params(sfile);
if (params->dir[0] != '\0') {
char name[FILE_MAX];
@@ -1274,7 +1278,7 @@ int file_highlight_set(SpaceFile *sfile, ARegion *region, int mx, int my)
}
numfiles = filelist_files_ensure(sfile->files);
- params = ED_fileselect_get_params(sfile);
+ params = ED_fileselect_get_active_params(sfile);
origfile = params->highlight_file;
@@ -1345,20 +1349,21 @@ static int file_column_sort_ui_context_invoke(bContext *C,
if (file_attribute_column_header_is_inside(
&region->v2d, sfile->layout, event->mval[0], event->mval[1])) {
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
const FileAttributeColumnType column_type = file_attribute_column_type_find_isect(
- &region->v2d, sfile->params, sfile->layout, event->mval[0]);
+ &region->v2d, params, sfile->layout, event->mval[0]);
if (column_type != COLUMN_NONE) {
const FileAttributeColumn *column = &sfile->layout->attribute_columns[column_type];
BLI_assert(column->sort_type != FILE_SORT_DEFAULT);
- if (sfile->params->sort == column->sort_type) {
+ if (params->sort == column->sort_type) {
/* Already sorting by selected column -> toggle sort invert (three state logic). */
- sfile->params->flag ^= FILE_SORT_INVERT;
+ params->flag ^= FILE_SORT_INVERT;
}
else {
- sfile->params->sort = column->sort_type;
- sfile->params->flag &= ~FILE_SORT_INVERT;
+ params->sort = column->sort_type;
+ params->flag &= ~FILE_SORT_INVERT;
}
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
@@ -1433,10 +1438,11 @@ void FILE_OT_cancel(struct wmOperatorType *ot)
void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, char *filepath)
{
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
PropertyRNA *prop;
/* XXX, not real length */
- BLI_join_dirfile(filepath, FILE_MAX, sfile->params->dir, sfile->params->file);
+ BLI_join_dirfile(filepath, FILE_MAX, params->dir, params->file);
if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) {
if (RNA_property_boolean_get(op->ptr, prop)) {
@@ -1445,10 +1451,10 @@ void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, ch
}
if ((prop = RNA_struct_find_property(op->ptr, "filename"))) {
- RNA_property_string_set(op->ptr, prop, sfile->params->file);
+ RNA_property_string_set(op->ptr, prop, params->file);
}
if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
- RNA_property_string_set(op->ptr, prop, sfile->params->dir);
+ RNA_property_string_set(op->ptr, prop, params->dir);
}
if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
RNA_property_string_set(op->ptr, prop, filepath);
@@ -1479,7 +1485,7 @@ void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, ch
* files selected */
if (0 == num_files) {
RNA_property_collection_add(op->ptr, prop, &itemptr);
- RNA_string_set(&itemptr, "name", sfile->params->file);
+ RNA_string_set(&itemptr, "name", params->file);
}
}
@@ -1500,7 +1506,7 @@ void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, ch
* directory selected */
if (0 == num_dirs) {
RNA_property_collection_add(op->ptr, prop, &itemptr);
- RNA_string_set(&itemptr, "name", sfile->params->dir);
+ RNA_string_set(&itemptr, "name", params->dir);
}
}
}
@@ -1514,30 +1520,28 @@ void file_sfile_to_operator(Main *bmain, wmOperator *op, SpaceFile *sfile)
void file_operator_to_sfile(Main *bmain, SpaceFile *sfile, wmOperator *op)
{
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
PropertyRNA *prop;
/* If neither of the above are set, split the filepath back */
if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
char filepath[FILE_MAX];
RNA_property_string_get(op->ptr, prop, filepath);
- BLI_split_dirfile(filepath,
- sfile->params->dir,
- sfile->params->file,
- sizeof(sfile->params->dir),
- sizeof(sfile->params->file));
+ BLI_split_dirfile(
+ filepath, params->dir, params->file, sizeof(params->dir), sizeof(params->file));
}
else {
if ((prop = RNA_struct_find_property(op->ptr, "filename"))) {
- RNA_property_string_get(op->ptr, prop, sfile->params->file);
+ RNA_property_string_get(op->ptr, prop, params->file);
}
if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
- RNA_property_string_get(op->ptr, prop, sfile->params->dir);
+ RNA_property_string_get(op->ptr, prop, params->dir);
}
}
/* we could check for relative_path property which is used when converting
* in the other direction but doesn't hurt to do this every time */
- BLI_path_abs(sfile->params->dir, BKE_main_blendfile_path(bmain));
+ BLI_path_abs(params->dir, BKE_main_blendfile_path(bmain));
/* XXX, files and dirs updates missing, not really so important though */
}
@@ -1547,21 +1551,19 @@ void file_operator_to_sfile(Main *bmain, SpaceFile *sfile, wmOperator *op)
*/
void file_sfile_filepath_set(SpaceFile *sfile, const char *filepath)
{
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
BLI_assert(BLI_exists(filepath));
if (BLI_is_dir(filepath)) {
- BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir));
+ BLI_strncpy(params->dir, filepath, sizeof(params->dir));
}
else {
- if ((sfile->params->flag & FILE_DIRSEL_ONLY) == 0) {
- BLI_split_dirfile(filepath,
- sfile->params->dir,
- sfile->params->file,
- sizeof(sfile->params->dir),
- sizeof(sfile->params->file));
+ if ((params->flag & FILE_DIRSEL_ONLY) == 0) {
+ BLI_split_dirfile(
+ filepath, params->dir, params->file, sizeof(params->dir), sizeof(params->file));
}
else {
- BLI_split_dir_part(filepath, sfile->params->dir, sizeof(sfile->params->dir));
+ BLI_split_dir_part(filepath, params->dir, sizeof(params->dir));
}
}
}
@@ -1605,9 +1607,10 @@ void file_draw_check_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
bool file_draw_check_exists(SpaceFile *sfile)
{
if (sfile->op) { /* fails on reload */
- if (sfile->params && (sfile->params->flag & FILE_CHECK_EXISTING)) {
+ const FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+ if (params && (params->flag & FILE_CHECK_EXISTING)) {
char filepath[FILE_MAX];
- BLI_join_dirfile(filepath, sizeof(filepath), sfile->params->dir, sfile->params->file);
+ BLI_join_dirfile(filepath, sizeof(filepath), params->dir, params->file);
if (BLI_is_file(filepath)) {
return true;
}
@@ -1628,21 +1631,22 @@ static int file_exec(bContext *C, wmOperator *exec_op)
Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- struct FileDirEntry *file = filelist_file(sfile->files, sfile->params->active_file);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+ struct FileDirEntry *file = filelist_file(sfile->files, params->active_file);
char filepath[FILE_MAX];
if (file && file->redirection_path) {
/* redirection_path is an absolute path that takes precedence
- * over using sfile->params->dir + sfile->params->file. */
+ * over using params->dir + params->file. */
BLI_split_dirfile(file->redirection_path,
- sfile->params->dir,
- sfile->params->file,
- sizeof(sfile->params->dir),
- sizeof(sfile->params->file));
+ params->dir,
+ params->file,
+ sizeof(params->dir),
+ sizeof(params->file));
/* Update relpath with redirected filename as well so that the alternative
- * combination of sfile->params->dir + relpath remains valid as well. */
+ * combination of params->dir + relpath remains valid as well. */
MEM_freeN(file->relpath);
- file->relpath = BLI_strdup(sfile->params->file);
+ file->relpath = BLI_strdup(params->file);
}
/* directory change */
@@ -1652,12 +1656,12 @@ static int file_exec(bContext *C, wmOperator *exec_op)
}
if (FILENAME_IS_PARENT(file->relpath)) {
- BLI_path_parent_dir(sfile->params->dir);
+ BLI_path_parent_dir(params->dir);
}
else {
- BLI_path_normalize(BKE_main_blendfile_path(bmain), sfile->params->dir);
- BLI_path_append(sfile->params->dir, sizeof(sfile->params->dir) - 1, file->relpath);
- BLI_path_slash_ensure(sfile->params->dir);
+ BLI_path_normalize(BKE_main_blendfile_path(bmain), params->dir);
+ BLI_path_append(params->dir, sizeof(params->dir) - 1, file->relpath);
+ BLI_path_slash_ensure(params->dir);
}
ED_file_change_dir(C);
}
@@ -1685,10 +1689,10 @@ static int file_exec(bContext *C, wmOperator *exec_op)
file_sfile_to_operator_ex(bmain, op, sfile, filepath);
- if (BLI_exists(sfile->params->dir)) {
+ if (BLI_exists(params->dir)) {
fsmenu_insert_entry(ED_fsmenu_get(),
FS_CATEGORY_RECENT,
- sfile->params->dir,
+ params->dir,
NULL,
ICON_FILE_FOLDER,
FS_INSERT_SAVE | FS_INSERT_FIRST);
@@ -1792,15 +1796,16 @@ static int file_parent_exec(bContext *C, wmOperator *UNUSED(unused))
{
Main *bmain = CTX_data_main(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
- if (sfile->params) {
- if (BLI_path_parent_dir(sfile->params->dir)) {
- BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), sfile->params->dir);
+ if (params) {
+ if (BLI_path_parent_dir(params->dir)) {
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir);
ED_file_change_dir(C);
- if (sfile->params->recursion_level > 1) {
+ if (params->recursion_level > 1) {
/* Disable 'dirtree' recursion when going up in tree. */
- sfile->params->recursion_level = 0;
- filelist_setrecursion(sfile->files, sfile->params->recursion_level);
+ params->recursion_level = 0;
+ filelist_setrecursion(sfile->files, params->recursion_level);
}
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
@@ -1830,15 +1835,12 @@ void FILE_OT_parent(struct wmOperatorType *ot)
static int file_previous_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
- if (sfile->params) {
- if (!sfile->folders_next) {
- sfile->folders_next = folderlist_new();
- }
-
- folderlist_pushdir(sfile->folders_next, sfile->params->dir);
- folderlist_popdir(sfile->folders_prev, sfile->params->dir);
- folderlist_pushdir(sfile->folders_next, sfile->params->dir);
+ if (params) {
+ folderlist_pushdir(sfile->folders_next, params->dir);
+ folderlist_popdir(sfile->folders_prev, params->dir);
+ folderlist_pushdir(sfile->folders_next, params->dir);
ED_file_change_dir(C);
}
@@ -1868,16 +1870,13 @@ void FILE_OT_previous(struct wmOperatorType *ot)
static int file_next_exec(bContext *C, wmOperator *UNUSED(unused))
{
SpaceFile *sfile = CTX_wm_space_file(C);
- if (sfile->params) {
- if (!sfile->folders_next) {
- sfile->folders_next = folderlist_new();
- }
-
- folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
- folderlist_popdir(sfile->folders_next, sfile->params->dir);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+ if (params) {
+ folderlist_pushdir(sfile->folders_prev, params->dir);
+ folderlist_popdir(sfile->folders_next, params->dir);
/* update folders_prev so we can check for it in #folderlist_clear_next() */
- folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
+ folderlist_pushdir(sfile->folders_prev, params->dir);
ED_file_change_dir(C);
}
@@ -1923,7 +1922,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
/* Due to async nature of file listing, we may execute this code before `file_refresh()`
* editing entry is available in our listing,
* so we also have to handle switching to rename mode here. */
- FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
if ((params->rename_flag &
(FILE_PARAMS_RENAME_PENDING | FILE_PARAMS_RENAME_POSTSCROLL_PENDING)) != 0) {
file_params_renamefile_activate(sfile, params);
@@ -2175,9 +2174,10 @@ static int file_directory_new_exec(bContext *C, wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
const bool do_diropen = RNA_boolean_get(op->ptr, "open");
- if (!sfile->params) {
+ if (!params) {
BKE_report(op->reports, RPT_WARNING, "No parent directory given");
return OPERATOR_CANCELLED;
}
@@ -2193,7 +2193,7 @@ static int file_directory_new_exec(bContext *C, wmOperator *op)
if (generate_name) {
/* create a new, non-existing folder name */
- if (!new_folder_path(sfile->params->dir, path, name)) {
+ if (!new_folder_path(params->dir, path, name)) {
BKE_report(op->reports, RPT_ERROR, "Could not create new folder name");
return OPERATOR_CANCELLED;
}
@@ -2226,8 +2226,8 @@ static int file_directory_new_exec(bContext *C, wmOperator *op)
/* If we don't enter the directory directly, remember file to jump into editing. */
if (do_diropen == false) {
- BLI_strncpy(sfile->params->renamefile, name, FILE_MAXFILE);
- sfile->params->rename_flag = FILE_PARAMS_RENAME_PENDING;
+ BLI_strncpy(params->renamefile, name, FILE_MAXFILE);
+ params->rename_flag = FILE_PARAMS_RENAME_PENDING;
}
/* set timer to smoothly view newly generated file */
@@ -2242,7 +2242,7 @@ static int file_directory_new_exec(bContext *C, wmOperator *op)
ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
if (do_diropen) {
- BLI_strncpy(sfile->params->dir, path, sizeof(sfile->params->dir));
+ BLI_strncpy(params->dir, path, sizeof(params->dir));
ED_file_change_dir(C);
}
@@ -2284,38 +2284,37 @@ static void file_expand_directory(bContext *C)
{
Main *bmain = CTX_data_main(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
- if (sfile->params) {
- if (BLI_path_is_rel(sfile->params->dir)) {
+ if (params) {
+ if (BLI_path_is_rel(params->dir)) {
/* Use of 'default' folder here is just to avoid an error message on '//' prefix. */
- BLI_path_abs(sfile->params->dir,
+ BLI_path_abs(params->dir,
G.relbase_valid ? BKE_main_blendfile_path(bmain) : BKE_appdir_folder_default());
}
- else if (sfile->params->dir[0] == '~') {
- char tmpstr[sizeof(sfile->params->dir) - 1];
- BLI_strncpy(tmpstr, sfile->params->dir + 1, sizeof(tmpstr));
- BLI_join_dirfile(
- sfile->params->dir, sizeof(sfile->params->dir), BKE_appdir_folder_default(), tmpstr);
+ else if (params->dir[0] == '~') {
+ char tmpstr[sizeof(params->dir) - 1];
+ BLI_strncpy(tmpstr, params->dir + 1, sizeof(tmpstr));
+ BLI_join_dirfile(params->dir, sizeof(params->dir), BKE_appdir_folder_default(), tmpstr);
}
- else if (sfile->params->dir[0] == '\0')
+ else if (params->dir[0] == '\0')
#ifndef WIN32
{
- sfile->params->dir[0] = '/';
- sfile->params->dir[1] = '\0';
+ params->dir[0] = '/';
+ params->dir[1] = '\0';
}
#else
{
- BLI_windows_get_default_root_dir(sfile->params->dir);
+ BLI_windows_get_default_root_dir(params->dir);
}
/* change "C:" --> "C:\", T28102. */
- else if ((isalpha(sfile->params->dir[0]) && (sfile->params->dir[1] == ':')) &&
- (sfile->params->dir[2] == '\0')) {
- sfile->params->dir[2] = '\\';
- sfile->params->dir[3] = '\0';
+ else if ((isalpha(params->dir[0]) && (params->dir[1] == ':')) && (params->dir[2] == '\0')) {
+ params->dir[2] = '\\';
+ params->dir[3] = '\0';
}
- else if (BLI_path_is_unc(sfile->params->dir)) {
- BLI_path_normalize_unc(sfile->params->dir, FILE_MAX_LIBEXTRA);
+ else if (BLI_path_is_unc(params->dir)) {
+ BLI_path_normalize_unc(params->dir, FILE_MAX_LIBEXTRA);
}
#endif
}
@@ -2343,46 +2342,44 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
{
Main *bmain = CTX_data_main(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
- if (sfile->params) {
- char old_dir[sizeof(sfile->params->dir)];
+ if (params) {
+ char old_dir[sizeof(params->dir)];
- BLI_strncpy(old_dir, sfile->params->dir, sizeof(old_dir));
+ BLI_strncpy(old_dir, params->dir, sizeof(old_dir));
file_expand_directory(C);
/* special case, user may have pasted a filepath into the directory */
- if (!filelist_is_dir(sfile->files, sfile->params->dir)) {
+ if (!filelist_is_dir(sfile->files, params->dir)) {
char tdir[FILE_MAX_LIBEXTRA];
char *group, *name;
- if (BLI_is_file(sfile->params->dir)) {
- char path[sizeof(sfile->params->dir)];
- BLI_strncpy(path, sfile->params->dir, sizeof(path));
- BLI_split_dirfile(path,
- sfile->params->dir,
- sfile->params->file,
- sizeof(sfile->params->dir),
- sizeof(sfile->params->file));
+ if (BLI_is_file(params->dir)) {
+ char path[sizeof(params->dir)];
+ BLI_strncpy(path, params->dir, sizeof(path));
+ BLI_split_dirfile(
+ path, params->dir, params->file, sizeof(params->dir), sizeof(params->file));
}
- else if (BLO_library_path_explode(sfile->params->dir, tdir, &group, &name)) {
+ else if (BLO_library_path_explode(params->dir, tdir, &group, &name)) {
if (group) {
BLI_path_append(tdir, sizeof(tdir), group);
}
- BLI_strncpy(sfile->params->dir, tdir, sizeof(sfile->params->dir));
+ BLI_strncpy(params->dir, tdir, sizeof(params->dir));
if (name) {
- BLI_strncpy(sfile->params->file, name, sizeof(sfile->params->file));
+ BLI_strncpy(params->file, name, sizeof(params->file));
}
else {
- sfile->params->file[0] = '\0';
+ params->file[0] = '\0';
}
}
}
- BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), sfile->params->dir);
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir);
- if (filelist_is_dir(sfile->files, sfile->params->dir)) {
- if (!STREQ(sfile->params->dir, old_dir)) { /* Avoids flickering when nothing's changed. */
+ if (filelist_is_dir(sfile->files, params->dir)) {
+ if (!STREQ(params->dir, old_dir)) { /* Avoids flickering when nothing's changed. */
/* if directory exists, enter it immediately */
ED_file_change_dir(C);
}
@@ -2392,10 +2389,10 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
/* UI_textbutton_activate_but(C, but); */
}
#if defined(WIN32)
- else if (!can_create_dir(sfile->params->dir)) {
+ else if (!can_create_dir(params->dir)) {
const char *lastdir = folderlist_peeklastdir(sfile->folders_prev);
if (lastdir) {
- BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
+ BLI_strncpy(params->dir, lastdir, sizeof(params->dir));
}
}
#endif
@@ -2405,21 +2402,21 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
/* If we are 'inside' a blend library, we cannot do anything... */
if (lastdir && BLO_library_path_explode(lastdir, tdir, NULL, NULL)) {
- BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
+ BLI_strncpy(params->dir, lastdir, sizeof(params->dir));
}
else {
/* if not, ask to create it and enter if confirmed */
wmOperatorType *ot = WM_operatortype_find("FILE_OT_directory_new", false);
PointerRNA ptr;
WM_operator_properties_create_ptr(&ptr, ot);
- RNA_string_set(&ptr, "directory", sfile->params->dir);
+ RNA_string_set(&ptr, "directory", params->dir);
RNA_boolean_set(&ptr, "open", true);
/* Enable confirmation prompt, else it's too easy
* to accidentally create new directories. */
RNA_boolean_set(&ptr, "confirm", true);
if (lastdir) {
- BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
+ BLI_strncpy(params->dir, lastdir, sizeof(params->dir));
}
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
@@ -2435,39 +2432,39 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg
{
Main *bmain = CTX_data_main(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
uiBut *but = arg_but;
char matched_file[FILE_MAX];
- char filepath[sizeof(sfile->params->dir)];
- if (sfile->params) {
+ if (params) {
+ char filepath[sizeof(params->dir)];
int matches;
matched_file[0] = '\0';
filepath[0] = '\0';
file_expand_directory(C);
- matches = file_select_match(sfile, sfile->params->file, matched_file);
+ matches = file_select_match(sfile, params->file, matched_file);
/* *After* file_select_match! */
- BLI_filename_make_safe(sfile->params->file);
+ BLI_filename_make_safe(params->file);
if (matches) {
/* replace the pattern (or filename that the user typed in,
* with the first selected file of the match */
- BLI_strncpy(sfile->params->file, matched_file, sizeof(sfile->params->file));
+ BLI_strncpy(params->file, matched_file, sizeof(params->file));
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
}
if (matches == 1) {
- BLI_join_dirfile(
- filepath, sizeof(sfile->params->dir), sfile->params->dir, sfile->params->file);
+ BLI_join_dirfile(filepath, sizeof(params->dir), params->dir, params->file);
/* if directory, open it and empty filename field */
if (filelist_is_dir(sfile->files, filepath)) {
BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), filepath);
- BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir));
- sfile->params->file[0] = '\0';
+ BLI_strncpy(params->dir, filepath, sizeof(params->dir));
+ params->file[0] = '\0';
ED_file_change_dir(C);
UI_textbutton_activate_but(C, but);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
@@ -2489,9 +2486,10 @@ static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused))
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
- if (sfile->params) {
- sfile->params->flag ^= FILE_HIDE_DOT;
+ if (params) {
+ params->flag ^= FILE_HIDE_DOT;
ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
@@ -2525,7 +2523,8 @@ static bool file_filenum_poll(bContext *C)
return false;
}
- return sfile->params && (sfile->params->flag & FILE_CHECK_EXISTING);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+ return params && (params->flag & FILE_CHECK_EXISTING);
}
/**
@@ -2563,11 +2562,12 @@ static void filenum_newname(char *name, size_t name_size, int add)
static int file_filenum_exec(bContext *C, wmOperator *op)
{
SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
ScrArea *area = CTX_wm_area(C);
int inc = RNA_int_get(op->ptr, "increment");
- if (sfile->params && (inc != 0)) {
- filenum_newname(sfile->params->file, sizeof(sfile->params->file), inc);
+ if (params && (inc != 0)) {
+ filenum_newname(params->file, sizeof(params->file), inc);
ED_area_tag_redraw(area);
file_draw_check(C);
// WM_event_add_notifier(C, NC_WINDOW, NULL);
@@ -2606,12 +2606,14 @@ static void file_rename_state_activate(SpaceFile *sfile, int file_idx, bool requ
if ((require_selected == false) ||
(filelist_entry_select_get(sfile->files, file, CHECK_ALL) & FILE_SEL_SELECTED)) {
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+
filelist_entry_select_index_set(
sfile->files, file_idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
- BLI_strncpy(sfile->params->renamefile, file->relpath, FILE_MAXFILE);
+ BLI_strncpy(params->renamefile, file->relpath, FILE_MAXFILE);
/* We can skip the pending state,
* as we can directly set FILE_SEL_EDITING on the expected entry here. */
- sfile->params->rename_flag = FILE_PARAMS_RENAME_ACTIVE;
+ params->rename_flag = FILE_PARAMS_RENAME_ACTIVE;
}
}
}
@@ -2620,9 +2622,10 @@ static int file_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent
{
ScrArea *area = CTX_wm_area(C);
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
- if (sfile->params) {
- file_rename_state_activate(sfile, sfile->params->active_file, true);
+ if (params) {
+ file_rename_state_activate(sfile, params->active_file, true);
ED_area_tag_redraw(area);
}
@@ -2633,9 +2636,10 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *area = CTX_wm_area(C);
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
- if (sfile->params) {
- file_rename_state_activate(sfile, sfile->params->highlight_file, false);
+ if (params) {
+ file_rename_state_activate(sfile, params->highlight_file, false);
ED_area_tag_redraw(area);
}
@@ -2665,8 +2669,9 @@ static bool file_delete_poll(bContext *C)
{
bool poll = ED_operator_file_active(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
- if (sfile && sfile->params) {
+ if (sfile && params) {
char dir[FILE_MAX_LIBEXTRA];
int numfiles = filelist_files_ensure(sfile->files);
int i;
@@ -2691,10 +2696,34 @@ static bool file_delete_poll(bContext *C)
return poll;
}
+static bool file_delete_single(const FileSelectParams *params,
+ FileDirEntry *file,
+ const char **r_error_message)
+{
+ if (file->typeflag & FILE_TYPE_ASSET) {
+ ID *id = filelist_file_get_id(file);
+ if (!id) {
+ *r_error_message = "File is not a local data-block asset.";
+ return false;
+ }
+ ED_asset_clear_id(id);
+ }
+ else {
+ char str[FILE_MAX];
+ BLI_join_dirfile(str, sizeof(str), params->dir, file->relpath);
+ if (BLI_delete_soft(str, r_error_message) != 0 || BLI_exists(str)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
static int file_delete_exec(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
int numfiles = filelist_files_ensure(sfile->files);
const char *error_message = NULL;
@@ -2703,9 +2732,7 @@ static int file_delete_exec(bContext *C, wmOperator *op)
for (int i = 0; i < numfiles; i++) {
if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL)) {
FileDirEntry *file = filelist_file(sfile->files, i);
- char str[FILE_MAX];
- BLI_join_dirfile(str, sizeof(str), sfile->params->dir, file->relpath);
- if (BLI_delete_soft(str, &error_message) != 0 || BLI_exists(str)) {
+ if (!file_delete_single(params, file, &error_message)) {
report_error = true;
}
}
@@ -2751,12 +2778,20 @@ void FILE_OT_delete(struct wmOperatorType *ot)
static int file_start_filter_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *area = CTX_wm_area(C);
- ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_UI);
- SpaceFile *sf = CTX_wm_space_file(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
ARegion *region_ctx = CTX_wm_region(C);
- CTX_wm_region_set(C, region);
- UI_textbutton_activate_rna(C, region, sf->params, "filter_search");
+
+ if (area) {
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ CTX_wm_region_set(C, region);
+ if (UI_textbutton_activate_rna(C, region, params, "filter_search")) {
+ break;
+ }
+ }
+ }
+
CTX_wm_region_set(C, region_ctx);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index 22d206c0a70..411f99cc3b4 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -132,7 +132,7 @@ static void file_panel_execution_buttons_draw(const bContext *C, Panel *panel)
{
bScreen *screen = CTX_wm_screen(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
uiBlock *block = uiLayoutGetBlock(panel->layout);
uiBut *but;
uiLayout *row;
@@ -180,11 +180,16 @@ static void file_panel_execution_buttons_draw(const bContext *C, Panel *panel)
UI_but_funcN_set(but, file_filename_enter_handle, NULL, but);
if (params->flag & FILE_CHECK_EXISTING) {
- but_extra_rna_ptr = UI_but_extra_operator_icon_add(
+ uiButExtraOpIcon *extra_icon;
+
+ extra_icon = UI_but_extra_operator_icon_add(
but, "FILE_OT_filenum", WM_OP_EXEC_REGION_WIN, ICON_REMOVE);
+ but_extra_rna_ptr = UI_but_extra_operator_icon_opptr_get(extra_icon);
RNA_int_set(but_extra_rna_ptr, "increment", -1);
- but_extra_rna_ptr = UI_but_extra_operator_icon_add(
+
+ extra_icon = UI_but_extra_operator_icon_add(
but, "FILE_OT_filenum", WM_OP_EXEC_REGION_WIN, ICON_ADD);
+ but_extra_rna_ptr = UI_but_extra_operator_icon_opptr_get(extra_icon);
RNA_int_set(but_extra_rna_ptr, "increment", 1);
}
diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c
index 452f2f704cf..9d85996c559 100644
--- a/source/blender/editors/space_file/file_utils.c
+++ b/source/blender/editors/space_file/file_utils.c
@@ -18,12 +18,14 @@
* \ingroup spfile
*/
+#include "BLI_fileops.h"
#include "BLI_listbase.h"
+#include "BLI_path_util.h"
#include "BLI_rect.h"
-
-#include "BLO_readfile.h"
+#include "BLI_string.h"
#include "BKE_context.h"
+#include "BLO_readfile.h"
#include "ED_fileselect.h"
#include "ED_screen.h"
@@ -44,3 +46,14 @@ void file_tile_boundbox(const ARegion *region, FileLayout *layout, const int fil
ymax - layout->tile_h - layout->tile_border_y,
ymax);
}
+
+/**
+ * If \a path leads to a .blend, remove the trailing slash (if needed).
+ */
+void file_path_to_ui_path(const char *path, char *r_path, int max_size)
+{
+ char tmp_path[PATH_MAX];
+ BLI_strncpy(tmp_path, path, sizeof(tmp_path));
+ BLI_path_slash_rstrip(tmp_path);
+ BLI_strncpy(r_path, BLO_has_bfile_extension(tmp_path) ? tmp_path : path, max_size);
+}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 9e51b6ca4ba..d66219c7549 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -53,13 +53,18 @@
# include "BLI_winstuff.h"
#endif
+#include "BKE_asset.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_idtype.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
+#include "BKE_main_idmap.h"
+#include "BKE_preferences.h"
#include "BLO_readfile.h"
+#include "DNA_asset_types.h"
#include "DNA_space_types.h"
#include "ED_datafiles.h"
@@ -82,6 +87,8 @@
#include "filelist.h"
+#define FILEDIR_NBR_ENTRIES_UNSET -1
+
/* ----------------- FOLDERLIST (previous/next) -------------- */
typedef struct FolderList {
@@ -89,12 +96,6 @@ typedef struct FolderList {
char *foldername;
} FolderList;
-ListBase *folderlist_new(void)
-{
- ListBase *p = MEM_callocN(sizeof(*p), __func__);
- return p;
-}
-
void folderlist_popdir(struct ListBase *folderlist, char *dir)
{
const char *prev_dir;
@@ -117,6 +118,10 @@ void folderlist_popdir(struct ListBase *folderlist, char *dir)
void folderlist_pushdir(ListBase *folderlist, const char *dir)
{
+ if (!dir[0]) {
+ return;
+ }
+
struct FolderList *folder, *previous_folder;
previous_folder = folderlist->last;
@@ -149,17 +154,18 @@ const char *folderlist_peeklastdir(ListBase *folderlist)
int folderlist_clear_next(struct SpaceFile *sfile)
{
+ const FileSelectParams *params = ED_fileselect_get_active_params(sfile);
struct FolderList *folder;
/* if there is no folder_next there is nothing we can clear */
- if (!sfile->folders_next) {
+ if (BLI_listbase_is_empty(sfile->folders_next)) {
return 0;
}
/* if previous_folder, next_folder or refresh_folder operators are executed
* it doesn't clear folder_next */
folder = sfile->folders_prev->last;
- if ((!folder) || (BLI_path_cmp(folder->foldername, sfile->params->dir) == 0)) {
+ if ((!folder) || (BLI_path_cmp(folder->foldername, params->dir) == 0)) {
return 0;
}
@@ -179,23 +185,79 @@ void folderlist_free(ListBase *folderlist)
}
}
-ListBase *folderlist_duplicate(ListBase *folderlist)
+static ListBase folderlist_duplicate(ListBase *folderlist)
{
+ ListBase folderlistn = {NULL};
- if (folderlist) {
- ListBase *folderlistn = MEM_callocN(sizeof(*folderlistn), __func__);
- FolderList *folder;
+ BLI_duplicatelist(&folderlistn, folderlist);
+
+ for (FolderList *folder = folderlistn.first; folder; folder = folder->next) {
+ folder->foldername = MEM_dupallocN(folder->foldername);
+ }
+ return folderlistn;
+}
- BLI_duplicatelist(folderlistn, folderlist);
+/* ----------------- Folder-History (wraps/owns file list above) -------------- */
- for (folder = folderlistn->first; folder; folder = folder->next) {
- folder->foldername = MEM_dupallocN(folder->foldername);
+static FileFolderHistory *folder_history_find(const SpaceFile *sfile, eFileBrowse_Mode browse_mode)
+{
+ LISTBASE_FOREACH (FileFolderHistory *, history, &sfile->folder_histories) {
+ if (history->browse_mode == browse_mode) {
+ return history;
}
- return folderlistn;
}
+
return NULL;
}
+void folder_history_list_ensure_for_active_browse_mode(SpaceFile *sfile)
+{
+ FileFolderHistory *history = folder_history_find(sfile, sfile->browse_mode);
+
+ if (!history) {
+ history = MEM_callocN(sizeof(*history), __func__);
+ history->browse_mode = sfile->browse_mode;
+ BLI_addtail(&sfile->folder_histories, history);
+ }
+
+ sfile->folders_next = &history->folders_next;
+ sfile->folders_prev = &history->folders_prev;
+}
+
+static void folder_history_entry_free(SpaceFile *sfile, FileFolderHistory *history)
+{
+ if (sfile->folders_prev == &history->folders_prev) {
+ sfile->folders_prev = NULL;
+ }
+ if (sfile->folders_next == &history->folders_next) {
+ sfile->folders_next = NULL;
+ }
+ folderlist_free(&history->folders_prev);
+ folderlist_free(&history->folders_next);
+ BLI_freelinkN(&sfile->folder_histories, history);
+}
+
+void folder_history_list_free(SpaceFile *sfile)
+{
+ LISTBASE_FOREACH_MUTABLE (FileFolderHistory *, history, &sfile->folder_histories) {
+ folder_history_entry_free(sfile, history);
+ }
+}
+
+ListBase folder_history_list_duplicate(ListBase *listbase)
+{
+ ListBase histories = {NULL};
+
+ LISTBASE_FOREACH (FileFolderHistory *, history, listbase) {
+ FileFolderHistory *history_new = MEM_dupallocN(history);
+ history_new->folders_prev = folderlist_duplicate(&history->folders_prev);
+ history_new->folders_next = folderlist_duplicate(&history->folders_next);
+ BLI_addtail(&histories, history_new);
+ }
+
+ return histories;
+}
+
/* ------------------FILELIST------------------------ */
typedef struct FileListInternEntry {
@@ -215,6 +277,24 @@ typedef struct FileListInternEntry {
/** not strictly needed, but used during sorting, avoids to have to recompute it there... */
char *name;
+ /**
+ * This is data from the current main, represented by this file. It's crucial that this is
+ * updated correctly on undo, redo and file reading (without UI). The space is responsible to
+ * take care of that.
+ */
+ struct {
+ /** When showing local IDs (FILE_MAIN, FILE_MAIN_ASSET), the ID this file entry represents. */
+ ID *id;
+
+ /* For the few file types that have the preview already in memory. For others, there's delayed
+ * preview reading from disk. Non-owning pointer. */
+ PreviewImage *preview_image;
+ } local_data;
+
+ /** When the file represents an asset read from another file, it is stored here.
+ * Owning pointer. */
+ AssetMetaData *imported_asset_data;
+
/** Defined in BLI_fileops.h */
eFileAttributes attributes;
BLI_stat_t st;
@@ -266,7 +346,11 @@ typedef struct FileListEntryPreview {
char path[FILE_MAX];
uint flags;
int index;
- ImBuf *img;
+ /* Some file types load the memory from runtime data, not from disk. We just wait until it's done
+ * generating (BKE_previewimg_is_finished()). */
+ PreviewImage *in_memory_preview;
+
+ int icon_id;
} FileListEntryPreview;
/* Dummy wrapper around FileListEntryPreview to ensure we do not access freed memory when freeing
@@ -289,11 +373,16 @@ enum {
FLF_HIDE_DOT = 1 << 1,
FLF_HIDE_PARENT = 1 << 2,
FLF_HIDE_LIB_DIR = 1 << 3,
+ FLF_ASSETS_ONLY = 1 << 4,
};
typedef struct FileList {
FileDirEntryArr filelist;
+ eFileSelectType type;
+ /* The library this list was created for. Stored here so we know when to re-read. */
+ FileSelectAssetLibraryUID *asset_library;
+
short flags;
short sort;
@@ -323,10 +412,13 @@ typedef struct FileList {
bool (*checkdirf)(struct FileList *, char *, const bool);
/* Fill filelist (to be called by read job). */
- void (*read_jobf)(struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
+ void (*read_jobf)(
+ Main *, struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
/* Filter an entry of current filelist. */
bool (*filterf)(struct FileListInternEntry *, const char *, FileListFilter *);
+
+ short tags; /* FileListTags */
} FileList;
/* FileList.flags */
@@ -339,6 +431,14 @@ enum {
FL_SORT_INVERT = 1 << 5,
};
+/* FileList.tags */
+enum FileListTags {
+ /** The file list has references to main data (IDs) and needs special care. */
+ FILELIST_TAGS_USES_MAIN_DATA = (1 << 0),
+ /** The file list type is not thread-safe. */
+ FILELIST_TAGS_NO_THREADS = (1 << 2),
+};
+
#define SPECIAL_IMG_SIZE 256
#define SPECIAL_IMG_ROWS 1
#define SPECIAL_IMG_COLS 7
@@ -356,24 +456,34 @@ enum {
static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX];
-static void filelist_readjob_main(FileList *filelist,
+static void filelist_readjob_main(Main *current_main,
+ FileList *filelist,
const char *main_name,
short *stop,
short *do_update,
float *progress,
ThreadMutex *lock);
-static void filelist_readjob_lib(FileList *filelist,
+static void filelist_readjob_lib(Main *current_main,
+ FileList *filelist,
const char *main_name,
short *stop,
short *do_update,
float *progress,
ThreadMutex *lock);
-static void filelist_readjob_dir(FileList *filelist,
+static void filelist_readjob_dir(Main *current_main,
+ FileList *filelist,
const char *main_name,
short *stop,
short *do_update,
float *progress,
ThreadMutex *lock);
+static void filelist_readjob_main_assets(Main *current_main,
+ FileList *filelist,
+ const char *main_name,
+ short *stop,
+ short *do_update,
+ float *progress,
+ ThreadMutex *lock);
/* helper, could probably go in BKE actually? */
static int groupname_to_code(const char *group);
@@ -629,7 +739,7 @@ void filelist_setsorting(struct FileList *filelist, const short sort, bool inver
/* ********** Filter helpers ********** */
/* True if filename is meant to be hidden, eg. starting with period. */
-static bool is_hidden_dot_filename(const char *filename, FileListInternEntry *file)
+static bool is_hidden_dot_filename(const char *filename, const FileListInternEntry *file)
{
if (filename[0] == '.' && !ELEM(filename[1], '.', '\0')) {
return true; /* ignore .file */
@@ -670,8 +780,8 @@ static bool is_hidden_dot_filename(const char *filename, FileListInternEntry *fi
/* True if should be hidden, based on current filtering. */
static bool is_filtered_hidden(const char *filename,
- FileListFilter *filter,
- FileListInternEntry *file)
+ const FileListFilter *filter,
+ const FileListInternEntry *file)
{
if ((filename[0] == '.') && (filename[1] == '\0')) {
return true; /* Ignore . */
@@ -693,6 +803,11 @@ static bool is_filtered_hidden(const char *filename,
return true;
}
#endif
+ /* For data-blocks (but not the group directories), check the asset-only filter. */
+ if (!(file->typeflag & FILE_TYPE_DIR) && (file->typeflag & FILE_TYPE_BLENDERLIB) &&
+ (filter->flags & FLF_ASSETS_ONLY) && !(file->typeflag & FILE_TYPE_ASSET)) {
+ return true;
+ }
return false;
}
@@ -736,51 +851,61 @@ static bool is_filtered_file(FileListInternEntry *file,
return is_filtered;
}
-static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileListFilter *filter)
+static bool is_filtered_id_file(const FileListInternEntry *file,
+ const char *id_group,
+ const char *name,
+ const FileListFilter *filter)
{
- bool is_filtered;
- char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name;
-
- BLI_join_dirfile(path, sizeof(path), root, file->relpath);
-
- if (BLO_library_path_explode(path, dir, &group, &name)) {
- is_filtered = !is_filtered_hidden(file->relpath, filter, file);
- if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) {
- /* We only check for types if some type are enabled in filtering. */
- if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) {
- if (file->typeflag & FILE_TYPE_DIR) {
- if (file->typeflag &
- (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
- if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
- is_filtered = false;
- }
- }
- else {
- if (!(filter->filter & FILE_TYPE_FOLDER)) {
- is_filtered = false;
- }
+ bool is_filtered = !is_filtered_hidden(file->relpath, filter, file);
+ if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) {
+ /* We only check for types if some type are enabled in filtering. */
+ if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) {
+ if (file->typeflag & FILE_TYPE_DIR) {
+ if (file->typeflag &
+ (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
+ if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
+ is_filtered = false;
}
}
- if (is_filtered && group) {
- if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) {
+ else {
+ if (!(filter->filter & FILE_TYPE_FOLDER)) {
is_filtered = false;
}
- else {
- uint64_t filter_id = groupname_to_filter_id(group);
- if (!(filter_id & filter->filter_id)) {
- is_filtered = false;
- }
- }
}
}
- /* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */
- if (is_filtered && (filter->filter_search[0] != '\0')) {
- if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
+ if (is_filtered && id_group) {
+ if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) {
is_filtered = false;
}
+ else {
+ uint64_t filter_id = groupname_to_filter_id(id_group);
+ if (!(filter_id & filter->filter_id)) {
+ is_filtered = false;
+ }
+ }
+ }
+ }
+ /* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */
+ if (is_filtered && (filter->filter_search[0] != '\0')) {
+ if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
+ is_filtered = false;
}
}
}
+
+ return is_filtered;
+}
+
+static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileListFilter *filter)
+{
+ bool is_filtered;
+ char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name;
+
+ BLI_join_dirfile(path, sizeof(path), root, file->relpath);
+
+ if (BLO_library_path_explode(path, dir, &group, &name)) {
+ is_filtered = is_filtered_id_file(file, group, name, filter);
+ }
else {
is_filtered = is_filtered_file(file, root, filter);
}
@@ -795,6 +920,14 @@ static bool is_filtered_main(FileListInternEntry *file,
return !is_filtered_hidden(file->relpath, filter, file);
}
+static bool is_filtered_main_assets(FileListInternEntry *file,
+ const char *UNUSED(dir),
+ FileListFilter *filter)
+{
+ /* "Filtered" means *not* being filtered out... So return true if the file should be visible. */
+ return is_filtered_id_file(file, file->relpath, file->name, filter);
+}
+
static void filelist_filter_clear(FileList *filelist)
{
filelist->flags |= FL_NEED_FILTERING;
@@ -806,7 +939,7 @@ void filelist_filter(FileList *filelist)
const int num_files = filelist->filelist.nbr_entries;
FileListInternEntry **filtered_tmp, *file;
- if (filelist->filelist.nbr_entries == 0) {
+ if (ELEM(filelist->filelist.nbr_entries, FILEDIR_NBR_ENTRIES_UNSET, 0)) {
return;
}
@@ -857,6 +990,7 @@ void filelist_setfilter_options(FileList *filelist,
const bool hide_parent,
const uint64_t filter,
const uint64_t filter_id,
+ const bool filter_assets_only,
const char *filter_glob,
const char *filter_search)
{
@@ -874,6 +1008,10 @@ void filelist_setfilter_options(FileList *filelist,
filelist->filter_data.flags ^= FLF_HIDE_PARENT;
update = true;
}
+ if (((filelist->filter_data.flags & FLF_ASSETS_ONLY) != 0) != (filter_assets_only != 0)) {
+ filelist->filter_data.flags ^= FLF_ASSETS_ONLY;
+ update = true;
+ }
if (filelist->filter_data.filter != filter) {
filelist->filter_data.filter = filter;
update = true;
@@ -902,6 +1040,54 @@ void filelist_setfilter_options(FileList *filelist,
}
}
+/**
+ * Checks two libraries for equality.
+ * \return True if the libraries match.
+ */
+static bool filelist_compare_asset_libraries(const FileSelectAssetLibraryUID *library_a,
+ const FileSelectAssetLibraryUID *library_b)
+{
+ if (library_a->type != library_b->type) {
+ return false;
+ }
+ if (library_a->type == FILE_ASSET_LIBRARY_CUSTOM) {
+ /* Don't only check the index, also check that it's valid. */
+ bUserAssetLibrary *library_ptr_a = BKE_preferences_asset_library_find_from_index(
+ &U, library_a->custom_library_index);
+ return (library_ptr_a != NULL) &&
+ (library_a->custom_library_index == library_b->custom_library_index);
+ }
+
+ return true;
+}
+
+/**
+ * \param asset_library: May be NULL to unset the library.
+ */
+void filelist_setlibrary(FileList *filelist, const FileSelectAssetLibraryUID *asset_library)
+{
+ /* Unset if needed. */
+ if (!asset_library) {
+ if (filelist->asset_library) {
+ MEM_SAFE_FREE(filelist->asset_library);
+ filelist->flags |= FL_FORCE_RESET;
+ }
+ return;
+ }
+
+ if (!filelist->asset_library) {
+ filelist->asset_library = MEM_mallocN(sizeof(*filelist->asset_library),
+ "filelist asset library");
+ *filelist->asset_library = *asset_library;
+
+ filelist->flags |= FL_FORCE_RESET;
+ }
+ else if (!filelist_compare_asset_libraries(filelist->asset_library, asset_library)) {
+ *filelist->asset_library = *asset_library;
+ filelist->flags |= FL_FORCE_RESET;
+ }
+}
+
/* ********** Icon/image helpers ********** */
void filelist_init_icons(void)
@@ -959,7 +1145,12 @@ ImBuf *filelist_getimage(struct FileList *filelist, const int index)
{
FileDirEntry *file = filelist_geticon_get_file(filelist, index);
- return file->image;
+ return file->preview_icon_id ? BKE_icon_imbuf_get_buffer(file->preview_icon_id) : NULL;
+}
+
+ImBuf *filelist_file_getimage(const FileDirEntry *file)
+{
+ return file->preview_icon_id ? BKE_icon_imbuf_get_buffer(file->preview_icon_id) : NULL;
}
static ImBuf *filelist_geticon_image_ex(FileDirEntry *file)
@@ -987,12 +1178,12 @@ ImBuf *filelist_geticon_image(struct FileList *filelist, const int index)
return filelist_geticon_image_ex(file);
}
-static int filelist_geticon_ex(FileDirEntry *file,
+static int filelist_geticon_ex(const FileDirEntry *file,
const char *root,
const bool is_main,
const bool ignore_libdir)
{
- const int typeflag = file->typeflag;
+ const eFileSel_File_Types typeflag = file->typeflag;
if ((typeflag & FILE_TYPE_DIR) &&
!(ignore_libdir && (typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER)))) {
@@ -1026,7 +1217,7 @@ static int filelist_geticon_ex(FileDirEntry *file,
if (file->redirection_path) {
target = file->redirection_path;
}
- else {
+ else if (root) {
BLI_join_dirfile(fullpath, sizeof(fullpath), root, file->relpath);
BLI_path_slash_ensure(fullpath);
}
@@ -1110,6 +1301,12 @@ int filelist_geticon(struct FileList *filelist, const int index, const bool is_m
return filelist_geticon_ex(file, filelist->filelist.root, is_main, false);
}
+int ED_file_icon(const FileDirEntry *file)
+{
+ return file->preview_icon_id ? file->preview_icon_id :
+ filelist_geticon_ex(file, NULL, false, false);
+}
+
/* ********** Main ********** */
static void parent_dir_until_exists_or_default_root(char *dir)
@@ -1159,6 +1356,14 @@ static bool filelist_checkdir_main(struct FileList *filelist, char *r_dir, const
return filelist_checkdir_lib(filelist, r_dir, do_change);
}
+static bool filelist_checkdir_main_assets(struct FileList *UNUSED(filelist),
+ char *UNUSED(r_dir),
+ const bool UNUSED(do_change))
+{
+ /* Main is always valid. */
+ return true;
+}
+
static void filelist_entry_clear(FileDirEntry *entry)
{
if (entry->name) {
@@ -1173,8 +1378,9 @@ static void filelist_entry_clear(FileDirEntry *entry)
if (entry->redirection_path) {
MEM_freeN(entry->redirection_path);
}
- if (entry->image) {
- IMB_freeImBuf(entry->image);
+ if (entry->preview_icon_id) {
+ BKE_icon_delete(entry->preview_icon_id);
+ entry->preview_icon_id = 0;
}
/* For now, consider FileDirEntryRevision::poin as not owned here,
* so no need to do anything about it */
@@ -1231,8 +1437,8 @@ static void filelist_direntryarr_free(FileDirEntryArr *array)
#else
BLI_assert(BLI_listbase_is_empty(&array->entries));
#endif
- array->nbr_entries = 0;
- array->nbr_entries_filtered = -1;
+ array->nbr_entries = FILEDIR_NBR_ENTRIES_UNSET;
+ array->nbr_entries_filtered = FILEDIR_NBR_ENTRIES_UNSET;
array->entry_idx_start = -1;
array->entry_idx_end = -1;
}
@@ -1248,6 +1454,10 @@ static void filelist_intern_entry_free(FileListInternEntry *entry)
if (entry->name) {
MEM_freeN(entry->name);
}
+ /* If we own the asset-data (it was generated from external file data), free it. */
+ if (entry->imported_asset_data) {
+ BKE_asset_metadata_free(&entry->imported_asset_data);
+ }
MEM_freeN(entry);
}
@@ -1271,37 +1481,54 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat
FileListEntryPreview *preview = preview_taskdata->preview;
ThumbSource source = 0;
+ bool done = false;
// printf("%s: Start (%d)...\n", __func__, threadid);
- // printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
- BLI_assert(preview->flags &
- (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | FILE_TYPE_BLENDER |
- FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB));
-
- if (preview->flags & FILE_TYPE_IMAGE) {
- source = THB_SOURCE_IMAGE;
- }
- else if (preview->flags &
- (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)) {
- source = THB_SOURCE_BLEND;
- }
- else if (preview->flags & FILE_TYPE_MOVIE) {
- source = THB_SOURCE_MOVIE;
- }
- else if (preview->flags & FILE_TYPE_FTFONT) {
- source = THB_SOURCE_FONT;
+ if (preview->in_memory_preview) {
+ if (BKE_previewimg_is_finished(preview->in_memory_preview, ICON_SIZE_PREVIEW)) {
+ ImBuf *imbuf = BKE_previewimg_to_imbuf(preview->in_memory_preview, ICON_SIZE_PREVIEW);
+ preview->icon_id = BKE_icon_imbuf_create(imbuf);
+ done = true;
+ }
}
+ else {
+ // printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+ BLI_assert(preview->flags &
+ (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | FILE_TYPE_BLENDER |
+ FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB));
- IMB_thumb_path_lock(preview->path);
- /* Always generate biggest preview size for now, it's simpler and avoids having to re-generate in
- * case user switch to a bigger preview size. */
- preview->img = IMB_thumb_manage(preview->path, THB_LARGE, source);
- IMB_thumb_path_unlock(preview->path);
+ if (preview->flags & FILE_TYPE_IMAGE) {
+ source = THB_SOURCE_IMAGE;
+ }
+ else if (preview->flags &
+ (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)) {
+ source = THB_SOURCE_BLEND;
+ }
+ else if (preview->flags & FILE_TYPE_MOVIE) {
+ source = THB_SOURCE_MOVIE;
+ }
+ else if (preview->flags & FILE_TYPE_FTFONT) {
+ source = THB_SOURCE_FONT;
+ }
+
+ IMB_thumb_path_lock(preview->path);
+ /* Always generate biggest preview size for now, it's simpler and avoids having to re-generate
+ * in case user switch to a bigger preview size. */
+ ImBuf *imbuf = IMB_thumb_manage(preview->path, THB_LARGE, source);
+ IMB_thumb_path_unlock(preview->path);
+ if (imbuf) {
+ preview->icon_id = BKE_icon_imbuf_create(imbuf);
+ }
+
+ done = true;
+ }
- /* That way task freeing function won't free th preview, since it does not own it anymore. */
- atomic_cas_ptr((void **)&preview_taskdata->preview, preview, NULL);
- BLI_thread_queue_push(cache->previews_done, preview);
+ if (done) {
+ /* That way task freeing function won't free th preview, since it does not own it anymore. */
+ atomic_cas_ptr((void **)&preview_taskdata->preview, preview, NULL);
+ BLI_thread_queue_push(cache->previews_done, preview);
+ }
// printf("%s: End (%d)...\n", __func__, threadid);
}
@@ -1314,8 +1541,8 @@ static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool), void
/* preview_taskdata->preview is atomically set to NULL once preview has been processed and sent
* to previews_done queue. */
if (preview != NULL) {
- if (preview->img) {
- IMB_freeImBuf(preview->img);
+ if (preview->icon_id) {
+ BKE_icon_delete(preview->icon_id);
}
MEM_freeN(preview);
}
@@ -1341,8 +1568,8 @@ static void filelist_cache_previews_clear(FileListEntryCache *cache)
while ((preview = BLI_thread_queue_pop_timeout(cache->previews_done, 0))) {
// printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path,
// preview->img);
- if (preview->img) {
- IMB_freeImBuf(preview->img);
+ if (preview->icon_id) {
+ BKE_icon_delete(preview->icon_id);
}
MEM_freeN(preview);
}
@@ -1373,10 +1600,11 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE);
- if (!entry->image && !(entry->flags & FILE_ENTRY_INVALID_PREVIEW) &&
+ if (!entry->preview_icon_id && !(entry->flags & FILE_ENTRY_INVALID_PREVIEW) &&
(entry->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT |
FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB))) {
FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__);
+ FileListInternEntry *intern_entry = filelist->filelist_intern.filtered[index];
if (entry->redirection_path) {
BLI_strncpy(preview->path, entry->redirection_path, FILE_MAXDIR);
@@ -1388,7 +1616,8 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
preview->index = index;
preview->flags = entry->typeflag;
- preview->img = NULL;
+ preview->in_memory_preview = intern_entry->local_data.preview_image;
+ preview->icon_id = 0;
// printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
filelist_cache_preview_ensure_running(cache);
@@ -1496,25 +1725,45 @@ FileList *filelist_new(short type)
p->selection_state = BLI_ghash_new(
BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__);
+ p->filelist.nbr_entries = FILEDIR_NBR_ENTRIES_UNSET;
+ filelist_settype(p, type);
- switch (type) {
+ return p;
+}
+
+void filelist_settype(FileList *filelist, short type)
+{
+ if (filelist->type == type) {
+ return;
+ }
+
+ filelist->type = type;
+ filelist->tags = 0;
+ switch (filelist->type) {
case FILE_MAIN:
- p->checkdirf = filelist_checkdir_main;
- p->read_jobf = filelist_readjob_main;
- p->filterf = is_filtered_main;
+ filelist->checkdirf = filelist_checkdir_main;
+ filelist->read_jobf = filelist_readjob_main;
+ filelist->filterf = is_filtered_main;
break;
case FILE_LOADLIB:
- p->checkdirf = filelist_checkdir_lib;
- p->read_jobf = filelist_readjob_lib;
- p->filterf = is_filtered_lib;
+ filelist->checkdirf = filelist_checkdir_lib;
+ filelist->read_jobf = filelist_readjob_lib;
+ filelist->filterf = is_filtered_lib;
+ break;
+ case FILE_MAIN_ASSET:
+ filelist->checkdirf = filelist_checkdir_main_assets;
+ filelist->read_jobf = filelist_readjob_main_assets;
+ filelist->filterf = is_filtered_main_assets;
+ filelist->tags |= FILELIST_TAGS_USES_MAIN_DATA | FILELIST_TAGS_NO_THREADS;
break;
default:
- p->checkdirf = filelist_checkdir_dir;
- p->read_jobf = filelist_readjob_dir;
- p->filterf = is_filtered_file;
+ filelist->checkdirf = filelist_checkdir_dir;
+ filelist->read_jobf = filelist_readjob_dir;
+ filelist->filterf = is_filtered_file;
break;
}
- return p;
+
+ filelist->flags |= FL_FORCE_RESET;
}
void filelist_clear_ex(struct FileList *filelist, const bool do_cache, const bool do_selection)
@@ -1559,6 +1808,8 @@ void filelist_free(struct FileList *filelist)
filelist->selection_state = NULL;
}
+ MEM_SAFE_FREE(filelist->asset_library);
+
memset(&filelist->filter_data, 0, sizeof(filelist->filter_data));
filelist->flags &= ~(FL_NEED_SORTING | FL_NEED_FILTERING);
@@ -1579,7 +1830,7 @@ BlendHandle *filelist_lib(struct FileList *filelist)
static const char *fileentry_uiname(const char *root,
const char *relpath,
- const int typeflag,
+ const eFileSel_File_Types typeflag,
char *buff)
{
char *name = NULL;
@@ -1623,11 +1874,12 @@ bool filelist_is_dir(struct FileList *filelist, const char *path)
*/
void filelist_setdir(struct FileList *filelist, char *r_dir)
{
+ const bool allow_invalid = filelist->asset_library != NULL;
BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA);
BLI_path_normalize_dir(BKE_main_blendfile_path_from_global(), r_dir);
- const bool is_valid_path = filelist->checkdirf(filelist, r_dir, true);
- BLI_assert(is_valid_path);
+ const bool is_valid_path = filelist->checkdirf(filelist, r_dir, !allow_invalid);
+ BLI_assert(is_valid_path || allow_invalid);
UNUSED_VARS_NDEBUG(is_valid_path);
if (!STREQ(filelist->filelist.root, r_dir)) {
@@ -1644,11 +1896,16 @@ void filelist_setrecursion(struct FileList *filelist, const int recursion_level)
}
}
-bool filelist_force_reset(struct FileList *filelist)
+bool filelist_needs_force_reset(FileList *filelist)
{
return (filelist->flags & FL_FORCE_RESET) != 0;
}
+void filelist_tag_force_reset(FileList *filelist)
+{
+ filelist->flags |= FL_FORCE_RESET;
+}
+
bool filelist_is_ready(struct FileList *filelist)
{
return (filelist->flags & FL_IS_READY) != 0;
@@ -1659,6 +1916,11 @@ bool filelist_pending(struct FileList *filelist)
return (filelist->flags & FL_IS_PENDING) != 0;
}
+bool filelist_needs_reset_on_main_changes(const FileList *filelist)
+{
+ return (filelist->tags & FILELIST_TAGS_USES_MAIN_DATA) != 0;
+}
+
/**
* Limited version of full update done by space_file's file_refresh(),
* to be used by operators and such.
@@ -1667,7 +1929,7 @@ bool filelist_pending(struct FileList *filelist)
*/
int filelist_files_ensure(FileList *filelist)
{
- if (!filelist_force_reset(filelist) || !filelist_empty(filelist)) {
+ if (!filelist_needs_force_reset(filelist) || !filelist_needs_reading(filelist)) {
filelist_sort(filelist);
filelist_filter(filelist);
}
@@ -1700,6 +1962,17 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in
if (entry->redirection_path) {
ret->redirection_path = BLI_strdup(entry->redirection_path);
}
+ ret->id = entry->local_data.id;
+ ret->asset_data = entry->imported_asset_data ? entry->imported_asset_data : NULL;
+ if (ret->id && (ret->asset_data == NULL)) {
+ ret->asset_data = ret->id->asset_data;
+ }
+ /* For some file types the preview is already available. */
+ if (entry->local_data.preview_image &&
+ BKE_previewimg_is_finished(entry->local_data.preview_image, ICON_SIZE_PREVIEW)) {
+ ImBuf *ibuf = BKE_previewimg_to_imbuf(entry->local_data.preview_image, ICON_SIZE_PREVIEW);
+ ret->preview_icon_id = BKE_icon_imbuf_create(ibuf);
+ }
BLI_addtail(&cache->cached_entries, ret);
return ret;
}
@@ -1769,7 +2042,7 @@ int filelist_file_findpath(struct FileList *filelist, const char *filename)
{
int fidx = -1;
- if (filelist->filelist.nbr_entries_filtered < 0) {
+ if (filelist->filelist.nbr_entries_filtered == FILEDIR_NBR_ENTRIES_UNSET) {
return fidx;
}
@@ -1787,9 +2060,17 @@ int filelist_file_findpath(struct FileList *filelist, const char *filename)
return -1;
}
+/**
+ * Get the ID a file represents (if any). For #FILE_MAIN, #FILE_MAIN_ASSET.
+ */
+ID *filelist_file_get_id(const FileDirEntry *file)
+{
+ return file->id;
+}
+
FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4])
{
- if (filelist->filelist.nbr_entries_filtered < 0) {
+ if (filelist->filelist.nbr_entries_filtered == FILEDIR_NBR_ENTRIES_UNSET) {
return NULL;
}
@@ -2146,15 +2427,17 @@ bool filelist_cache_previews_update(FileList *filelist)
// printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
- if (preview->img) {
+ if (preview->icon_id) {
/* Due to asynchronous process, a preview for a given image may be generated several times,
* i.e. entry->image may already be set at this point. */
- if (entry && !entry->image) {
- entry->image = preview->img;
+ if (entry && !entry->preview_icon_id) {
+ /* Move ownership over icon. */
+ entry->preview_icon_id = preview->icon_id;
+ preview->icon_id = 0;
changed = true;
}
else {
- IMB_freeImBuf(preview->img);
+ BKE_icon_delete(preview->icon_id);
}
}
else if (entry) {
@@ -2312,9 +2595,9 @@ int ED_file_extension_icon(const char *path)
}
}
-int filelist_empty(struct FileList *filelist)
+int filelist_needs_reading(struct FileList *filelist)
{
- return (filelist->filelist.nbr_entries == 0);
+ return (filelist->filelist.nbr_entries == FILEDIR_NBR_ENTRIES_UNSET);
}
uint filelist_entry_select_set(const FileList *filelist,
@@ -2563,8 +2846,8 @@ static int filelist_readjob_list_dir(const char *root,
static int filelist_readjob_list_lib(const char *root, ListBase *entries, const bool skip_currpar)
{
FileListInternEntry *entry;
- LinkNode *ln, *names;
- int i, nnames, idcode = 0, nbr_entries = 0;
+ LinkNode *ln, *names = NULL, *datablock_infos = NULL;
+ int i, nitems, idcode = 0, nbr_entries = 0;
char dir[FILE_MAX_LIBEXTRA], *group;
bool ok;
@@ -2586,11 +2869,11 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const
* and freed in filelist_entry_free. */
if (group) {
idcode = groupname_to_code(group);
- names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, &nnames);
+ datablock_infos = BLO_blendhandle_get_datablock_info(libfiledata, idcode, &nitems);
}
else {
names = BLO_blendhandle_get_linkable_groups(libfiledata);
- nnames = BLI_linklist_count(names);
+ nitems = BLI_linklist_count(names);
}
BLO_blendhandle_close(libfiledata);
@@ -2603,12 +2886,18 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const
nbr_entries++;
}
- for (i = 0, ln = names; i < nnames; i++, ln = ln->next) {
- const char *blockname = ln->link;
+ for (i = 0, ln = (datablock_infos ? datablock_infos : names); i < nitems; i++, ln = ln->next) {
+ struct BLODataBlockInfo *info = datablock_infos ? ln->link : NULL;
+ const char *blockname = info ? info->name : ln->link;
entry = MEM_callocN(sizeof(*entry), __func__);
entry->relpath = BLI_strdup(blockname);
entry->typeflag |= FILE_TYPE_BLENDERLIB;
+ if (info && info->asset_data) {
+ entry->typeflag |= FILE_TYPE_ASSET;
+ /* Moves ownership! */
+ entry->imported_asset_data = info->asset_data;
+ }
if (!(group && idcode)) {
entry->typeflag |= FILE_TYPE_DIR;
entry->blentype = groupname_to_code(blockname);
@@ -2620,7 +2909,7 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const
nbr_entries++;
}
- BLI_linklist_free(names, free);
+ BLI_linklist_freeN(datablock_infos ? datablock_infos : names);
return nbr_entries;
}
@@ -2819,7 +3108,10 @@ static void filelist_readjob_do(const bool do_lib,
// BLI_assert(filelist->filtered == NULL);
BLI_assert(BLI_listbase_is_empty(&filelist->filelist.entries) &&
- (filelist->filelist.nbr_entries == 0));
+ (filelist->filelist.nbr_entries == FILEDIR_NBR_ENTRIES_UNSET));
+
+ /* A valid, but empty directory from now. */
+ filelist->filelist.nbr_entries = 0;
todo_dirs = BLI_stack_new(sizeof(*td_dir), __func__);
td_dir = BLI_stack_push_r(todo_dirs);
@@ -2931,7 +3223,8 @@ static void filelist_readjob_do(const bool do_lib,
BLI_stack_free(todo_dirs);
}
-static void filelist_readjob_dir(FileList *filelist,
+static void filelist_readjob_dir(Main *UNUSED(current_main),
+ FileList *filelist,
const char *main_name,
short *stop,
short *do_update,
@@ -2941,7 +3234,8 @@ static void filelist_readjob_dir(FileList *filelist,
filelist_readjob_do(false, filelist, main_name, stop, do_update, progress, lock);
}
-static void filelist_readjob_lib(FileList *filelist,
+static void filelist_readjob_lib(Main *UNUSED(current_main),
+ FileList *filelist,
const char *main_name,
short *stop,
short *do_update,
@@ -2951,7 +3245,8 @@ static void filelist_readjob_lib(FileList *filelist,
filelist_readjob_do(true, filelist, main_name, stop, do_update, progress, lock);
}
-static void filelist_readjob_main(FileList *filelist,
+static void filelist_readjob_main(Main *current_main,
+ FileList *filelist,
const char *main_name,
short *stop,
short *do_update,
@@ -2959,12 +3254,67 @@ static void filelist_readjob_main(FileList *filelist,
ThreadMutex *lock)
{
/* TODO! */
- filelist_readjob_dir(filelist, main_name, stop, do_update, progress, lock);
+ filelist_readjob_dir(current_main, filelist, main_name, stop, do_update, progress, lock);
+}
+
+/**
+ * \warning Acts on main, so NOT thread-safe!
+ */
+static void filelist_readjob_main_assets(Main *current_main,
+ FileList *filelist,
+ const char *UNUSED(main_name),
+ short *UNUSED(stop),
+ short *do_update,
+ float *UNUSED(progress),
+ ThreadMutex *UNUSED(lock))
+{
+ BLI_assert(BLI_listbase_is_empty(&filelist->filelist.entries) &&
+ (filelist->filelist.nbr_entries == FILEDIR_NBR_ENTRIES_UNSET));
+
+ /* A valid, but empty directory from now. */
+ filelist->filelist.nbr_entries = 0;
+
+ FileListInternEntry *entry;
+ ListBase tmp_entries = {0};
+ ID *id_iter;
+ int nbr_entries = 0;
+
+ FOREACH_MAIN_ID_BEGIN (current_main, id_iter) {
+ if (!id_iter->asset_data) {
+ continue;
+ }
+
+ const char *id_code_name = BKE_idtype_idcode_to_name(GS(id_iter->name));
+
+ entry = MEM_callocN(sizeof(*entry), __func__);
+ entry->relpath = BLI_strdup(id_code_name);
+ entry->name = BLI_strdup(id_iter->name + 2);
+ entry->typeflag |= FILE_TYPE_BLENDERLIB | FILE_TYPE_ASSET;
+ entry->blentype = GS(id_iter->name);
+ *((uint32_t *)entry->uuid) = atomic_add_and_fetch_uint32(
+ (uint32_t *)filelist->filelist_intern.curr_uuid, 1);
+ entry->local_data.preview_image = BKE_asset_metadata_preview_get_from_id(id_iter->asset_data,
+ id_iter);
+ entry->local_data.id = id_iter;
+ nbr_entries++;
+ BLI_addtail(&tmp_entries, entry);
+ }
+ FOREACH_MAIN_ID_END;
+
+ if (nbr_entries) {
+ *do_update = true;
+
+ BLI_movelisttolist(&filelist->filelist.entries, &tmp_entries);
+ filelist->filelist.nbr_entries += nbr_entries;
+ filelist->filelist.nbr_entries_filtered = filelist->filelist.entry_idx_start =
+ filelist->filelist.entry_idx_end = -1;
+ }
}
typedef struct FileListReadJob {
ThreadMutex lock;
char main_name[FILE_MAX];
+ Main *current_main;
struct FileList *filelist;
/** XXX We may use a simpler struct here... just a linked list and root path? */
struct FileList *tmp_filelist;
@@ -2984,7 +3334,7 @@ static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update
flrj->tmp_filelist = MEM_dupallocN(flrj->filelist);
BLI_listbase_clear(&flrj->tmp_filelist->filelist.entries);
- flrj->tmp_filelist->filelist.nbr_entries = 0;
+ flrj->tmp_filelist->filelist.nbr_entries = FILEDIR_NBR_ENTRIES_UNSET;
flrj->tmp_filelist->filelist_intern.filtered = NULL;
BLI_listbase_clear(&flrj->tmp_filelist->filelist_intern.entries);
@@ -2995,11 +3345,17 @@ static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update
flrj->tmp_filelist->libfiledata = NULL;
memset(&flrj->tmp_filelist->filelist_cache, 0, sizeof(flrj->tmp_filelist->filelist_cache));
flrj->tmp_filelist->selection_state = NULL;
+ flrj->tmp_filelist->asset_library = NULL;
BLI_mutex_unlock(&flrj->lock);
- flrj->tmp_filelist->read_jobf(
- flrj->tmp_filelist, flrj->main_name, stop, do_update, progress, &flrj->lock);
+ flrj->tmp_filelist->read_jobf(flrj->current_main,
+ flrj->tmp_filelist,
+ flrj->main_name,
+ stop,
+ do_update,
+ progress,
+ &flrj->lock);
}
static void filelist_readjob_update(void *flrjv)
@@ -3014,7 +3370,7 @@ static void filelist_readjob_update(void *flrjv)
BLI_mutex_lock(&flrj->lock);
- if (flrj->tmp_filelist->filelist.nbr_entries) {
+ if (flrj->tmp_filelist->filelist.nbr_entries > 0) {
/* We just move everything out of 'thread context' into final list. */
new_nbr_entries = flrj->tmp_filelist->filelist.nbr_entries;
BLI_movelisttolist(&new_entries, &flrj->tmp_filelist->filelist.entries);
@@ -3032,7 +3388,7 @@ static void filelist_readjob_update(void *flrjv)
/* if no new_nbr_entries, this is NOP */
BLI_movelisttolist(&fl_intern->entries, &new_entries);
- flrj->filelist->filelist.nbr_entries = nbr_entries + new_nbr_entries;
+ flrj->filelist->filelist.nbr_entries = MAX2(nbr_entries, 0) + new_nbr_entries;
}
static void filelist_readjob_endjob(void *flrjv)
@@ -3073,16 +3429,36 @@ void filelist_readjob_start(FileList *filelist, const bContext *C)
wmJob *wm_job;
FileListReadJob *flrj;
+ if (!filelist_is_dir(filelist, filelist->filelist.root)) {
+ return;
+ }
+
/* prepare job data */
flrj = MEM_callocN(sizeof(*flrj), __func__);
flrj->filelist = filelist;
+ flrj->current_main = bmain;
BLI_strncpy(flrj->main_name, BKE_main_blendfile_path(bmain), sizeof(flrj->main_name));
filelist->flags &= ~(FL_FORCE_RESET | FL_IS_READY);
filelist->flags |= FL_IS_PENDING;
+ /* Init even for single threaded execution. Called functions use it. */
BLI_mutex_init(&flrj->lock);
+ if (filelist->tags & FILELIST_TAGS_NO_THREADS) {
+ short dummy_stop = false;
+ short dummy_do_update = false;
+ float dummy_progress = 0.0f;
+
+ /* Single threaded execution. Just directly call the callbacks. */
+ filelist_readjob_startjob(flrj, &dummy_stop, &dummy_do_update, &dummy_progress);
+ filelist_readjob_endjob(flrj);
+ filelist_readjob_free(flrj);
+
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ return;
+ }
+
/* setup job */
wm_job = WM_jobs_get(CTX_wm_manager(C),
CTX_wm_window(C),
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index 4b8cc052382..16984bb6e43 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -29,6 +29,7 @@ extern "C" {
struct BlendHandle;
struct FileList;
+struct FileSelectAssetLibraryUID;
struct FileSelection;
struct wmWindowManager;
@@ -46,14 +47,16 @@ typedef enum FileCheckType {
CHECK_ALL = 3,
} FileCheckType;
-struct ListBase *folderlist_new(void);
void folderlist_free(struct ListBase *folderlist);
-struct ListBase *folderlist_duplicate(ListBase *folderlist);
void folderlist_popdir(struct ListBase *folderlist, char *dir);
void folderlist_pushdir(struct ListBase *folderlist, const char *dir);
const char *folderlist_peeklastdir(struct ListBase *folderlist);
int folderlist_clear_next(struct SpaceFile *sfile);
+void folder_history_list_ensure_for_active_browse_mode(struct SpaceFile *sfile);
+void folder_history_list_free(struct SpaceFile *sfile);
+struct ListBase folder_history_list_duplicate(struct ListBase *listbase);
+
void filelist_setsorting(struct FileList *filelist, const short sort, bool invert_sort);
void filelist_sort(struct FileList *filelist);
@@ -63,17 +66,22 @@ void filelist_setfilter_options(struct FileList *filelist,
const bool hide_parent,
const uint64_t filter,
const uint64_t filter_id,
+ const bool filter_assets_only,
const char *filter_glob,
const char *filter_search);
void filelist_filter(struct FileList *filelist);
+void filelist_setlibrary(struct FileList *filelist,
+ const struct FileSelectAssetLibraryUID *asset_library);
void filelist_init_icons(void);
void filelist_free_icons(void);
struct ImBuf *filelist_getimage(struct FileList *filelist, const int index);
+struct ImBuf *filelist_file_getimage(const FileDirEntry *file);
struct ImBuf *filelist_geticon_image(struct FileList *filelist, const int index);
int filelist_geticon(struct FileList *filelist, const int index, const bool is_main);
struct FileList *filelist_new(short type);
+void filelist_settype(struct FileList *filelist, short type);
void filelist_clear(struct FileList *filelist);
void filelist_clear_ex(struct FileList *filelist, const bool do_cache, const bool do_selection);
void filelist_free(struct FileList *filelist);
@@ -83,15 +91,18 @@ bool filelist_is_dir(struct FileList *filelist, const char *path);
void filelist_setdir(struct FileList *filelist, char *r_dir);
int filelist_files_ensure(struct FileList *filelist);
-int filelist_empty(struct FileList *filelist);
+int filelist_needs_reading(struct FileList *filelist);
FileDirEntry *filelist_file(struct FileList *filelist, int index);
int filelist_file_findpath(struct FileList *filelist, const char *file);
+struct ID *filelist_file_get_id(const struct FileDirEntry *file);
FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4]);
void filelist_file_cache_slidingwindow_set(struct FileList *filelist, size_t window_size);
bool filelist_file_cache_block(struct FileList *filelist, const int index);
-bool filelist_force_reset(struct FileList *filelist);
+bool filelist_needs_force_reset(struct FileList *filelist);
+void filelist_tag_force_reset(struct FileList *filelist);
bool filelist_pending(struct FileList *filelist);
+bool filelist_needs_reset_on_main_changes(const struct FileList *filelist);
bool filelist_is_ready(struct FileList *filelist);
unsigned int filelist_entry_select_set(const struct FileList *filelist,
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 15c6972c5f5..b919a30e6cd 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -56,7 +56,9 @@
#include "BKE_appdir.h"
#include "BKE_context.h"
+#include "BKE_idtype.h"
#include "BKE_main.h"
+#include "BKE_preferences.h"
#include "BLF_api.h"
@@ -77,19 +79,76 @@
#define VERTLIST_MAJORCOLUMN_WIDTH (25 * UI_UNIT_X)
-FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile)
+static void fileselect_initialize_params_common(SpaceFile *sfile, FileSelectParams *params)
{
- if (!sfile->params) {
- ED_fileselect_set_params(sfile);
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
+
+ /* operator has no setting for this */
+ params->active_file = -1;
+
+ if (!params->dir[0]) {
+ if (blendfile_path[0] != '\0') {
+ BLI_split_dir_part(blendfile_path, params->dir, sizeof(params->dir));
+ }
+ else {
+ const char *doc_path = BKE_appdir_folder_default();
+ if (doc_path) {
+ BLI_strncpy(params->dir, doc_path, sizeof(params->dir));
+ }
+ }
+ }
+
+ folder_history_list_ensure_for_active_browse_mode(sfile);
+ folderlist_pushdir(sfile->folders_prev, params->dir);
+
+ /* Switching thumbnails needs to recalc layout T28809. */
+ if (sfile->layout) {
+ sfile->layout->dirty = true;
}
- return sfile->params;
+}
+
+static void fileselect_ensure_updated_asset_params(SpaceFile *sfile)
+{
+ BLI_assert(sfile->browse_mode == FILE_BROWSE_MODE_ASSETS);
+ BLI_assert(sfile->op == NULL);
+
+ FileAssetSelectParams *asset_params = sfile->asset_params;
+
+ if (!asset_params) {
+ asset_params = sfile->asset_params = MEM_callocN(sizeof(*asset_params),
+ "FileAssetSelectParams");
+ asset_params->base_params.details_flags = U_default.file_space_data.details_flags;
+ asset_params->asset_library.type = FILE_ASSET_LIBRARY_LOCAL;
+ asset_params->asset_library.custom_library_index = -1;
+ }
+
+ FileSelectParams *base_params = &asset_params->base_params;
+ base_params->file[0] = '\0';
+ base_params->filter_glob[0] = '\0';
+ /* TODO this way of using filters to form categories is notably slower than specifying a
+ * "group" to read. That's because all types are read and filtering is applied afterwards. Would
+ * be nice if we could lazy-read individual groups. */
+ base_params->flag |= U_default.file_space_data.flag | FILE_ASSETS_ONLY | FILE_FILTER;
+ base_params->flag &= ~FILE_DIRSEL_ONLY;
+ base_params->filter |= FILE_TYPE_BLENDERLIB;
+ base_params->filter_id = FILTER_ID_OB | FILTER_ID_GR;
+ base_params->display = FILE_IMGDISPLAY;
+ base_params->sort = FILE_SORT_ALPHA;
+ base_params->recursion_level = 1;
+ /* 'SMALL' size by default. More reasonable since this is typically used as regular editor,
+ * space is more of an issue here. */
+ base_params->thumbnail_size = 96;
+
+ fileselect_initialize_params_common(sfile, base_params);
}
/**
* \note RNA_struct_property_is_set_ex is used here because we want
* the previously used settings to be used here rather than overriding them */
-short ED_fileselect_set_params(SpaceFile *sfile)
+static FileSelectParams *fileselect_ensure_updated_file_params(SpaceFile *sfile)
{
+ BLI_assert(sfile->browse_mode == FILE_BROWSE_MODE_FILES);
+
FileSelectParams *params;
wmOperator *op = sfile->op;
@@ -136,20 +195,17 @@ short ED_fileselect_set_params(SpaceFile *sfile)
RNA_string_get(op->ptr, "filepath", name);
if (params->type == FILE_LOADLIB) {
BLI_strncpy(params->dir, name, sizeof(params->dir));
- sfile->params->file[0] = '\0';
+ params->file[0] = '\0';
}
else {
- BLI_split_dirfile(name,
- sfile->params->dir,
- sfile->params->file,
- sizeof(sfile->params->dir),
- sizeof(sfile->params->file));
+ BLI_split_dirfile(
+ name, params->dir, params->file, sizeof(params->dir), sizeof(params->file));
}
}
else {
if (is_directory && RNA_struct_property_is_set_ex(op->ptr, "directory", false)) {
RNA_string_get(op->ptr, "directory", params->dir);
- sfile->params->file[0] = '\0';
+ params->file[0] = '\0';
}
if (is_filename && RNA_struct_property_is_set_ex(op->ptr, "filename", false)) {
@@ -298,34 +354,104 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->filter_glob[0] = '\0';
}
- /* operator has no setting for this */
- params->active_file = -1;
+ fileselect_initialize_params_common(sfile, params);
- /* initialize the list with previous folders */
- if (!sfile->folders_prev) {
- sfile->folders_prev = folderlist_new();
- }
+ return params;
+}
- if (!sfile->params->dir[0]) {
- if (blendfile_path[0] != '\0') {
- BLI_split_dir_part(blendfile_path, sfile->params->dir, sizeof(sfile->params->dir));
- }
- else {
- const char *doc_path = BKE_appdir_folder_default();
- if (doc_path) {
- BLI_strncpy(sfile->params->dir, doc_path, sizeof(sfile->params->dir));
+/**
+ * If needed, create and return the file select parameters for the active browse mode.
+ */
+FileSelectParams *ED_fileselect_ensure_active_params(SpaceFile *sfile)
+{
+ switch ((eFileBrowse_Mode)sfile->browse_mode) {
+ case FILE_BROWSE_MODE_FILES:
+ if (!sfile->params) {
+ fileselect_ensure_updated_file_params(sfile);
+ }
+ return sfile->params;
+ case FILE_BROWSE_MODE_ASSETS:
+ if (!sfile->asset_params) {
+ fileselect_ensure_updated_asset_params(sfile);
}
+ return &sfile->asset_params->base_params;
+ }
+
+ BLI_assert(!"Invalid browse mode set in file space.");
+ return NULL;
+}
+
+/**
+ * Get the file select parameters for the active browse mode.
+ */
+FileSelectParams *ED_fileselect_get_active_params(const SpaceFile *sfile)
+{
+ if (!sfile) {
+ /* Sometimes called in poll before space type was checked. */
+ return NULL;
+ }
+
+ switch ((eFileBrowse_Mode)sfile->browse_mode) {
+ case FILE_BROWSE_MODE_FILES:
+ return sfile->params;
+ case FILE_BROWSE_MODE_ASSETS:
+ return (FileSelectParams *)sfile->asset_params;
+ }
+
+ BLI_assert(!"Invalid browse mode set in file space.");
+ return NULL;
+}
+
+FileSelectParams *ED_fileselect_get_file_params(const SpaceFile *sfile)
+{
+ return (sfile->browse_mode == FILE_BROWSE_MODE_FILES) ? sfile->params : NULL;
+}
+
+FileAssetSelectParams *ED_fileselect_get_asset_params(const SpaceFile *sfile)
+{
+ return (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) ? sfile->asset_params : NULL;
+}
+
+static void fileselect_refresh_asset_params(FileAssetSelectParams *asset_params)
+{
+ FileSelectAssetLibraryUID *library = &asset_params->asset_library;
+ FileSelectParams *base_params = &asset_params->base_params;
+ bUserAssetLibrary *user_library = NULL;
+
+ /* Ensure valid repo, or fall-back to local one. */
+ if (library->type == FILE_ASSET_LIBRARY_CUSTOM) {
+ BLI_assert(library->custom_library_index >= 0);
+
+ user_library = BKE_preferences_asset_library_find_from_index(&U,
+ library->custom_library_index);
+ if (!user_library) {
+ library->type = FILE_ASSET_LIBRARY_LOCAL;
}
}
- folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
+ switch (library->type) {
+ case FILE_ASSET_LIBRARY_LOCAL:
+ base_params->dir[0] = '\0';
+ break;
+ case FILE_ASSET_LIBRARY_CUSTOM:
+ BLI_assert(user_library);
+ BLI_strncpy(base_params->dir, user_library->path, sizeof(base_params->dir));
+ break;
+ }
+ base_params->type = (library->type == FILE_ASSET_LIBRARY_LOCAL) ? FILE_MAIN_ASSET : FILE_LOADLIB;
+}
- /* Switching thumbnails needs to recalc layout T28809. */
- if (sfile->layout) {
- sfile->layout->dirty = true;
+void fileselect_refresh_params(SpaceFile *sfile)
+{
+ FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
+ if (asset_params) {
+ fileselect_refresh_asset_params(asset_params);
}
+}
- return 1;
+bool ED_fileselect_is_asset_browser(const SpaceFile *sfile)
+{
+ return (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS);
}
/* The subset of FileSelectParams.flag items we store into preferences. Note that FILE_SORT_ALPHA
@@ -364,28 +490,28 @@ void ED_fileselect_set_params_from_userdef(SpaceFile *sfile)
wmOperator *op = sfile->op;
UserDef_FileSpaceData *sfile_udata = &U.file_space_data;
- ED_fileselect_set_params(sfile);
+ sfile->browse_mode = FILE_BROWSE_MODE_FILES;
+ FileSelectParams *params = fileselect_ensure_updated_file_params(sfile);
if (!op) {
return;
}
- sfile->params->thumbnail_size = sfile_udata->thumbnail_size;
- sfile->params->details_flags = sfile_udata->details_flags;
- sfile->params->filter_id = sfile_udata->filter_id;
+ params->thumbnail_size = sfile_udata->thumbnail_size;
+ params->details_flags = sfile_udata->details_flags;
+ params->filter_id = sfile_udata->filter_id;
/* Combine flags we take from params with the flags we take from userdef. */
- sfile->params->flag = (sfile->params->flag & ~PARAMS_FLAGS_REMEMBERED) |
- (sfile_udata->flag & PARAMS_FLAGS_REMEMBERED);
+ params->flag = (params->flag & ~PARAMS_FLAGS_REMEMBERED) |
+ (sfile_udata->flag & PARAMS_FLAGS_REMEMBERED);
if (file_select_use_default_display_type(sfile)) {
- sfile->params->display = sfile_udata->display_type;
+ params->display = sfile_udata->display_type;
}
if (file_select_use_default_sort_type(sfile)) {
- sfile->params->sort = sfile_udata->sort_type;
+ params->sort = sfile_udata->sort_type;
/* For the default sorting, also take invert flag from userdef. */
- sfile->params->flag = (sfile->params->flag & ~FILE_SORT_INVERT) |
- (sfile_udata->flag & FILE_SORT_INVERT);
+ params->flag = (params->flag & ~FILE_SORT_INVERT) | (sfile_udata->flag & FILE_SORT_INVERT);
}
}
@@ -400,25 +526,26 @@ void ED_fileselect_params_to_userdef(SpaceFile *sfile,
const int temp_win_size[2],
const bool is_maximized)
{
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
UserDef_FileSpaceData *sfile_udata_new = &U.file_space_data;
UserDef_FileSpaceData sfile_udata_old = U.file_space_data;
- sfile_udata_new->thumbnail_size = sfile->params->thumbnail_size;
- sfile_udata_new->details_flags = sfile->params->details_flags;
- sfile_udata_new->flag = sfile->params->flag & PARAMS_FLAGS_REMEMBERED;
- sfile_udata_new->filter_id = sfile->params->filter_id;
+ sfile_udata_new->thumbnail_size = params->thumbnail_size;
+ sfile_udata_new->details_flags = params->details_flags;
+ sfile_udata_new->flag = params->flag & PARAMS_FLAGS_REMEMBERED;
+ sfile_udata_new->filter_id = params->filter_id;
/* In some rare cases, operators ask for a specific display or sort type (e.g. chronological
* sorting for "Recover Auto Save"). So the settings are optimized for a specific operation.
* Don't let that change the userdef memory for more general cases. */
if (file_select_use_default_display_type(sfile)) {
- sfile_udata_new->display_type = sfile->params->display;
+ sfile_udata_new->display_type = params->display;
}
if (file_select_use_default_sort_type(sfile)) {
- sfile_udata_new->sort_type = sfile->params->sort;
+ sfile_udata_new->sort_type = params->sort;
/* In this case also remember the invert flag. */
sfile_udata_new->flag = (sfile_udata_new->flag & ~FILE_SORT_INVERT) |
- (sfile->params->flag & FILE_SORT_INVERT);
+ (params->flag & FILE_SORT_INVERT);
}
if (temp_win_size && !is_maximized) {
@@ -432,14 +559,6 @@ void ED_fileselect_params_to_userdef(SpaceFile *sfile,
}
}
-void ED_fileselect_reset_params(SpaceFile *sfile)
-{
- sfile->params->type = FILE_UNIX;
- sfile->params->flag = 0;
- sfile->params->title[0] = '\0';
- sfile->params->active_file = -1;
-}
-
/**
* Sets FileSelectParams->file (name of selected file)
*/
@@ -447,7 +566,8 @@ void fileselect_file_set(SpaceFile *sfile, const int index)
{
const struct FileDirEntry *file = filelist_file(sfile->files, index);
if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_DIR)) {
- BLI_strncpy(sfile->params->file, file->relpath, FILE_MAXFILE);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+ BLI_strncpy(params->file, file->relpath, FILE_MAXFILE);
}
}
@@ -759,7 +879,7 @@ static void file_attribute_columns_init(const FileSelectParams *params, FileLayo
void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *region)
{
- FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
FileLayout *layout = NULL;
View2D *v2d = &region->v2d;
int numfiles;
@@ -873,7 +993,8 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area)
return;
}
SpaceFile *sfile = area->spacedata.first;
- if (sfile->params) {
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+ if (params) {
wmWindowManager *wm = CTX_wm_manager(C);
Scene *scene = WM_windows_scene_get_from_screen(wm, screen);
if (LIKELY(scene != NULL)) {
@@ -882,20 +1003,20 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area)
/* Clear search string, it is very rare to want to keep that filter while changing dir,
* and usually very annoying to keep it actually! */
- sfile->params->filter_search[0] = '\0';
- sfile->params->active_file = -1;
+ params->filter_search[0] = '\0';
+ params->active_file = -1;
- if (!filelist_is_dir(sfile->files, sfile->params->dir)) {
- BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir));
+ if (!filelist_is_dir(sfile->files, params->dir)) {
+ BLI_strncpy(params->dir, filelist_dir(sfile->files), sizeof(params->dir));
/* could return but just refresh the current dir */
}
- filelist_setdir(sfile->files, sfile->params->dir);
+ filelist_setdir(sfile->files, params->dir);
if (folderlist_clear_next(sfile)) {
folderlist_free(sfile->folders_next);
}
- folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
+ folderlist_pushdir(sfile->folders_prev, params->dir);
file_draw_check_ex(C, area);
}
@@ -1010,7 +1131,8 @@ void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfi
filelist_clear(sfile->files);
}
- sfile->params->highlight_file = -1;
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+ params->highlight_file = -1;
WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
@@ -1036,8 +1158,7 @@ void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfil
sfile->op = NULL;
}
- folderlist_free(sfile->folders_prev);
- folderlist_free(sfile->folders_next);
+ folder_history_list_free(sfile);
if (sfile->files) {
ED_fileselect_clear(wm, owner_scene, sfile);
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 6ffe553e076..774dc54700c 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -35,6 +35,8 @@
#include "BKE_screen.h"
#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_message.h"
@@ -55,6 +57,23 @@
#include "filelist.h"
#include "fsmenu.h"
+static ARegion *file_ui_region_ensure(ScrArea *area, ARegion *region_prev)
+{
+ ARegion *region;
+
+ if ((region = BKE_area_find_region_type(area, RGN_TYPE_UI)) != NULL) {
+ return region;
+ }
+
+ region = MEM_callocN(sizeof(ARegion), "execute region for file");
+ BLI_insertlinkafter(&area->regionbase, region_prev, region);
+ region->regiontype = RGN_TYPE_UI;
+ region->alignment = RGN_ALIGN_TOP;
+ region->flag = RGN_FLAG_DYNAMIC_SIZE;
+
+ return region;
+}
+
static ARegion *file_execute_region_ensure(ScrArea *area, ARegion *region_prev)
{
ARegion *region;
@@ -149,22 +168,10 @@ static void file_free(SpaceLink *sl)
sfile->files = NULL;
}
- if (sfile->folders_prev) {
- folderlist_free(sfile->folders_prev);
- MEM_freeN(sfile->folders_prev);
- sfile->folders_prev = NULL;
- }
+ folder_history_list_free(sfile);
- if (sfile->folders_next) {
- folderlist_free(sfile->folders_next);
- MEM_freeN(sfile->folders_next);
- sfile->folders_next = NULL;
- }
-
- if (sfile->params) {
- MEM_freeN(sfile->params);
- sfile->params = NULL;
- }
+ MEM_SAFE_FREE(sfile->params);
+ MEM_SAFE_FREE(sfile->asset_params);
if (sfile->layout) {
MEM_freeN(sfile->layout);
@@ -205,19 +212,20 @@ static SpaceLink *file_duplicate(SpaceLink *sl)
sfilen->previews_timer = NULL;
sfilen->smoothscroll_timer = NULL;
+ FileSelectParams *active_params_old = ED_fileselect_get_active_params(sfileo);
+ if (active_params_old) {
+ sfilen->files = filelist_new(active_params_old->type);
+ filelist_setdir(sfilen->files, active_params_old->dir);
+ }
+
if (sfileo->params) {
- sfilen->files = filelist_new(sfileo->params->type);
sfilen->params = MEM_dupallocN(sfileo->params);
- filelist_setdir(sfilen->files, sfilen->params->dir);
}
-
- if (sfileo->folders_prev) {
- sfilen->folders_prev = folderlist_duplicate(sfileo->folders_prev);
+ if (sfileo->asset_params) {
+ sfilen->asset_params = MEM_dupallocN(sfileo->asset_params);
}
- if (sfileo->folders_next) {
- sfilen->folders_next = folderlist_duplicate(sfileo->folders_next);
- }
+ sfilen->folder_histories = folder_history_list_duplicate(&sfileo->folder_histories);
if (sfileo->layout) {
sfilen->layout = MEM_dupallocN(sfileo->layout);
@@ -232,15 +240,30 @@ static void file_ensure_valid_region_state(bContext *C,
SpaceFile *sfile,
FileSelectParams *params)
{
- ARegion *region_ui = BKE_area_find_region_type(area, RGN_TYPE_UI);
- ARegion *region_props = BKE_area_find_region_type(area, RGN_TYPE_TOOL_PROPS);
- ARegion *region_execute = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE);
+ ARegion *region_tools = BKE_area_find_region_type(area, RGN_TYPE_TOOLS);
bool needs_init = false; /* To avoid multiple ED_area_init() calls. */
+ BLI_assert(region_tools);
+
+ if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) {
+ ARegion *region_execute = file_execute_region_ensure(area, region_tools);
+ ARegion *region_props = file_tool_props_region_ensure(area, region_execute);
+
+ /* Hide specific regions by default. */
+ region_props->flag |= RGN_FLAG_HIDDEN;
+ region_execute->flag |= RGN_FLAG_HIDDEN;
+
+ ARegion *region_ui = BKE_area_find_region_type(area, RGN_TYPE_UI);
+ if (region_ui) {
+ ED_region_remove(C, area, region_ui);
+ needs_init = true;
+ }
+ }
/* If there's an file-operation, ensure we have the option and execute region */
- if (sfile->op && (region_props == NULL)) {
- region_execute = file_execute_region_ensure(area, region_ui);
- region_props = file_tool_props_region_ensure(area, region_execute);
+ else if (sfile->op) {
+ ARegion *region_ui = file_ui_region_ensure(area, region_tools);
+ ARegion *region_execute = file_execute_region_ensure(area, region_ui);
+ ARegion *region_props = file_tool_props_region_ensure(area, region_execute);
if (params->flag & FILE_HIDE_TOOL_PROPS) {
region_props->flag |= RGN_FLAG_HIDDEN;
@@ -252,12 +275,19 @@ static void file_ensure_valid_region_state(bContext *C,
needs_init = true;
}
/* If there's _no_ file-operation, ensure we _don't_ have the option and execute region */
- else if ((sfile->op == NULL) && (region_props != NULL)) {
- BLI_assert(region_execute != NULL);
+ else {
+ ARegion *region_props = BKE_area_find_region_type(area, RGN_TYPE_TOOL_PROPS);
+ ARegion *region_execute = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE);
+ ARegion *region_ui = file_ui_region_ensure(area, region_tools);
+ UNUSED_VARS(region_ui);
- ED_region_remove(C, area, region_props);
- ED_region_remove(C, area, region_execute);
- needs_init = true;
+ if (region_props) {
+ BLI_assert(region_execute);
+
+ ED_region_remove(C, area, region_props);
+ ED_region_remove(C, area, region_execute);
+ needs_init = true;
+ }
}
if (needs_init) {
@@ -265,24 +295,42 @@ static void file_ensure_valid_region_state(bContext *C,
}
}
+/**
+ * Tag the space to recreate the file-list.
+ */
+static void file_tag_reset_list(ScrArea *area, SpaceFile *sfile)
+{
+ filelist_tag_force_reset(sfile->files);
+ ED_area_tag_refresh(area);
+}
+
static void file_refresh(const bContext *C, ScrArea *area)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileSelectParams *params = ED_fileselect_ensure_active_params(sfile);
+ FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
struct FSMenu *fsmenu = ED_fsmenu_get();
- if (!sfile->folders_prev) {
- sfile->folders_prev = folderlist_new();
+ fileselect_refresh_params(sfile);
+ folder_history_list_ensure_for_active_browse_mode(sfile);
+
+ if (sfile->files && (sfile->tags & FILE_TAG_REBUILD_MAIN_FILES) &&
+ filelist_needs_reset_on_main_changes(sfile->files)) {
+ filelist_tag_force_reset(sfile->files);
}
+ sfile->tags &= ~FILE_TAG_REBUILD_MAIN_FILES;
+
if (!sfile->files) {
sfile->files = filelist_new(params->type);
params->highlight_file = -1; /* added this so it opens nicer (ton) */
}
+ filelist_settype(sfile->files, params->type);
filelist_setdir(sfile->files, params->dir);
filelist_setrecursion(sfile->files, params->recursion_level);
filelist_setsorting(sfile->files, params->sort, params->flag & FILE_SORT_INVERT);
+ filelist_setlibrary(sfile->files, asset_params ? &asset_params->asset_library : NULL);
filelist_setfilter_options(
sfile->files,
(params->flag & FILE_FILTER) != 0,
@@ -290,6 +338,7 @@ static void file_refresh(const bContext *C, ScrArea *area)
true, /* Just always hide parent, prefer to not add an extra user option for this. */
params->filter,
params->filter_id,
+ (params->flag & FILE_ASSETS_ONLY) != 0,
params->filter_glob,
params->filter_search);
@@ -300,12 +349,12 @@ static void file_refresh(const bContext *C, ScrArea *area)
sfile->bookmarknr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir);
sfile->recentnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_RECENT, params->dir);
- if (filelist_force_reset(sfile->files)) {
+ if (filelist_needs_force_reset(sfile->files)) {
filelist_readjob_stop(wm, CTX_data_scene(C));
filelist_clear(sfile->files);
}
- if (filelist_empty(sfile->files)) {
+ if (filelist_needs_reading(sfile->files)) {
if (!filelist_pending(sfile->files)) {
filelist_readjob_start(sfile->files, C);
}
@@ -363,8 +412,21 @@ static void file_listener(wmWindow *UNUSED(win),
ED_area_tag_refresh(area);
}
break;
+ case ND_SPACE_ASSET_PARAMS:
+ if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) {
+ ED_area_tag_refresh(area);
+ }
+ break;
}
break;
+ case NC_ASSET: {
+ if (sfile->files && filelist_needs_reset_on_main_changes(sfile->files)) {
+ /* Full refresh of the file list if local asset data was changed. Refreshing this view is
+ * cheap and users expect this to be updated immediately. */
+ file_tag_reset_list(area, sfile);
+ }
+ break;
+ }
}
}
@@ -413,7 +475,7 @@ static void file_main_region_message_subscribe(const struct bContext *UNUSED(C),
struct wmMsgBus *mbus)
{
SpaceFile *sfile = area->spacedata.first;
- FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileSelectParams *params = ED_fileselect_ensure_active_params(sfile);
/* This is a bit odd that a region owns the subscriber for an area,
* keep for now since all subscribers for WM are regions.
* May be worth re-visiting later. */
@@ -442,16 +504,31 @@ static void file_main_region_message_subscribe(const struct bContext *UNUSED(C),
}
}
+static bool file_main_region_needs_refresh_before_draw(SpaceFile *sfile)
+{
+ /* Needed, because filelist is not initialized on loading */
+ if (!sfile->files || filelist_needs_reading(sfile->files)) {
+ return true;
+ }
+
+ /* File reading tagged the space because main data changed that may require a filelist reset. */
+ if (filelist_needs_reset_on_main_changes(sfile->files) &&
+ (sfile->tags & FILE_TAG_REBUILD_MAIN_FILES)) {
+ return true;
+ }
+
+ return false;
+}
+
static void file_main_region_draw(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileSelectParams *params = ED_fileselect_ensure_active_params(sfile);
View2D *v2d = &region->v2d;
- /* Needed, because filelist is not initialized on loading */
- if (!sfile->files || filelist_empty(sfile->files)) {
+ if (file_main_region_needs_refresh_before_draw(sfile)) {
file_refresh(C, NULL);
}
@@ -497,7 +574,9 @@ static void file_main_region_draw(const bContext *C, ARegion *region)
file_highlight_set(sfile, region, event->x, event->y);
}
- file_draw_list(C, region);
+ if (!file_draw_hint_if_invalid(sfile, region)) {
+ file_draw_list(C, region);
+ }
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -681,6 +760,87 @@ static void file_dropboxes(void)
WM_dropbox_add(lb, "FILE_OT_filepath_drop", filepath_drop_poll, filepath_drop_copy);
}
+static int file_space_subtype_get(ScrArea *area)
+{
+ SpaceFile *sfile = area->spacedata.first;
+ return sfile->browse_mode;
+}
+
+static void file_space_subtype_set(ScrArea *area, int value)
+{
+ SpaceFile *sfile = area->spacedata.first;
+ sfile->browse_mode = value;
+}
+
+static void file_space_subtype_item_extend(bContext *UNUSED(C),
+ EnumPropertyItem **item,
+ int *totitem)
+{
+ RNA_enum_items_add(item, totitem, rna_enum_space_file_browse_mode_items);
+}
+
+static const char *file_context_dir[] = {"active_file", "active_id", NULL};
+
+static int /*eContextResult*/ file_context(const bContext *C,
+ const char *member,
+ bContextDataResult *result)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+
+ BLI_assert(!ED_area_is_global(CTX_wm_area(C)));
+
+ if (CTX_data_dir(member)) {
+ CTX_data_dir_set(result, file_context_dir);
+ return CTX_RESULT_OK;
+ }
+
+ /* The following member checks return file-list data, check if that needs refreshing first. */
+ if (file_main_region_needs_refresh_before_draw(sfile)) {
+ return CTX_RESULT_NO_DATA;
+ }
+
+ if (CTX_data_equals(member, "active_file")) {
+ FileDirEntry *file = filelist_file(sfile->files, params->active_file);
+ if (file == NULL) {
+ return CTX_RESULT_NO_DATA;
+ }
+
+ CTX_data_pointer_set(result, &screen->id, &RNA_FileSelectEntry, file);
+ return CTX_RESULT_OK;
+ }
+ if (CTX_data_equals(member, "id")) {
+ const FileDirEntry *file = filelist_file(sfile->files, params->active_file);
+ if (file == NULL) {
+ return CTX_RESULT_NO_DATA;
+ }
+
+ ID *id = filelist_file_get_id(file);
+ if (id == NULL) {
+ return CTX_RESULT_NO_DATA;
+ }
+
+ CTX_data_id_pointer_set(result, id);
+ return CTX_RESULT_OK;
+ }
+
+ return CTX_RESULT_MEMBER_NOT_FOUND;
+}
+
+static void file_id_remap(ScrArea *area, SpaceLink *sl, ID *UNUSED(old_id), ID *UNUSED(new_id))
+{
+ SpaceFile *sfile = (SpaceFile *)sl;
+
+ /* If the file shows main data (IDs), tag it for reset. */
+ if (sfile->files && filelist_needs_reset_on_main_changes(sfile->files)) {
+ /* Full refresh of the file list if main data was changed, don't even attempt remap pointers.
+ * We could give file list types a id-remap callback, but it's probably not worth it.
+ * Refreshing local file lists is relatively cheap. */
+ file_tag_reset_list(area, sfile);
+ }
+}
+
/* only called once, from space/spacetypes.c */
void ED_spacetype_file(void)
{
@@ -700,6 +860,11 @@ void ED_spacetype_file(void)
st->operatortypes = file_operatortypes;
st->keymap = file_keymap;
st->dropboxes = file_dropboxes;
+ st->space_subtype_item_extend = file_space_subtype_item_extend;
+ st->space_subtype_get = file_space_subtype_get;
+ st->space_subtype_set = file_space_subtype_set;
+ st->context = file_context;
+ st->id_remap = file_id_remap;
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
diff --git a/source/blender/editors/space_graph/CMakeLists.txt b/source/blender/editors/space_graph/CMakeLists.txt
index 414e5c87f5a..2a795dd954c 100644
--- a/source/blender/editors/space_graph/CMakeLists.txt
+++ b/source/blender/editors/space_graph/CMakeLists.txt
@@ -34,8 +34,8 @@ set(SRC
graph_draw.c
graph_edit.c
graph_ops.c
- graph_slider_ops.c
graph_select.c
+ graph_slider_ops.c
graph_utils.c
graph_view.c
space_graph.c
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index ae34cd6cf6d..e56d71913d6 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -72,7 +72,9 @@
/* ************************************************************************** */
/* INSERT DUPLICATE AND BAKE KEYFRAMES */
-/* ******************** Insert Keyframes Operator ************************* */
+/* -------------------------------------------------------------------- */
+/** \name Insert Keyframes Operator
+ * \{ */
/* Mode defines for insert keyframes tool. */
typedef enum eGraphKeys_InsertKey_Types {
@@ -290,7 +292,11 @@ void GRAPH_OT_keyframe_insert(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_insertkey_types, 0, "Type", "");
}
-/* ******************** Click-Insert Keyframes Operator ************************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Click-Insert Keyframes Operator
+ * \{ */
static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
{
@@ -444,8 +450,13 @@ void GRAPH_OT_click_insert(wmOperatorType *ot)
"Extend selection instead of deselecting everything first");
}
-/* ******************** Copy/Paste Keyframes Operator ************************* */
-/* NOTE: the backend code for this is shared with the dopesheet editor */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Copy/Paste Keyframes Operator
+ *
+ * \note the back-end code for this is shared with the dope-sheet editor.
+ * \{ */
static short copy_graph_keys(bAnimContext *ac)
{
@@ -605,7 +616,11 @@ void GRAPH_OT_paste(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ******************** Duplicate Keyframes Operator ************************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Duplicate Keyframes Operator
+ * \{ */
static void duplicate_graph_keys(bAnimContext *ac)
{
@@ -667,7 +682,11 @@ void GRAPH_OT_duplicate(wmOperatorType *ot)
RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
}
-/* ******************** Delete Keyframes Operator ************************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Keyframes Operator
+ * \{ */
static bool delete_graph_keys(bAnimContext *ac)
{
@@ -746,7 +765,11 @@ void GRAPH_OT_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************** Clean Keyframes Operator ************************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clean Keyframes Operator
+ * \{ */
static void clean_graph_keys(bAnimContext *ac, float thresh, bool clean_chan)
{
@@ -816,8 +839,13 @@ void GRAPH_OT_clean(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "channels", false, "Channels", "");
}
-/* ******************** Bake F-Curve Operator *********************** */
-/* This operator bakes the data of the selected F-Curves to F-Points */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Bake F-Curve Operator
+ *
+ * This operator bakes the data of the selected F-Curves to F-Points.
+ * \{ */
/* Bake each F-Curve into a set of samples. */
static void bake_graph_curves(bAnimContext *ac, int start, int end)
@@ -899,8 +927,13 @@ void GRAPH_OT_bake(wmOperatorType *ot)
/* TODO: add props for start/end frames (Joshua Leung 2009) */
}
-/* ******************** Un-Bake F-Curve Operator *********************** */
-/* This operator unbakes the data of the selected F-Points to F-Curves. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Un-Bake F-Curve Operator
+ *
+ * This operator un-bakes the data of the selected F-Points to F-Curves.
+ * \{ */
/* Un-Bake F-Points into F-Curves. */
static void unbake_graph_curves(bAnimContext *ac, int start, int end)
@@ -970,8 +1003,13 @@ void GRAPH_OT_unbake(wmOperatorType *ot)
#ifdef WITH_AUDASPACE
-/* ******************** Sound Bake F-Curve Operator *********************** */
-/* This operator bakes the given sound to the selected F-Curves */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Sound Bake F-Curve Operator
+ *
+ * This operator bakes the given sound to the selected F-Curves.
+ * \{ */
/* ------------------- */
@@ -1204,10 +1242,14 @@ void GRAPH_OT_sound_bake(wmOperatorType *ot)
0.1);
}
-/* ******************** Sample Keyframes Operator *********************** */
-/* This operator 'bakes' the values of the curve into new keyframes between pairs
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Sample Keyframes Operator
+ *
+ * This operator 'bakes' the values of the curve into new keyframes between pairs
* of selected keyframes. It is useful for creating keyframes for tweaking overlap.
- */
+ * \{ */
/* Evaluates the curves between each selected keyframe on each frame, and keys the value. */
static void sample_graph_keys(bAnimContext *ac)
@@ -1267,10 +1309,14 @@ void GRAPH_OT_sample(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
/* ************************************************************************** */
/* EXTRAPOLATION MODE AND KEYFRAME HANDLE SETTINGS */
-/* ******************** Set Extrapolation-Type Operator *********************** */
+/* -------------------------------------------------------------------- */
+/** \name Set Extrapolation-Type Operator
+ * \{ */
/* Defines for make/clear cyclic extrapolation tools. */
#define MAKE_CYCLIC_EXPO -1
@@ -1400,7 +1446,11 @@ void GRAPH_OT_extrapolation_type(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_expo_types, 0, "Type", "");
}
-/* ******************** Set Interpolation-Type Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Interpolation-Type Operator
+ * \{ */
/* This function is responsible for setting interpolation mode for keyframes. */
static void setipo_graph_keys(bAnimContext *ac, short mode)
@@ -1474,7 +1524,11 @@ void GRAPH_OT_interpolation_type(wmOperatorType *ot)
ot->srna, "type", rna_enum_beztriple_interpolation_mode_items, 0, "Type", "");
}
-/* ******************** Set Easing Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Easing Operator
+ * \{ */
static void seteasing_graph_keys(bAnimContext *ac, short mode)
{
@@ -1545,7 +1599,11 @@ void GRAPH_OT_easing_type(wmOperatorType *ot)
ot->srna, "type", rna_enum_beztriple_interpolation_easing_items, 0, "Type", "");
}
-/* ******************** Set Handle-Type Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Handle-Type Operator
+ * \{ */
/* This function is responsible for setting handle-type of selected keyframes. */
static void sethandles_graph_keys(bAnimContext *ac, short mode)
@@ -1624,15 +1682,19 @@ void GRAPH_OT_handle_type(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", "");
}
+/** \} */
+
/* ************************************************************************** */
/* EULER FILTER */
-/* ***************** 'Euler Filter' Operator **************************** */
-/* Euler filter tools (as seen in Maya), are necessary for working with 'baked'
+/* -------------------------------------------------------------------- */
+/** \name 'Euler Filter' Operator
+ *
+ * Euler filter tools (as seen in Maya), are necessary for working with 'baked'
* rotation curves (with Euler rotations). The main purpose of such tools is to
* resolve any discontinuities that may arise in the curves due to the clamping
* of values to -180 degrees to 180 degrees.
- */
+ * \{ */
/* Set of three euler-rotation F-Curves. */
typedef struct tEulerFilter {
@@ -1955,10 +2017,14 @@ void GRAPH_OT_euler_filter(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
/* ************************************************************************** */
/* SNAPPING */
-/* ***************** Jump to Selected Frames Operator *********************** */
+/* -------------------------------------------------------------------- */
+/** \name Jump to Selected Frames Operator
+ * \{ */
static bool graphkeys_framejump_poll(bContext *C)
{
@@ -2110,7 +2176,11 @@ void GRAPH_OT_snap_cursor_value(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************** Snap Keyframes Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snap Keyframes Operator
+ * \{ */
/* Defines for snap keyframes tool. */
static const EnumPropertyItem prop_graphkeys_snap_types[] = {
@@ -2262,7 +2332,11 @@ void GRAPH_OT_snap(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_snap_types, 0, "Type", "");
}
-/* ******************** Mirror Keyframes Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mirror Keyframes Operator
+ * \{ */
/* Defines for mirror keyframes tool. */
static const EnumPropertyItem prop_graphkeys_mirror_types[] = {
@@ -2280,12 +2354,12 @@ static const EnumPropertyItem prop_graphkeys_mirror_types[] = {
{GRAPHKEYS_MIRROR_YAXIS,
"YAXIS",
0,
- "By Times Over Time=0",
+ "By Times Over Zero Time",
"Flip times of selected keyframes, effectively reversing the order they appear in"},
{GRAPHKEYS_MIRROR_XAXIS,
"XAXIS",
0,
- "By Values Over Value=0",
+ "By Values Over Zero Value",
"Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"},
{GRAPHKEYS_MIRROR_MARKER,
"MARKER",
@@ -2421,7 +2495,11 @@ void GRAPH_OT_mirror(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_mirror_types, 0, "Type", "");
}
-/* ******************** Smooth Keyframes Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Smooth Keyframes Operator
+ * \{ */
static int graphkeys_smooth_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -2475,10 +2553,14 @@ void GRAPH_OT_smooth(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
/* ************************************************************************** */
/* F-CURVE MODIFIERS */
-/* ******************** Add F-Modifier Operator *********************** */
+/* -------------------------------------------------------------------- */
+/** \name Add F-Modifier Operator
+ * \{ */
static const EnumPropertyItem *graph_fmodifier_itemf(bContext *C,
PointerRNA *UNUSED(ptr),
@@ -2596,7 +2678,11 @@ void GRAPH_OT_fmodifier_add(wmOperatorType *ot)
ot->srna, "only_active", 1, "Only Active", "Only add F-Modifier to active F-Curve");
}
-/* ******************** Copy F-Modifiers Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Copy F-Modifiers Operator
+ * \{ */
static int graph_fmodifier_copy_exec(bContext *C, wmOperator *op)
{
@@ -2658,7 +2744,11 @@ void GRAPH_OT_fmodifier_copy(wmOperatorType *ot)
#endif
}
-/* ******************** Paste F-Modifiers Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Paste F-Modifiers Operator
+ * \{ */
static int graph_fmodifier_paste_exec(bContext *C, wmOperator *op)
{
@@ -2746,10 +2836,14 @@ void GRAPH_OT_fmodifier_paste(wmOperatorType *ot)
"Replace existing F-Modifiers, instead of just appending to the end of the existing list");
}
+/** \} */
+
/* ************************************************************************** */
/* Drivers */
-/* ******************** Copy Driver Vars Operator *********************** */
+/* -------------------------------------------------------------------- */
+/** \name Copy Driver Variables Operator
+ * \{ */
static int graph_driver_vars_copy_exec(bContext *C, wmOperator *op)
{
@@ -2786,7 +2880,11 @@ void GRAPH_OT_driver_variables_copy(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************** Paste Driver Vars Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Paste Driver Variables Operator
+ * \{ */
static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op)
{
@@ -2838,7 +2936,11 @@ void GRAPH_OT_driver_variables_paste(wmOperatorType *ot)
"existing list");
}
-/* ************************************************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Invalid Drivers Operator
+ * \{ */
static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op)
{
@@ -2926,3 +3028,5 @@ void GRAPH_OT_driver_delete_invalid(wmOperatorType *ot)
/* Flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/** \} */
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 12035ab6b61..4ab4ef518fb 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -1288,8 +1288,8 @@ void GRAPH_OT_select_less(wmOperatorType *ot)
/* defines for left-right select tool */
static const EnumPropertyItem prop_graphkeys_leftright_select_types[] = {
{GRAPHKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
- {GRAPHKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
- {GRAPHKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
+ {GRAPHKEYS_LRSEL_LEFT, "LEFT", 0, "Before Current Frame", ""},
+ {GRAPHKEYS_LRSEL_RIGHT, "RIGHT", 0, "After Current Frame", ""},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c
index 0b9ba3762a3..cde0dab3503 100644
--- a/source/blender/editors/space_graph/graph_view.c
+++ b/source/blender/editors/space_graph/graph_view.c
@@ -533,4 +533,4 @@ void GRAPH_OT_ghost_curves_clear(wmOperatorType *ot)
/* Flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-} \ No newline at end of file
+}
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index c0c0280959c..1996f05b36a 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -86,26 +86,9 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void *
{
uiBlock *block = uiLayoutGetBlock(layout);
Image *image = image_p;
- int slot_id;
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 0,
- IFACE_("Slot"),
- 0,
- 0,
- UI_UNIT_X * 5,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- uiItemS(layout);
-
- slot_id = BLI_listbase_count(&image->renderslots) - 1;
- for (RenderSlot *slot = image->renderslots.last; slot; slot = slot->prev) {
+ int slot_id;
+ LISTBASE_FOREACH_INDEX (RenderSlot *, slot, &image->renderslots, slot_id) {
char str[64];
if (slot->name[0] != '\0') {
BLI_strncpy(str, slot->name, sizeof(str));
@@ -127,8 +110,23 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void *
0,
-1,
"");
- slot_id--;
}
+
+ uiItemS(layout);
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Slot"),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
}
static bool ui_imageuser_slot_menu_step(bContext *C, int direction, void *image_p)
@@ -175,14 +173,9 @@ static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void
Image *image = rnd_data->image;
ImageUser *iuser = rnd_data->iuser;
Scene *scene = iuser->scene;
- RenderResult *rr;
- RenderLayer *rl;
- RenderLayer rl_fake = {NULL};
- const char *fake_name;
- int nr;
- /* may have been freed since drawing */
- rr = BKE_image_acquire_renderresult(scene, image);
+ /* May have been freed since drawing. */
+ RenderResult *rr = BKE_image_acquire_renderresult(scene, image);
if (UNLIKELY(rr == NULL)) {
return;
}
@@ -190,32 +183,26 @@ static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void
UI_block_layout_set_current(block, layout);
uiLayoutColumn(layout, false);
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 0,
- IFACE_("Layer"),
- 0,
- 0,
- UI_UNIT_X * 5,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- uiItemS(layout);
-
- nr = BLI_listbase_count(&rr->layers) - 1;
- fake_name = ui_imageuser_layer_fake_name(rr);
-
+ const char *fake_name = ui_imageuser_layer_fake_name(rr);
if (fake_name) {
- BLI_strncpy(rl_fake.name, fake_name, sizeof(rl_fake.name));
- nr += 1;
+ uiDefButS(block,
+ UI_BTYPE_BUT_MENU,
+ B_NOP,
+ fake_name,
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_X,
+ &iuser->layer,
+ 0.0,
+ 0.0,
+ 0,
+ -1,
+ "");
}
- for (rl = rr->layers.last; rl; rl = rl->prev, nr--) {
- final:
+ int nr = fake_name ? 1 : 0;
+ for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next, nr++) {
uiDefButS(block,
UI_BTYPE_BUT_MENU,
B_NOP,
@@ -232,13 +219,21 @@ static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void
"");
}
- if (fake_name) {
- fake_name = NULL;
- rl = &rl_fake;
- goto final;
- }
-
- BLI_assert(nr == -1);
+ uiItemS(layout);
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Layer"),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
BKE_image_release_renderresult(scene, image);
}
@@ -268,23 +263,6 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
UI_block_layout_set_current(block, layout);
uiLayoutColumn(layout, false);
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 0,
- IFACE_("Pass"),
- 0,
- 0,
- UI_UNIT_X * 5,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
-
- uiItemS(layout);
-
nr = (rl == NULL) ? 1 : 0;
ListBase added_passes;
@@ -315,6 +293,22 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
"");
}
+ uiItemS(layout);
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Pass"),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+
BLI_freelistN(&added_passes);
BKE_image_release_renderresult(scene, image);
@@ -806,7 +800,8 @@ void uiTemplateImage(uiLayout *layout,
C,
ptr,
propname,
- ima ? NULL : "IMAGE_OT_new",
+ "IMAGE_OT_new",
+ NULL,
"IMAGE_OT_open",
NULL,
UI_TEMPLATE_ID_FILTER_ALL,
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index 180f1fb183c..c26f92c5463 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -407,6 +407,9 @@ bool ED_image_slot_cycle(struct Image *image, int direction)
image->render_slot = ((cur == 1) ? 0 : 1);
}
+ if ((cur != image->render_slot)) {
+ image->gpuflag |= IMA_GPU_REFRESH;
+ }
return (cur != image->render_slot);
}
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 0fa48059cdc..a2c0819dc60 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -2649,7 +2649,7 @@ void IMAGE_OT_new(wmOperatorType *ot)
"Generated Type",
"Fill the image with a grid for UV map testing");
RNA_def_boolean(
- ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
+ ot->srna, "float", 0, "32-bit Float", "Create image with 32-bit floating-point bit depth");
RNA_def_property_flag(prop, PROP_HIDDEN);
prop = RNA_def_boolean(
ot->srna, "use_stereo_3d", 0, "Stereo 3D", "Create an image with left and right views");
@@ -3737,7 +3737,7 @@ static void def_fill_tile(StructOrFunctionRNA *srna)
/* Only needed when filling the first tile. */
RNA_def_boolean(
- srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
+ srna, "float", 0, "32-bit Float", "Create image with 32-bit floating-point bit depth");
RNA_def_boolean(srna, "alpha", 1, "Alpha", "Create an image with an alpha channel");
}
diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c
index 3ba088018c3..7dd8382c8ef 100644
--- a/source/blender/editors/space_info/info_report.c
+++ b/source/blender/editors/space_info/info_report.c
@@ -396,7 +396,7 @@ void INFO_OT_report_copy(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Copy Reports to Clipboard";
- ot->description = "Copy selected reports to Clipboard";
+ ot->description = "Copy selected reports to clipboard";
ot->idname = "INFO_OT_report_copy";
/* api callbacks */
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 083fd641dc1..218fc3b7141 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -292,8 +292,9 @@ static void nla_panel_animdata(const bContext *C, Panel *panel)
(bContext *)C,
&adt_ptr,
"action",
- "ACTION_OT_new",
NULL,
+ "ACTION_OT_new",
+ "ACTION_OT_duplicate_assign",
"NLA_OT_action_unlink",
UI_TEMPLATE_ID_FILTER_ALL,
false,
@@ -345,7 +346,7 @@ static void nla_panel_stripname(const bContext *C, Panel *panel)
uiItemR(row, &strip_ptr, "name", 0, "", ICON_NLA);
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
uiItemR(row, &strip_ptr, "mute", 0, "", ICON_NONE);
UI_block_emboss_set(block, UI_EMBOSS);
}
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 561de5e82a6..9832ca975cf 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -292,7 +292,7 @@ static int mouse_nla_channels(
/* TODO: make this use the operator instead of calling the function directly
* however, calling the operator requires that we supply the args,
* and that works with proper buttons only */
- BKE_nla_action_pushdown(adt);
+ BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(ale->id));
}
else {
/* when in tweakmode, this button becomes the toggle for mapped editing */
@@ -516,7 +516,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
}
/* 'push-down' action - only usable when not in TweakMode */
- BKE_nla_action_pushdown(adt);
+ BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(id));
struct Main *bmain = CTX_data_main(C);
DEG_id_tag_update_ex(bmain, id, ID_RECALC_ANIMATION);
@@ -648,19 +648,21 @@ bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel)
NlaTrack *nlt = (NlaTrack *)ale->data;
AnimData *adt = ale->adt;
+ const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
+
/* check if just adding a new track above this one,
* or whether we're adding a new one to the top of the stack that this one belongs to
*/
if (above_sel) {
/* just add a new one above this one */
- BKE_nlatrack_add(adt, nlt);
+ BKE_nlatrack_add(adt, nlt, is_liboverride);
ale->update = ANIM_UPDATE_DEPS;
added = true;
}
else if ((lastAdt == NULL) || (adt != lastAdt)) {
/* add one track to the top of the owning AnimData's stack,
* then don't add anymore to this stack */
- BKE_nlatrack_add(adt, NULL);
+ BKE_nlatrack_add(adt, NULL, is_liboverride);
lastAdt = adt;
ale->update = ANIM_UPDATE_DEPS;
added = true;
@@ -698,7 +700,7 @@ bool nlaedit_add_tracks_empty(bAnimContext *ac)
/* ensure it is empty */
if (BLI_listbase_is_empty(&adt->nla_tracks)) {
/* add new track to this AnimData block then */
- BKE_nlatrack_add(adt, NULL);
+ BKE_nlatrack_add(adt, NULL, ID_IS_OVERRIDE_LIBRARY(ale->id));
ale->update = ANIM_UPDATE_DEPS;
added = true;
}
@@ -796,6 +798,11 @@ static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op))
NlaTrack *nlt = (NlaTrack *)ale->data;
AnimData *adt = ale->adt;
+ if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
+ /* No deletion of non-local tracks of override data. */
+ continue;
+ }
+
/* if track is currently 'solo', then AnimData should have its
* 'has solo' flag disabled
*/
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index ed8e5ad76e9..3fa1b614a03 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -649,6 +649,7 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
NlaTrack *nlt = (NlaTrack *)ale->data;
AnimData *adt = ale->adt;
NlaStrip *strip = NULL;
+ const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
/* Sanity check: only apply actions of the right type for this ID.
* NOTE: in the case that this hasn't been set,
@@ -671,12 +672,12 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
strip->start = cfra;
/* firstly try adding strip to our current track, but if that fails, add to a new track */
- if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
+ if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) {
/* trying to add to the current failed (no space),
* so add a new track to the stack, and add to that...
*/
- nlt = BKE_nlatrack_add(adt, NULL);
- BKE_nlatrack_add_strip(nlt, strip);
+ nlt = BKE_nlatrack_add(adt, NULL, is_liboverride);
+ BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
}
/* auto-name it */
@@ -886,6 +887,7 @@ static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op))
AnimData *adt = ale->adt;
NlaTrack *nlt = (NlaTrack *)ale->data;
NlaStrip *strip;
+ const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
/* does this belong to speaker - assumed to live on Object level only */
if ((GS(ale->id->name) != ID_OB) || (ob->type != OB_SPEAKER)) {
@@ -899,12 +901,12 @@ static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op))
strip->end += cfra;
/* firstly try adding strip to our current track, but if that fails, add to a new track */
- if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
+ if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) {
/* trying to add to the current failed (no space),
* so add a new track to the stack, and add to that...
*/
- nlt = BKE_nlatrack_add(adt, NULL);
- BKE_nlatrack_add_strip(nlt, strip);
+ nlt = BKE_nlatrack_add(adt, NULL, is_liboverride);
+ BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
}
/* auto-name it */
@@ -966,6 +968,11 @@ static int nlaedit_add_meta_exec(bContext *C, wmOperator *UNUSED(op))
AnimData *adt = ale->adt;
NlaStrip *strip;
+ if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
+ /* No making metastrips in non-local tracks of override data. */
+ continue;
+ }
+
/* create meta-strips from the continuous chains of selected strips */
BKE_nlastrips_make_metas(&nlt->strips, 0);
@@ -1030,6 +1037,11 @@ static int nlaedit_remove_meta_exec(bContext *C, wmOperator *UNUSED(op))
for (ale = anim_data.first; ale; ale = ale->next) {
NlaTrack *nlt = (NlaTrack *)ale->data;
+ if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
+ /* No removing metastrips from non-local tracks of override data. */
+ continue;
+ }
+
/* clear all selected meta-strips, regardless of whether they are temporary or not */
BKE_nlastrips_clear_metas(&nlt->strips, 1, 0);
@@ -1096,6 +1108,11 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
NlaStrip *strip, *nstrip, *next;
NlaTrack *track;
+ /* Note: We allow this operator in override context because it is almost always (from possible
+ * default user interactions) paired with the transform one, which will ensure that the new
+ * strip ends up in a valid (local) track. */
+
+ const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
for (strip = nlt->strips.first; strip; strip = next) {
next = strip->next;
@@ -1106,13 +1123,13 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
/* in case there's no space in the track above,
* or we haven't got a reference to it yet, try adding */
- if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) {
+ if (BKE_nlatrack_add_strip(nlt->next, nstrip, is_liboverride) == 0) {
/* need to add a new track above the one above the current one
* - if the current one is the last one, nlt->next will be NULL, which defaults to adding
* at the top of the stack anyway...
*/
- track = BKE_nlatrack_add(adt, nlt->next);
- BKE_nlatrack_add_strip(track, nstrip);
+ track = BKE_nlatrack_add(adt, nlt->next, is_liboverride);
+ BKE_nlatrack_add_strip(track, nstrip, is_liboverride);
}
/* deselect the original and the active flag */
@@ -1209,6 +1226,11 @@ static int nlaedit_delete_exec(bContext *C, wmOperator *UNUSED(op))
NlaTrack *nlt = (NlaTrack *)ale->data;
NlaStrip *strip, *nstrip;
+ if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
+ /* No deletion of strips in non-local tracks of override data. */
+ continue;
+ }
+
for (strip = nlt->strips.first; strip; strip = nstrip) {
nstrip = strip->next;
@@ -1359,6 +1381,11 @@ static int nlaedit_split_exec(bContext *C, wmOperator *UNUSED(op))
AnimData *adt = ale->adt;
NlaStrip *strip, *next;
+ if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
+ /* No splitting of strips in non-local tracks of override data. */
+ continue;
+ }
+
for (strip = nlt->strips.first; strip; strip = next) {
next = strip->next;
@@ -1502,6 +1529,12 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
NlaStrip *strip, *stripN = NULL;
NlaStrip *area = NULL, *sb = NULL;
+ const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
+
+ if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
+ /* No re-ordering of strips whithin non-local tracks of override data. */
+ continue;
+ }
/* make temporary metastrips so that entire islands of selections can be moved around */
BKE_nlastrips_make_metas(&nlt->strips, 1);
@@ -1610,8 +1643,8 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
}
/* add strips back to track now */
- BKE_nlatrack_add_strip(nlt, area);
- BKE_nlatrack_add_strip(nlt, sb);
+ BKE_nlatrack_add_strip(nlt, area, is_liboverride);
+ BKE_nlatrack_add_strip(nlt, sb, is_liboverride);
}
/* clear (temp) metastrips */
@@ -1674,11 +1707,19 @@ static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op))
NlaTrack *nltn = nlt->next;
NlaStrip *strip, *stripn;
+ const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
+
/* if this track has no tracks after it, skip for now... */
if (nltn == NULL) {
continue;
}
+ if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt) ||
+ BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nltn)) {
+ /* No moving of strips in non-local tracks of override data. */
+ continue;
+ }
+
/* for every selected strip, try to move */
for (strip = nlt->strips.first; strip; strip = stripn) {
stripn = strip->next;
@@ -1689,7 +1730,7 @@ static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op))
/* remove from its current track, and add to the one above
* (it 'should' work, so no need to worry) */
BLI_remlink(&nlt->strips, strip);
- BKE_nlatrack_add_strip(nltn, strip);
+ BKE_nlatrack_add_strip(nltn, strip, is_liboverride);
}
}
}
@@ -1751,11 +1792,19 @@ static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op))
NlaTrack *nltp = nlt->prev;
NlaStrip *strip, *stripn;
+ const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
+
/* if this track has no tracks before it, skip for now... */
if (nltp == NULL) {
continue;
}
+ if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt) ||
+ BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nltp)) {
+ /* No moving of strips in non-local tracks of override data. */
+ continue;
+ }
+
/* for every selected strip, try to move */
for (strip = nlt->strips.first; strip; strip = stripn) {
stripn = strip->next;
@@ -1766,7 +1815,7 @@ static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op))
/* remove from its current track, and add to the one above
* (it 'should' work, so no need to worry) */
BLI_remlink(&nlt->strips, strip);
- BKE_nlatrack_add_strip(nltp, strip);
+ BKE_nlatrack_add_strip(nltp, strip, is_liboverride);
}
}
}
@@ -2023,11 +2072,11 @@ static int nlaedit_apply_scale_exec(bContext *C, wmOperator *UNUSED(op))
/* strip must be selected, and must be action-clip only
* (transitions don't have scale) */
if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
- /* if the referenced action is used by other strips,
- * make this strip use its own copy */
- if (strip->act == NULL) {
+ if (strip->act == NULL || ID_IS_OVERRIDE_LIBRARY(strip->act) || ID_IS_LINKED(strip->act)) {
continue;
}
+ /* if the referenced action is used by other strips,
+ * make this strip use its own copy */
if (strip->act->id.us > 1) {
/* make a copy of the Action to work on */
bAction *act = (bAction *)BKE_id_copy(bmain, &strip->act->id);
@@ -2200,6 +2249,8 @@ static int nlaedit_snap_exec(bContext *C, wmOperator *op)
NlaStrip *strip, *stripn;
NlaTrack *track;
+ const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
+
/* create meta-strips from the continuous chains of selected strips */
BKE_nlastrips_make_metas(&nlt->strips, 1);
@@ -2255,10 +2306,10 @@ static int nlaedit_snap_exec(bContext *C, wmOperator *op)
BLI_remlink(&tmp_strips, strip);
/* in case there's no space in the current track, try adding */
- if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
+ if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) {
/* need to add a new track above the current one */
- track = BKE_nlatrack_add(adt, nlt);
- BKE_nlatrack_add_strip(track, strip);
+ track = BKE_nlatrack_add(adt, nlt, is_liboverride);
+ BKE_nlatrack_add_strip(track, strip, is_liboverride);
/* clear temp meta-strips on this new track,
* as we may not be able to get back to it */
@@ -2375,6 +2426,11 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
NlaTrack *nlt = (NlaTrack *)ale->data;
NlaStrip *strip;
+ if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
+ /* No adding f-modifiers to strips in non-local tracks of override data. */
+ continue;
+ }
+
for (strip = nlt->strips.first; strip; strip = strip->next) {
/* can F-Modifier be added to the current strip? */
if (active_only) {
@@ -2552,6 +2608,11 @@ static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op)
NlaTrack *nlt = (NlaTrack *)ale->data;
NlaStrip *strip;
+ if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
+ /* No pasting in non-local tracks of override data. */
+ continue;
+ }
+
for (strip = nlt->strips.first; strip; strip = strip->next) {
/* can F-Modifier be added to the current strip? */
if (active_only) {
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index d8f31161c20..f4a3bb96aeb 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -21,6 +21,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../compositor
../../depsgraph
../../draw
../../gpu
@@ -29,7 +30,6 @@ set(INC
../../makesrna
../../nodes
../../render
- ../../compositor
../../windowmanager
../../../../intern/glew-mx
../../../../intern/guardedalloc
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 84e7a74fab3..0ce31707204 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -203,42 +203,6 @@ static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *
uiItemR(layout, &sockptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
}
-#if 0 /* not used in 2.5x yet */
-static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v)
-{
- Main *bmain = CTX_data_main(C);
- bNodeTree *ntree = ntree_v;
- bNode *node = node_v;
- Tex *tex;
-
- if (node->menunr < 1) {
- return;
- }
-
- if (node->id) {
- id_us_min(node->id);
- node->id = NULL;
- }
- tex = BLI_findlink(&bmain->tex, node->menunr - 1);
-
- node->id = &tex->id;
- id_us_plus(node->id);
- BLI_strncpy(node->name, node->id->name + 2, sizeof(node->name));
-
- nodeSetActive(ntree, node);
-
- if (ntree->type == NTREE_TEXTURE) {
- ntreeTexCheckCyclics(ntree);
- }
-
- // allqueue(REDRAWBUTSSHADING, 0);
- // allqueue(REDRAWNODE, 0);
- NodeTagChanged(ntree, node);
-
- node->menunr = 0;
-}
-#endif
-
static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
bNode *node = ptr->data;
@@ -771,6 +735,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
ptr,
"image",
"IMAGE_OT_new",
+ NULL,
"IMAGE_OT_open",
NULL,
UI_TEMPLATE_ID_FILTER_ALL,
@@ -808,6 +773,7 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
ptr,
"image",
"IMAGE_OT_new",
+ NULL,
"IMAGE_OT_open",
NULL,
UI_TEMPLATE_ID_FILTER_ALL,
@@ -1395,6 +1361,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
ptr,
"image",
"IMAGE_OT_new",
+ NULL,
"IMAGE_OT_open",
NULL,
UI_TEMPLATE_ID_FILTER_ALL,
@@ -1426,7 +1393,8 @@ static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, Pointer
bNode *node = ptr->data;
uiLayout *col, *row;
- uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
+ uiTemplateID(
+ layout, C, ptr, "scene", NULL, NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
if (!node->id) {
return;
@@ -1548,7 +1516,8 @@ static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA
col = uiLayoutColumn(layout, false);
uiItemR(col, ptr, "use_preview", DEFAULT_FLAGS, NULL, ICON_NONE);
- uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
+ uiTemplateID(
+ layout, C, ptr, "scene", NULL, NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
col = uiLayoutColumn(layout, false);
uiItemR(col, ptr, "use_zbuffer", DEFAULT_FLAGS, NULL, ICON_NONE);
@@ -2163,8 +2132,17 @@ static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), Pointe
static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- uiTemplateID(
- layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
+ uiTemplateID(layout,
+ C,
+ ptr,
+ "clip",
+ NULL,
+ NULL,
+ "CLIP_OT_open",
+ NULL,
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false,
+ NULL);
}
static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -2172,8 +2150,17 @@ static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, Point
bNode *node = ptr->data;
PointerRNA clipptr;
- uiTemplateID(
- layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
+ uiTemplateID(layout,
+ C,
+ ptr,
+ "clip",
+ NULL,
+ NULL,
+ "CLIP_OT_open",
+ NULL,
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false,
+ NULL);
if (!node->id) {
return;
@@ -2188,8 +2175,17 @@ static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, Pointe
{
bNode *node = ptr->data;
- uiTemplateID(
- layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
+ uiTemplateID(layout,
+ C,
+ ptr,
+ "clip",
+ NULL,
+ NULL,
+ "CLIP_OT_open",
+ NULL,
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false,
+ NULL);
if (!node->id) {
return;
@@ -2214,8 +2210,17 @@ static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, Po
{
bNode *node = ptr->data;
- uiTemplateID(
- layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
+ uiTemplateID(layout,
+ C,
+ ptr,
+ "clip",
+ NULL,
+ NULL,
+ "CLIP_OT_open",
+ NULL,
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false,
+ NULL);
if (!node->id) {
return;
@@ -2538,7 +2543,8 @@ static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *p
{
bNode *node = ptr->data;
- uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
+ uiTemplateID(
+ layout, C, ptr, "mask", NULL, NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
uiItemR(layout, ptr, "use_feather", DEFAULT_FLAGS, NULL, ICON_NONE);
uiItemR(layout, ptr, "size_source", DEFAULT_FLAGS, "", ICON_NONE);
@@ -2559,7 +2565,8 @@ static void node_composit_buts_keyingscreen(uiLayout *layout, bContext *C, Point
{
bNode *node = ptr->data;
- uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
+ uiTemplateID(
+ layout, C, ptr, "clip", NULL, NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
if (node->id) {
MovieClip *clip = (MovieClip *)node->id;
@@ -2595,8 +2602,17 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
{
bNode *node = ptr->data;
- uiTemplateID(
- layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
+ uiTemplateID(layout,
+ C,
+ ptr,
+ "clip",
+ NULL,
+ NULL,
+ "CLIP_OT_open",
+ NULL,
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false,
+ NULL);
if (node->id) {
MovieClip *clip = (MovieClip *)node->id;
@@ -2636,8 +2652,17 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P
bNode *node = ptr->data;
NodePlaneTrackDeformData *data = node->storage;
- uiTemplateID(
- layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
+ uiTemplateID(layout,
+ C,
+ ptr,
+ "clip",
+ NULL,
+ NULL,
+ "CLIP_OT_open",
+ NULL,
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false,
+ NULL);
if (node->id) {
MovieClip *clip = (MovieClip *)node->id;
@@ -3072,6 +3097,7 @@ static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *p
ptr,
"image",
"IMAGE_OT_new",
+ NULL,
"IMAGE_OT_open",
NULL,
UI_TEMPLATE_ID_FILTER_ALL,
@@ -3149,6 +3175,15 @@ static void node_geometry_buts_boolean_math(uiLayout *layout, bContext *UNUSED(C
uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE);
}
+static void node_geometry_buts_attribute_compare(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(layout, ptr, "input_type_a", DEFAULT_FLAGS, IFACE_("Type A"), ICON_NONE);
+ uiItemR(layout, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("Type B"), ICON_NONE);
+}
+
static void node_geometry_buts_subdivision_surface(uiLayout *layout,
bContext *UNUSED(C),
PointerRNA *UNUSED(ptr))
@@ -3182,6 +3217,49 @@ static void node_geometry_buts_attribute_math(uiLayout *layout,
uiItemR(layout, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("Type B"), ICON_NONE);
}
+static void node_geometry_buts_point_instance(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "instance_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ if (RNA_enum_get(ptr, "instance_type") == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION) {
+ uiItemR(layout, ptr, "use_whole_collection", DEFAULT_FLAGS, NULL, ICON_NONE);
+ }
+}
+
+static void node_geometry_buts_attribute_fill(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE);
+ // uiItemR(layout, ptr, "domain", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
+static void node_geometry_buts_attribute_mix(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE);
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "input_type_factor", DEFAULT_FLAGS, IFACE_("Factor"), ICON_NONE);
+ uiItemR(col, ptr, "input_type_a", DEFAULT_FLAGS, IFACE_("A"), ICON_NONE);
+ uiItemR(col, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("B"), ICON_NONE);
+}
+
+static void node_geometry_buts_attribute_point_distribute(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "distribute_method", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
+static void node_geometry_buts_attribute_color_ramp(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiTemplateColorRamp(layout, ptr, "color_ramp", 0);
+}
+
static void node_geometry_set_butfunc(bNodeType *ntype)
{
switch (ntype->type) {
@@ -3194,12 +3272,30 @@ static void node_geometry_set_butfunc(bNodeType *ntype)
case GEO_NODE_TRIANGULATE:
ntype->draw_buttons = node_geometry_buts_triangulate;
break;
- case GEO_NODE_RANDOM_ATTRIBUTE:
+ case GEO_NODE_ATTRIBUTE_RANDOMIZE:
ntype->draw_buttons = node_geometry_buts_random_attribute;
break;
case GEO_NODE_ATTRIBUTE_MATH:
ntype->draw_buttons = node_geometry_buts_attribute_math;
break;
+ case GEO_NODE_ATTRIBUTE_COMPARE:
+ ntype->draw_buttons = node_geometry_buts_attribute_compare;
+ break;
+ case GEO_NODE_POINT_INSTANCE:
+ ntype->draw_buttons = node_geometry_buts_point_instance;
+ break;
+ case GEO_NODE_ATTRIBUTE_FILL:
+ ntype->draw_buttons = node_geometry_buts_attribute_fill;
+ break;
+ case GEO_NODE_ATTRIBUTE_MIX:
+ ntype->draw_buttons = node_geometry_buts_attribute_mix;
+ break;
+ case GEO_NODE_POINT_DISTRIBUTE:
+ ntype->draw_buttons = node_geometry_buts_attribute_point_distribute;
+ break;
+ case GEO_NODE_ATTRIBUTE_COLOR_RAMP:
+ ntype->draw_buttons = node_geometry_buts_attribute_color_ramp;
+ break;
}
}
@@ -3222,6 +3318,12 @@ static void node_function_buts_switch(uiLayout *layout, bContext *UNUSED(C), Poi
uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE);
}
+static void node_function_buts_input_vector(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiLayout *col = uiLayoutColumn(layout, true);
+ uiItemR(col, ptr, "vector", UI_ITEM_R_EXPAND, "", ICON_NONE);
+}
+
static void node_function_set_butfunc(bNodeType *ntype)
{
switch (ntype->type) {
@@ -3234,6 +3336,9 @@ static void node_function_set_butfunc(bNodeType *ntype)
case FN_NODE_SWITCH:
ntype->draw_buttons = node_function_buts_switch;
break;
+ case FN_NODE_INPUT_VECTOR:
+ ntype->draw_buttons = node_function_buts_input_vector;
+ break;
}
}
@@ -3389,6 +3494,7 @@ static const float std_node_socket_colors[][4] = {
{0.93, 0.62, 0.36, 1.0}, /* SOCK_OBJECT */
{0.89, 0.76, 0.43, 1.0}, /* SOCK_IMAGE */
{0.00, 0.84, 0.64, 1.0}, /* SOCK_GEOMETRY */
+ {0.96, 0.96, 0.96, 1.0}, /* SOCK_COLLECTION */
};
/* common color callbacks for standard types */
@@ -3512,6 +3618,10 @@ static void std_node_socket_draw(
uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
break;
}
+ case SOCK_COLLECTION: {
+ uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
+ break;
+ }
default:
node_socket_button_label(C, layout, ptr, node_ptr, text);
break;
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index fc7fa3a6caa..d3fec7257f5 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -344,8 +344,6 @@ void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry)
/* based on settings in node, sets drawing rect info. each redraw! */
static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
{
- uiLayout *layout, *row;
-
PointerRNA nodeptr;
RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
@@ -374,15 +372,15 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
PointerRNA sockptr;
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
- layout = UI_block_layout(node->block,
- UI_LAYOUT_VERTICAL,
- UI_LAYOUT_PANEL,
- locx + NODE_DYS,
- dy,
- NODE_WIDTH(node) - NODE_DY,
- NODE_DY,
- 0,
- UI_style_get_dpi());
+ uiLayout *layout = UI_block_layout(node->block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_PANEL,
+ locx + NODE_DYS,
+ dy,
+ NODE_WIDTH(node) - NODE_DY,
+ NODE_DY,
+ 0,
+ UI_style_get_dpi());
if (node->flag & NODE_MUTED) {
uiLayoutSetActive(layout, false);
@@ -393,7 +391,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
uiLayoutSetContextPointer(layout, "socket", &sockptr);
/* align output buttons to the right */
- row = uiLayoutRow(layout, 1);
+ uiLayout *row = uiLayoutRow(layout, true);
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
const char *socket_label = nodeSocketLabel(nsock);
nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
@@ -469,15 +467,15 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
node->butr.ymin = 0;
node->butr.ymax = 0;
- layout = UI_block_layout(node->block,
- UI_LAYOUT_VERTICAL,
- UI_LAYOUT_PANEL,
- locx + NODE_DYS,
- dy,
- node->butr.xmax,
- 0,
- 0,
- UI_style_get_dpi());
+ uiLayout *layout = UI_block_layout(node->block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_PANEL,
+ locx + NODE_DYS,
+ dy,
+ node->butr.xmax,
+ 0,
+ 0,
+ UI_style_get_dpi());
if (node->flag & NODE_MUTED) {
uiLayoutSetActive(layout, false);
@@ -502,15 +500,15 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
PointerRNA sockptr;
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
- layout = UI_block_layout(node->block,
- UI_LAYOUT_VERTICAL,
- UI_LAYOUT_PANEL,
- locx + NODE_DYS,
- dy,
- NODE_WIDTH(node) - NODE_DY,
- NODE_DY,
- 0,
- UI_style_get_dpi());
+ uiLayout *layout = UI_block_layout(node->block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_PANEL,
+ locx + NODE_DYS,
+ dy,
+ NODE_WIDTH(node) - NODE_DY,
+ NODE_DY,
+ 0,
+ UI_style_get_dpi());
if (node->flag & NODE_MUTED) {
uiLayoutSetActive(layout, false);
@@ -520,7 +518,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
uiLayoutSetContextPointer(layout, "node", &nodeptr);
uiLayoutSetContextPointer(layout, "socket", &sockptr);
- row = uiLayoutRow(layout, 1);
+ uiLayout *row = uiLayoutRow(layout, true);
const char *socket_label = nodeSocketLabel(nsock);
nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
@@ -771,7 +769,6 @@ void node_socket_color_get(
bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, bNodeSocket *sock, float r_color[4])
{
PointerRNA ptr;
-
BLI_assert(RNA_struct_is_a(node_ptr->type, &RNA_Node));
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
@@ -1623,7 +1620,6 @@ void node_draw_nodetree(const bContext *C,
}
bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
- node->nr = a; /* index of node in list, used for exec event code */
node_draw(C, region, snode, ntree, node, key);
}
@@ -1646,7 +1642,6 @@ void node_draw_nodetree(const bContext *C,
}
bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
- node->nr = a; /* index of node in list, used for exec event code */
node_draw(C, region, snode, ntree, node, key);
}
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 039ddad71ef..e6f11f3eb83 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -100,9 +100,7 @@ typedef struct CompoJob {
static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags)
{
- bNode *node;
-
- for (node = nodetree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &nodetree->nodes) {
if (node->type == CMP_NODE_COMPOSITE) {
if (recalc_flags & COM_RECALC_COMPOSITE) {
node->flag |= NODE_DO_OUTPUT_RECALC;
@@ -124,14 +122,12 @@ static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags)
static int compo_get_recalc_flags(const bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win;
int recalc_flags = 0;
- for (win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
const bScreen *screen = WM_window_get_active_screen(win);
- ScrArea *area;
- for (area = screen->areabase.first; area; area = area->next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
if (area->spacetype == SPACE_IMAGE) {
SpaceImage *sima = area->spacedata.first;
if (sima->image) {
@@ -247,7 +243,6 @@ static void compo_startjob(void *cjv,
CompoJob *cj = cjv;
bNodeTree *ntree = cj->localtree;
Scene *scene = cj->scene;
- SceneRenderView *srv;
if (scene->use_nodes == false) {
return;
@@ -280,7 +275,7 @@ static void compo_startjob(void *cjv,
"");
}
else {
- for (srv = scene->r.views.first; srv; srv = srv->next) {
+ LISTBASE_FOREACH (SceneRenderView *, srv, &scene->r.views) {
if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) {
continue;
}
@@ -309,8 +304,6 @@ static void compo_startjob(void *cjv,
*/
void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene *scene_owner)
{
- wmJob *wm_job;
- CompoJob *cj;
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -327,13 +320,13 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene
BKE_image_backup_render(
scene, BKE_image_ensure_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"), false);
- wm_job = WM_jobs_get(CTX_wm_manager(C),
- CTX_wm_window(C),
- scene_owner,
- "Compositing",
- WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS,
- WM_JOB_TYPE_COMPOSITE);
- cj = MEM_callocN(sizeof(CompoJob), "compo job");
+ wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene_owner,
+ "Compositing",
+ WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS,
+ WM_JOB_TYPE_COMPOSITE);
+ CompoJob *cj = MEM_callocN(sizeof(CompoJob), "compo job");
/* customdata for preview thread */
cj->bmain = bmain;
@@ -524,9 +517,6 @@ void ED_node_shader_default(const bContext *C, ID *id)
/* called from shading buttons or header */
void ED_node_composit_default(const bContext *C, struct Scene *sce)
{
- bNode *in, *out;
- bNodeSocket *fromsock, *tosock;
-
/* but lets check it anyway */
if (sce->nodetree) {
if (G.debug & G_DEBUG) {
@@ -541,18 +531,18 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce)
sce->nodetree->edit_quality = NTREE_QUALITY_HIGH;
sce->nodetree->render_quality = NTREE_QUALITY_HIGH;
- out = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_COMPOSITE);
+ bNode *out = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_COMPOSITE);
out->locx = 300.0f;
out->locy = 400.0f;
- in = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_R_LAYERS);
+ bNode *in = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_R_LAYERS);
in->locx = 10.0f;
in->locy = 400.0f;
nodeSetActive(sce->nodetree, in);
/* links from color to color */
- fromsock = in->outputs.first;
- tosock = out->inputs.first;
+ bNodeSocket *fromsock = in->outputs.first;
+ bNodeSocket *tosock = out->inputs.first;
nodeAddLink(sce->nodetree, in, fromsock, out, tosock);
ntreeUpdateTree(CTX_data_main(C), sce->nodetree);
@@ -562,9 +552,6 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce)
/* called from shading buttons or header */
void ED_node_texture_default(const bContext *C, Tex *tex)
{
- bNode *in, *out;
- bNodeSocket *fromsock, *tosock;
-
/* but lets check it anyway */
if (tex->nodetree) {
if (G.debug & G_DEBUG) {
@@ -575,17 +562,17 @@ void ED_node_texture_default(const bContext *C, Tex *tex)
tex->nodetree = ntreeAddTree(NULL, "Texture Nodetree", ntreeType_Texture->idname);
- out = nodeAddStaticNode(C, tex->nodetree, TEX_NODE_OUTPUT);
+ bNode *out = nodeAddStaticNode(C, tex->nodetree, TEX_NODE_OUTPUT);
out->locx = 300.0f;
out->locy = 300.0f;
- in = nodeAddStaticNode(C, tex->nodetree, TEX_NODE_CHECKER);
+ bNode *in = nodeAddStaticNode(C, tex->nodetree, TEX_NODE_CHECKER);
in->locx = 10.0f;
in->locy = 300.0f;
nodeSetActive(tex->nodetree, in);
- fromsock = in->outputs.first;
- tosock = out->inputs.first;
+ bNodeSocket *fromsock = in->outputs.first;
+ bNodeSocket *tosock = out->inputs.first;
nodeAddLink(tex->nodetree, in, fromsock, out, tosock);
ntreeUpdateTree(CTX_data_main(C), tex->nodetree);
@@ -634,15 +621,13 @@ void snode_set_context(const bContext *C)
void snode_update(SpaceNode *snode, bNode *node)
{
- bNodeTreePath *path;
-
/* XXX this only updates nodes in the current node space tree path.
* The function supposedly should update any potential group node linking to changed tree,
* this really requires a working depsgraph ...
*/
/* update all edited group nodes */
- path = snode->treepath.last;
+ bNodeTreePath *path = snode->treepath.last;
if (path) {
bNodeTree *ngroup = path->nodetree;
for (path = path->prev; path; path = path->prev) {
@@ -671,10 +656,9 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti
/* generic node group output: set node as active output */
if (node->type == NODE_GROUP_OUTPUT) {
- bNode *tnode;
- for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
- if (tnode->type == NODE_GROUP_OUTPUT) {
- tnode->flag &= ~NODE_DO_OUTPUT;
+ LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) {
+ if (node_iter->type == NODE_GROUP_OUTPUT) {
+ node_iter->flag &= ~NODE_DO_OUTPUT;
}
}
@@ -696,11 +680,9 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti
SH_NODE_OUTPUT_WORLD,
SH_NODE_OUTPUT_LIGHT,
SH_NODE_OUTPUT_LINESTYLE)) {
- bNode *tnode;
-
- for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
- if (tnode->type == node->type) {
- tnode->flag &= ~NODE_DO_OUTPUT;
+ LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) {
+ if (node_iter->type == node->type) {
+ node_iter->flag &= ~NODE_DO_OUTPUT;
}
}
@@ -715,16 +697,13 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti
/* if active texture changed, free glsl materials */
if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
- Material *ma;
- World *wo;
-
- for (ma = bmain->materials.first; ma; ma = ma->id.next) {
+ LISTBASE_FOREACH (Material *, ma, &bmain->materials) {
if (ma->nodetree && ma->use_nodes && ntreeHasTree(ma->nodetree, ntree)) {
GPU_material_free(&ma->gpumaterial);
}
}
- for (wo = bmain->worlds.first; wo; wo = wo->id.next) {
+ LISTBASE_FOREACH (World *, wo, &bmain->materials) {
if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree)) {
GPU_material_free(&wo->gpumaterial);
}
@@ -742,11 +721,9 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti
else if (ntree->type == NTREE_COMPOSIT) {
/* make active viewer, currently only 1 supported... */
if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
- bNode *tnode;
-
- for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
- if (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
- tnode->flag &= ~NODE_DO_OUTPUT;
+ LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) {
+ if (ELEM(node_iter->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ node_iter->flag &= ~NODE_DO_OUTPUT;
}
}
@@ -760,11 +737,9 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti
}
else if (node->type == CMP_NODE_COMPOSITE) {
if (was_output == 0) {
- bNode *tnode;
-
- for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
- if (tnode->type == CMP_NODE_COMPOSITE) {
- tnode->flag &= ~NODE_DO_OUTPUT;
+ LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) {
+ if (node_iter->type == CMP_NODE_COMPOSITE) {
+ node_iter->flag &= ~NODE_DO_OUTPUT;
}
}
@@ -879,14 +854,12 @@ static void edit_node_properties_get(
/* is rct in visible part of node? */
static bNode *visible_node(SpaceNode *snode, const rctf *rct)
{
- bNode *node;
-
- for (node = snode->edittree->nodes.last; node; node = node->prev) {
+ LISTBASE_FOREACH_BACKWARD (bNode *, node, &snode->edittree->nodes) {
if (BLI_rctf_isect(&node->totr, rct, NULL)) {
- break;
+ return node;
}
}
- return node;
+ return NULL;
}
/* ********************** size widget operator ******************** */
@@ -952,23 +925,19 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
ARegion *region = CTX_wm_region(C);
bNode *node = nodeGetActive(snode->edittree);
NodeSizeWidget *nsw = op->customdata;
- float mx, my, dx, dy;
switch (event->type) {
- case MOUSEMOVE:
-
+ case MOUSEMOVE: {
+ float mx, my;
UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &mx, &my);
- dx = (mx - nsw->mxstart) / UI_DPI_FAC;
- dy = (my - nsw->mystart) / UI_DPI_FAC;
+ float dx = (mx - nsw->mxstart) / UI_DPI_FAC;
+ float dy = (my - nsw->mystart) / UI_DPI_FAC;
if (node) {
- float *pwidth;
- float oldwidth, widthmin, widthmax;
-
- pwidth = &node->width;
- oldwidth = nsw->oldwidth;
- widthmin = node->typeinfo->minwidth;
- widthmax = node->typeinfo->maxwidth;
+ float *pwidth = &node->width;
+ float oldwidth = nsw->oldwidth;
+ float widthmin = node->typeinfo->minwidth;
+ float widthmax = node->typeinfo->maxwidth;
{
if (nsw->directions & NODE_RESIZE_RIGHT) {
@@ -1026,23 +995,24 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(region);
break;
-
+ }
case LEFTMOUSE:
case MIDDLEMOUSE:
- case RIGHTMOUSE:
+ case RIGHTMOUSE: {
if (event->val == KM_RELEASE) {
node_resize_exit(C, op, false);
ED_node_post_apply_transform(C, snode->edittree);
return OPERATOR_FINISHED;
}
- else if (event->val == KM_PRESS) {
+ if (event->val == KM_PRESS) {
node_resize_exit(C, op, true);
ED_region_tag_redraw(region);
return OPERATOR_CANCELLED;
}
break;
+ }
}
return OPERATOR_RUNNING_MODAL;
@@ -1095,14 +1065,12 @@ void NODE_OT_resize(wmOperatorType *ot)
bool node_has_hidden_sockets(bNode *node)
{
- bNodeSocket *sock;
-
- for (sock = node->inputs.first; sock; sock = sock->next) {
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
if (sock->flag & SOCK_HIDDEN) {
return true;
}
}
- for (sock = node->outputs.first; sock; sock = sock->next) {
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
if (sock->flag & SOCK_HIDDEN) {
return true;
}
@@ -1112,24 +1080,22 @@ bool node_has_hidden_sockets(bNode *node)
void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
{
- bNodeSocket *sock;
-
if (set == 0) {
- for (sock = node->inputs.first; sock; sock = sock->next) {
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
sock->flag &= ~SOCK_HIDDEN;
}
- for (sock = node->outputs.first; sock; sock = sock->next) {
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
sock->flag &= ~SOCK_HIDDEN;
}
}
else {
/* hide unused sockets */
- for (sock = node->inputs.first; sock; sock = sock->next) {
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
if (sock->link == NULL) {
sock->flag |= SOCK_HIDDEN;
}
}
- for (sock = node->outputs.first; sock; sock = sock->next) {
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
if (nodeCountSocketLinks(snode->edittree, sock) == 0) {
sock->flag |= SOCK_HIDDEN;
}
@@ -1142,16 +1108,13 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
int node_find_indicated_socket(
SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, float cursor[2], int in_out)
{
- bNode *node;
- bNodeSocket *sock;
rctf rect;
*nodep = NULL;
*sockp = NULL;
/* check if we click in a socket */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
-
+ LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
BLI_rctf_init_pt_radius(&rect, cursor, NODE_SOCKSIZE + 4);
if (!(node->flag & NODE_HIDDEN)) {
@@ -1167,7 +1130,7 @@ int node_find_indicated_socket(
}
if (in_out & SOCK_IN) {
- for (sock = node->inputs.first; sock; sock = sock->next) {
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
if (!nodeSocketIsHidden(sock)) {
if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
if (node == visible_node(snode, &rect)) {
@@ -1180,7 +1143,7 @@ int node_find_indicated_socket(
}
}
if (in_out & SOCK_OUT) {
- for (sock = node->outputs.first; sock; sock = sock->next) {
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
if (!nodeSocketIsHidden(sock)) {
if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
if (node == visible_node(snode, &rect)) {
@@ -1226,17 +1189,15 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- bNode *node, *newnode, *lastnode;
- bNodeLink *link, *newlink, *lastlink;
const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
bool do_tag_update = false;
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- lastnode = ntree->nodes.last;
- for (node = ntree->nodes.first; node; node = node->next) {
+ bNode *lastnode = ntree->nodes.last;
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->flag & SELECT) {
- newnode = BKE_node_copy_store_new_pointers(ntree, node, LIB_ID_COPY_DEFAULT);
+ BKE_node_copy_store_new_pointers(ntree, node, LIB_ID_COPY_DEFAULT);
/* to ensure redraws or rerenders happen */
ED_node_tag_update_id(snode->id);
@@ -1251,14 +1212,14 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
/* copy links between selected nodes
* NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
*/
- lastlink = ntree->links.last;
- for (link = ntree->links.first; link; link = link->next) {
+ bNodeLink *lastlink = ntree->links.last;
+ LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
/* This creates new links between copied nodes.
* If keep_inputs is set, also copies input links from unselected (when fromnode==NULL)!
*/
if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
(keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT)))) {
- newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
+ bNodeLink *newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
newlink->flag = link->flag;
newlink->tonode = link->tonode->new_node;
newlink->tosock = link->tosock->new_sock;
@@ -1282,11 +1243,11 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
}
/* clear flags for recursive depth-first iteration */
- for (node = ntree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
node->flag &= ~NODE_TEST;
}
/* reparent copied nodes */
- for (node = ntree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if ((node->flag & SELECT) && !(node->flag & NODE_TEST)) {
node_duplicate_reparent_recursive(node);
}
@@ -1298,10 +1259,10 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
}
/* deselect old nodes, select the copies instead */
- for (node = ntree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->flag & SELECT) {
/* has been set during copy above */
- newnode = node->new_node;
+ bNode *newnode = node->new_node;
nodeSetSelected(node, false);
node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_TEXTURE);
@@ -1389,17 +1350,16 @@ static int node_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
- Scene *curscene = CTX_data_scene(C), *scene;
- bNode *node;
+ Scene *curscene = CTX_data_scene(C);
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
/* first tag scenes unread */
- for (scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
scene->id.tag |= LIB_TAG_DOIT;
}
- for (node = snode->edittree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
if (node->type == CMP_NODE_R_LAYERS) {
ID *id = node->id;
if (id->tag & LIB_TAG_DOIT) {
@@ -1434,13 +1394,14 @@ void NODE_OT_read_viewlayers(wmOperatorType *ot)
int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *sce = CTX_data_scene(C);
- bNode *node;
/* This is actually a test whether scene is used by the compositor or not.
* All the nodes are using same render result, so there is no need to do
* anything smart about check how exactly scene is used. */
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->id == (ID *)sce) {
+ bNode *node = NULL;
+ LISTBASE_FOREACH (bNode *, node_iter, &sce->nodetree->nodes) {
+ if (node_iter->id == (ID *)sce) {
+ node = node_iter;
break;
}
}
@@ -1486,14 +1447,14 @@ void NODE_OT_render_changed(wmOperatorType *ot)
static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
{
- bNode *node;
int tot_eq = 0, tot_neq = 0;
/* Toggles the flag on all selected nodes.
* If the flag is set on all nodes it is unset.
* If the flag is not set on all nodes, it is set.
*/
- for (node = snode->edittree->nodes.first; node; node = node->next) {
+
+ LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
if (node->flag & SELECT) {
if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) {
@@ -1512,7 +1473,7 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
}
}
}
- for (node = snode->edittree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
if (node->flag & SELECT) {
if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) {
@@ -1631,8 +1592,6 @@ void NODE_OT_options_toggle(wmOperatorType *ot)
static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node;
- int hidden;
/* sanity checking (poll callback checks this already) */
if ((snode == NULL) || (snode->edittree == NULL)) {
@@ -1642,17 +1601,17 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
/* Toggle for all selected nodes */
- hidden = 0;
- for (node = snode->edittree->nodes.first; node; node = node->next) {
+ bool hidden = false;
+ LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
if (node->flag & SELECT) {
if (node_has_hidden_sockets(node)) {
- hidden = 1;
+ hidden = true;
break;
}
}
}
- for (node = snode->edittree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
if (node->flag & SELECT) {
node_set_hidden_sockets(snode, node, !hidden);
}
@@ -1686,12 +1645,11 @@ static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node;
bool do_tag_update = false;
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- for (node = snode->edittree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
/* Only allow muting of nodes having a mute func! */
if ((node->flag & SELECT) && node->typeinfo->update_internal_links) {
node->flag ^= NODE_MUTED;
@@ -1731,13 +1689,11 @@ static int node_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node, *next;
bool do_tag_update = false;
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- for (node = snode->edittree->nodes.first; node; node = next) {
- next = node->next;
+ LISTBASE_FOREACH_MUTABLE (bNode *, node, &snode->edittree->nodes) {
if (node->flag & SELECT) {
do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, node));
nodeRemoveNode(bmain, snode->edittree, node, true);
@@ -1787,10 +1743,8 @@ static bool node_switch_view_poll(bContext *C)
static int node_switch_view_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node, *next;
- for (node = snode->edittree->nodes.first; node; node = next) {
- next = node->next;
+ LISTBASE_FOREACH_MUTABLE (bNode *, node, &snode->edittree->nodes) {
if (node->flag & SELECT) {
/* call the update function from the Switch View node */
node->update = NODE_UPDATE_OPERATOR;
@@ -1825,12 +1779,10 @@ static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node, *next;
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- for (node = snode->edittree->nodes.first; node; node = next) {
- next = node->next;
+ LISTBASE_FOREACH_MUTABLE (bNode *, node, &snode->edittree->nodes) {
if (node->flag & SELECT) {
nodeInternalRelink(snode->edittree, node);
nodeRemoveNode(bmain, snode->edittree, node, true);
@@ -1963,9 +1915,6 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
SpaceNode *snode = CTX_wm_space_node(C);
PointerRNA ptr = CTX_data_pointer_get(C, "node");
bNode *node = NULL;
- NodeImageMultiFile *nimf;
- bNodeSocket *sock;
- int direction;
if (ptr.data) {
node = ptr.data;
@@ -1978,14 +1927,14 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- nimf = node->storage;
+ NodeImageMultiFile *nimf = node->storage;
- sock = BLI_findlink(&node->inputs, nimf->active_input);
+ bNodeSocket *sock = BLI_findlink(&node->inputs, nimf->active_input);
if (!sock) {
return OPERATOR_CANCELLED;
}
- direction = RNA_enum_get(op->ptr, "direction");
+ int direction = RNA_enum_get(op->ptr, "direction");
if (direction == 1) {
bNodeSocket *before = sock->prev;
@@ -2037,24 +1986,23 @@ static int node_copy_color_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- bNode *node, *tnode;
if (!ntree) {
return OPERATOR_CANCELLED;
}
- node = nodeGetActive(ntree);
+ bNode *node = nodeGetActive(ntree);
if (!node) {
return OPERATOR_CANCELLED;
}
- for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
- if (tnode->flag & NODE_SELECT && tnode != node) {
+ LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) {
+ if (node_iter->flag & NODE_SELECT && node_iter != node) {
if (node->flag & NODE_CUSTOM_COLOR) {
- tnode->flag |= NODE_CUSTOM_COLOR;
- copy_v3_v3(tnode->color, node->color);
+ node_iter->flag |= NODE_CUSTOM_COLOR;
+ copy_v3_v3(node_iter->color, node->color);
}
else {
- tnode->flag &= ~NODE_CUSTOM_COLOR;
+ node_iter->flag &= ~NODE_CUSTOM_COLOR;
}
}
}
@@ -2086,8 +2034,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- bNode *node;
- bNodeLink *link, *newlink;
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
@@ -2095,7 +2041,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
BKE_node_clipboard_clear();
BKE_node_clipboard_init(ntree);
- for (node = ntree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->flag & SELECT) {
/* No ID refcounting, this node is virtual,
* detached from any actual Blender data currently. */
@@ -2105,7 +2051,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- for (node = ntree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->flag & SELECT) {
bNode *new_node = node->new_node;
@@ -2126,11 +2072,11 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
/* copy links between selected nodes
* NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
*/
- for (link = ntree->links.first; link; link = link->next) {
+ LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
/* This creates new links between copied nodes. */
if (link->tonode && (link->tonode->flag & NODE_SELECT) && link->fromnode &&
(link->fromnode->flag & NODE_SELECT)) {
- newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
+ bNodeLink *newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
newlink->flag = link->flag;
newlink->tonode = link->tonode->new_node;
newlink->tosock = link->tosock->new_sock;
@@ -2165,18 +2111,11 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- const ListBase *clipboard_nodes_lb;
- const ListBase *clipboard_links_lb;
- bNode *node;
- bNodeLink *link;
- int num_nodes;
- float center[2];
- bool is_clipboard_valid, all_nodes_valid;
/* validate pointers in the clipboard */
- is_clipboard_valid = BKE_node_clipboard_validate();
- clipboard_nodes_lb = BKE_node_clipboard_get_nodes();
- clipboard_links_lb = BKE_node_clipboard_get_links();
+ bool is_clipboard_valid = BKE_node_clipboard_validate();
+ const ListBase *clipboard_nodes_lb = BKE_node_clipboard_get_nodes();
+ const ListBase *clipboard_links_lb = BKE_node_clipboard_get_links();
if (BLI_listbase_is_empty(clipboard_nodes_lb)) {
BKE_report(op->reports, RPT_ERROR, "Clipboard is empty");
@@ -2196,8 +2135,8 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
}
/* make sure all clipboard nodes would be valid in the target tree */
- all_nodes_valid = true;
- for (node = clipboard_nodes_lb->first; node; node = node->next) {
+ bool all_nodes_valid = true;
+ LISTBASE_FOREACH (bNode *, node, clipboard_nodes_lb) {
if (!node->typeinfo->poll_instance || !node->typeinfo->poll_instance(node, ntree)) {
all_nodes_valid = false;
BKE_reportf(op->reports,
@@ -2217,15 +2156,16 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
node_deselect_all(snode);
/* calculate "barycenter" for placing on mouse cursor */
- zero_v2(center);
- for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) {
+ float center[2] = {0.0f, 0.0f};
+ int num_nodes = 0;
+ LISTBASE_FOREACH_INDEX (bNode *, node, clipboard_nodes_lb, num_nodes) {
center[0] += BLI_rctf_cent_x(&node->totr);
center[1] += BLI_rctf_cent_y(&node->totr);
}
mul_v2_fl(center, 1.0 / num_nodes);
/* copy nodes from clipboard */
- for (node = clipboard_nodes_lb->first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, clipboard_nodes_lb) {
bNode *new_node = BKE_node_copy_store_new_pointers(ntree, node, LIB_ID_COPY_DEFAULT);
/* pasted nodes are selected */
@@ -2233,14 +2173,14 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
}
/* reparent copied nodes */
- for (node = clipboard_nodes_lb->first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, clipboard_nodes_lb) {
bNode *new_node = node->new_node;
if (new_node->parent) {
new_node->parent = new_node->parent->new_node;
}
}
- for (link = clipboard_links_lb->first; link; link = link->next) {
+ LISTBASE_FOREACH (bNodeLink *, link, clipboard_links_lb) {
nodeAddLink(ntree,
link->fromnode->new_node,
link->fromsock->new_sock,
@@ -2275,10 +2215,9 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot)
static bNodeSocket *ntree_get_active_interface_socket(ListBase *lb)
{
- bNodeSocket *sock;
- for (sock = lb->first; sock; sock = sock->next) {
- if (sock->flag & SELECT) {
- return sock;
+ LISTBASE_FOREACH (bNodeSocket *, socket, lb) {
+ if (socket->flag & SELECT) {
+ return socket;
}
}
return NULL;
@@ -2289,12 +2228,12 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op)
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
int in_out = RNA_enum_get(op->ptr, "in_out");
- PointerRNA ntree_ptr;
- bNodeSocket *sock, *tsock, *active_sock;
- const char *default_name;
+ PointerRNA ntree_ptr;
RNA_id_pointer_create((ID *)ntree, &ntree_ptr);
+ const char *default_name;
+ bNodeSocket *active_sock;
if (in_out == SOCK_IN) {
active_sock = ntree_get_active_interface_socket(&ntree->inputs);
default_name = "Input";
@@ -2304,6 +2243,7 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op)
default_name = "Output";
}
+ bNodeSocket *sock;
if (active_sock) {
/* insert a copy of the active socket right after it */
sock = ntreeInsertSocketInterface(
@@ -2317,11 +2257,11 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op)
}
/* deactivate sockets (has to check both lists) */
- for (tsock = ntree->inputs.first; tsock; tsock = tsock->next) {
- tsock->flag &= ~SELECT;
+ LISTBASE_FOREACH (bNodeSocket *, socket_iter, &ntree->inputs) {
+ socket_iter->flag &= ~SELECT;
}
- for (tsock = ntree->outputs.first; tsock; tsock = tsock->next) {
- tsock->flag &= ~SELECT;
+ LISTBASE_FOREACH (bNodeSocket *, socket_iter, &ntree->outputs) {
+ socket_iter->flag &= ~SELECT;
}
/* make the new socket active */
sock->flag |= SELECT;
@@ -2359,9 +2299,8 @@ static int ntree_socket_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- bNodeSocket *iosock, *active_sock;
- iosock = ntree_get_active_interface_socket(&ntree->inputs);
+ bNodeSocket *iosock = ntree_get_active_interface_socket(&ntree->inputs);
if (!iosock) {
iosock = ntree_get_active_interface_socket(&ntree->outputs);
}
@@ -2370,7 +2309,7 @@ static int ntree_socket_remove_exec(bContext *C, wmOperator *UNUSED(op))
}
/* preferably next socket becomes active, otherwise try previous socket */
- active_sock = (iosock->next ? iosock->next : iosock->prev);
+ bNodeSocket *active_sock = (iosock->next ? iosock->next : iosock->prev);
ntreeRemoveSocketInterface(ntree, iosock);
/* set active socket */
@@ -2416,11 +2355,9 @@ static int ntree_socket_move_exec(bContext *C, wmOperator *op)
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
int direction = RNA_enum_get(op->ptr, "direction");
- bNodeSocket *iosock;
- ListBase *lb;
- lb = &ntree->inputs;
- iosock = ntree_get_active_interface_socket(lb);
+ ListBase *lb = &ntree->inputs;
+ bNodeSocket *iosock = ntree_get_active_interface_socket(lb);
if (!iosock) {
lb = &ntree->outputs;
iosock = ntree_get_active_interface_socket(lb);
@@ -2489,8 +2426,6 @@ static bool node_shader_script_update_poll(bContext *C)
Scene *scene = CTX_data_scene(C);
const RenderEngineType *type = RE_engines_find(scene->r.engine);
SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node;
- Text *text;
/* test if we have a render engine that supports shaders scripts */
if (!(type && type->update_script_node)) {
@@ -2498,7 +2433,7 @@ static bool node_shader_script_update_poll(bContext *C)
}
/* see if we have a shader script node in context */
- node = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data;
+ bNode *node = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data;
if (!node && snode && snode->edittree) {
node = nodeGetActive(snode->edittree);
@@ -2513,7 +2448,7 @@ static bool node_shader_script_update_poll(bContext *C)
}
/* see if we have a text datablock in context */
- text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
+ Text *text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
if (text) {
return 1;
}
@@ -2530,12 +2465,11 @@ static bool node_shader_script_update_text_recursive(RenderEngine *engine,
Text *text)
{
bool found = false;
- bNode *node;
ntree->done = true;
/* update each script that is using this text datablock */
- for (node = ntree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type == NODE_GROUP) {
bNodeTree *ngroup = (bNodeTree *)node->id;
if (ngroup && !ngroup->done) {
@@ -2557,18 +2491,16 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
SpaceNode *snode = CTX_wm_space_node(C);
PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript);
- bNodeTree *ntree_base = NULL;
- bNode *node = NULL;
- RenderEngine *engine;
- RenderEngineType *type;
bool found = false;
/* setup render engine */
- type = RE_engines_find(scene->r.engine);
- engine = RE_engine_create(type);
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ RenderEngine *engine = RE_engine_create(type);
engine->reports = op->reports;
/* get node */
+ bNodeTree *ntree_base = NULL;
+ bNode *node = NULL;
if (nodeptr.data) {
ntree_base = (bNodeTree *)nodeptr.owner_id;
node = nodeptr.data;
@@ -2643,10 +2575,8 @@ static void viewer_border_corner_to_backdrop(SpaceNode *snode,
float *fx,
float *fy)
{
- float bufx, bufy;
-
- bufx = backdrop_width * snode->zoom;
- bufy = backdrop_height * snode->zoom;
+ float bufx = backdrop_width * snode->zoom;
+ float bufy = backdrop_height * snode->zoom;
*fx = (bufx > 0.0f ? ((float)x - 0.5f * region->winx - snode->xof) / bufx + 0.5f : 0.0f);
*fy = (bufy > 0.0f ? ((float)y - 0.5f * region->winy - snode->yof) / bufy + 0.5f : 0.0f);
@@ -2655,14 +2585,12 @@ static void viewer_border_corner_to_backdrop(SpaceNode *snode,
static int viewer_border_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Image *ima;
void *lock;
- ImBuf *ibuf;
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
ARegion *region = CTX_wm_region(C);
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index 3c861896d37..d2c88ed787c 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -283,7 +283,7 @@ void NODE_OT_backimage_move(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Background Image Move";
- ot->description = "Move Node backdrop";
+ ot->description = "Move node backdrop";
ot->idname = "NODE_OT_backimage_move";
/* api callbacks */
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index afc1a963f4f..ad7632377a3 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -645,7 +645,7 @@ static bool node_ima_drop_poll(bContext *UNUSED(C),
/* rule might not work? */
return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE));
}
- return WM_drag_ID(drag, ID_IM) != NULL;
+ return WM_drag_get_local_ID(drag, ID_IM) != NULL;
}
static bool node_mask_drop_poll(bContext *UNUSED(C),
@@ -653,19 +653,19 @@ static bool node_mask_drop_poll(bContext *UNUSED(C),
const wmEvent *UNUSED(event),
const char **UNUSED(r_tooltip))
{
- return WM_drag_ID(drag, ID_MSK) != NULL;
+ return WM_drag_get_local_ID(drag, ID_MSK) != NULL;
}
static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, 0);
+ ID *id = WM_drag_get_local_ID(drag, 0);
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, 0);
+ ID *id = WM_drag_get_local_ID(drag, 0);
if (id) {
RNA_string_set(drop->ptr, "name", id->name + 2);
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index 74f99540bee..e0262371559 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -34,6 +34,7 @@ set(INC
set(SRC
outliner_collections.c
+ outliner_context.c
outliner_dragdrop.c
outliner_draw.c
outliner_edit.c
@@ -46,12 +47,12 @@ set(SRC
space_outliner.c
tree/common.cc
tree/tree_display.cc
+ tree/tree_display_data.cc
tree/tree_display_libraries.cc
- tree/tree_display_view_layer.cc
- tree/tree_display_sequencer.cc
tree/tree_display_orphaned.cc
tree/tree_display_scenes.cc
- tree/tree_display_data.cc
+ tree/tree_display_sequencer.cc
+ tree/tree_display_view_layer.cc
tree/tree_element.cc
tree/tree_element_anim_data.cc
tree/tree_element_driver_base.cc
diff --git a/source/blender/editors/space_outliner/outliner_context.c b/source/blender/editors/space_outliner/outliner_context.c
new file mode 100644
index 00000000000..a314a640e42
--- /dev/null
+++ b/source/blender/editors/space_outliner/outliner_context.c
@@ -0,0 +1,73 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup spoutliner
+ */
+
+#include "BLI_listbase.h"
+
+#include "BKE_context.h"
+
+#include "DNA_space_types.h"
+
+#include "RNA_access.h"
+
+#include "outliner_intern.h"
+
+static void outliner_context_selected_ids_recursive(const ListBase *subtree,
+ bContextDataResult *result)
+{
+ LISTBASE_FOREACH (const TreeElement *, te, subtree) {
+ const TreeStoreElem *tse = TREESTORE(te);
+ if ((tse->flag & TSE_SELECTED) && (ELEM(tse->type, 0, TSE_LAYER_COLLECTION))) {
+ CTX_data_id_list_add(result, tse->id);
+ }
+ outliner_context_selected_ids_recursive(&te->subtree, result);
+ }
+}
+
+static void outliner_context_selected_ids(const SpaceOutliner *space_outliner,
+ bContextDataResult *result)
+{
+ outliner_context_selected_ids_recursive(&space_outliner->tree, result);
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+}
+
+static const char *outliner_context_dir[] = {"selected_ids", NULL};
+
+int /*eContextResult*/ outliner_context(const bContext *C,
+ const char *member,
+ bContextDataResult *result)
+{
+ SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
+
+ if (CTX_data_dir(member)) {
+ CTX_data_dir_set(result, outliner_context_dir);
+ return CTX_RESULT_OK;
+ }
+ if (CTX_data_equals(member, "selected_ids")) {
+ outliner_context_selected_ids(space_outliner, result);
+ return CTX_RESULT_OK;
+ }
+ /* Note: Querying non-ID selection could also work if tree elements stored their matching RNA
+ * struct type. */
+
+ return CTX_RESULT_MEMBER_NOT_FOUND;
+}
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c
index d3da7b80765..152bbc96281 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.c
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.c
@@ -333,7 +333,7 @@ static bool parent_drop_poll(bContext *C,
ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
}
- Object *potential_child = (Object *)WM_drag_ID(drag, ID_OB);
+ Object *potential_child = (Object *)WM_drag_get_local_ID(drag, ID_OB);
if (!potential_child) {
return false;
}
@@ -421,7 +421,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
Object *par = (Object *)tselem->id;
- Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB);
+ Object *ob = (Object *)WM_drag_get_local_ID_from_event(event, ID_OB);
if (ELEM(NULL, ob, par)) {
return OPERATOR_CANCELLED;
@@ -445,7 +445,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void OUTLINER_OT_parent_drop(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Drop to Set Parent [+Alt keeps transforms]";
+ ot->name = "Drop to Set Parent (hold Alt to keep transforms)";
ot->description = "Drag to parent in Outliner";
ot->idname = "OUTLINER_OT_parent_drop";
@@ -473,7 +473,7 @@ static bool parent_clear_poll(bContext *C,
}
}
- Object *ob = (Object *)WM_drag_ID(drag, ID_OB);
+ Object *ob = (Object *)WM_drag_get_local_ID(drag, ID_OB);
if (!ob) {
return false;
}
@@ -531,7 +531,7 @@ static int parent_clear_invoke(bContext *C, wmOperator *UNUSED(op), const wmEven
void OUTLINER_OT_parent_clear(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Drop to Clear Parent [+Alt keeps transforms]";
+ ot->name = "Drop to Clear Parent (hold Alt to keep transforms)";
ot->description = "Drag to clear parent in Outliner";
ot->idname = "OUTLINER_OT_parent_clear";
@@ -552,7 +552,7 @@ static bool scene_drop_poll(bContext *C,
const char **UNUSED(r_tooltip))
{
/* Ensure item under cursor is valid drop target */
- Object *ob = (Object *)WM_drag_ID(drag, ID_OB);
+ Object *ob = (Object *)WM_drag_get_local_ID(drag, ID_OB);
return (ob && (outliner_ID_drop_find(C, event, ID_SCE) != NULL));
}
@@ -560,7 +560,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent
{
Main *bmain = CTX_data_main(C);
Scene *scene = (Scene *)outliner_ID_drop_find(C, event, ID_SCE);
- Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB);
+ Object *ob = (Object *)WM_drag_get_local_ID_from_event(event, ID_OB);
if (ELEM(NULL, ob, scene) || ID_IS_LINKED(scene)) {
return OPERATOR_CANCELLED;
@@ -620,7 +620,7 @@ static bool material_drop_poll(bContext *C,
const char **UNUSED(r_tooltip))
{
/* Ensure item under cursor is valid drop target */
- Material *ma = (Material *)WM_drag_ID(drag, ID_MA);
+ Material *ma = (Material *)WM_drag_get_local_ID(drag, ID_MA);
return (ma && (outliner_ID_drop_find(C, event, ID_OB) != NULL));
}
@@ -628,7 +628,7 @@ static int material_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve
{
Main *bmain = CTX_data_main(C);
Object *ob = (Object *)outliner_ID_drop_find(C, event, ID_OB);
- Material *ma = (Material *)WM_drag_ID_from_event(event, ID_MA);
+ Material *ma = (Material *)WM_drag_get_local_ID_from_event(event, ID_MA);
if (ELEM(NULL, ob, ma)) {
return OPERATOR_CANCELLED;
@@ -1461,14 +1461,14 @@ static int outliner_item_drag_drop_invoke(bContext *C,
parent = scene->master_collection;
}
- WM_drag_add_ID(drag, id, &parent->id);
+ WM_drag_add_local_ID(drag, id, &parent->id);
}
BLI_freelistN(&selected.selected_array);
}
else {
/* Add single ID. */
- WM_drag_add_ID(drag, data.drag_id, data.drag_parent);
+ WM_drag_add_local_ID(drag, data.drag_id, data.drag_parent);
}
ED_outliner_select_sync_from_outliner(C, space_outliner);
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 6364fbc0a87..9223da136e1 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1996,7 +1996,7 @@ static void outliner_draw_mode_column_toggle(uiBlock *block,
"Change the object in the current mode\n"
"* Ctrl to add to the current mode");
}
-
+ UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
uiBut *but = uiDefIconBut(block,
UI_BTYPE_ICON_TOGGLE,
0,
@@ -2845,6 +2845,7 @@ static void outliner_draw_iconrow(bContext *C,
LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
+ te->flag &= ~(TE_ICONROW | TE_ICONROW_MERGED);
/* object hierarchy always, further constrained on level */
if (level < 1 || (tselem->type == 0 && te->idcode == ID_OB)) {
@@ -2928,8 +2929,6 @@ static void outliner_draw_iconrow(bContext *C,
/* closed tree element */
static void outliner_set_coord_tree_element(TreeElement *te, int startx, int starty)
{
- TreeElement *ten;
-
/* closed items may be displayed in row of parent, don't change their coordinate! */
if ((te->flag & TE_ICONROW) == 0 && (te->flag & TE_ICONROW_MERGED) == 0) {
te->xs = 0;
@@ -2937,7 +2936,7 @@ static void outliner_set_coord_tree_element(TreeElement *te, int startx, int sta
te->xend = 0;
}
- for (ten = te->subtree.first; ten; ten = ten->next) {
+ LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) {
outliner_set_coord_tree_element(ten, startx + UI_UNIT_X, starty);
}
}
@@ -3647,7 +3646,7 @@ void draw_outliner(const bContext *C)
outliner_tree_dimensions(space_outliner, &tree_width, &tree_height);
/* Default to no emboss for outliner UI. */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
if (space_outliner->outlinevis == SO_DATA_API) {
int buttons_start_x = outliner_data_api_buttons_start_x(tree_width);
@@ -3656,7 +3655,7 @@ void draw_outliner(const bContext *C)
UI_block_emboss_set(block, UI_EMBOSS);
outliner_draw_rnabuts(block, region, space_outliner, buttons_start_x, &space_outliner->tree);
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
}
else if (space_outliner->outlinevis == SO_ID_ORPHANS) {
/* draw user toggle columns */
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index a1ff6193cd0..1cb98e704f2 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -1253,8 +1253,7 @@ static void outliner_set_coordinates_element_recursive(SpaceOutliner *space_outl
*starty -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, space_outliner)) {
- TreeElement *ten;
- for (ten = te->subtree.first; ten; ten = ten->next) {
+ LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) {
outliner_set_coordinates_element_recursive(space_outliner, ten, startx + UI_UNIT_X, starty);
}
}
@@ -1753,7 +1752,7 @@ static void tree_element_to_path(TreeElement *te,
{
ListBase hierarchy = {NULL, NULL};
LinkData *ld;
- TreeElement *tem, *temnext, *temsub;
+ TreeElement *tem, *temnext;
TreeStoreElem *tse /* , *tsenext */ /* UNUSED */;
PointerRNA *ptr, *nextptr;
PropertyRNA *prop;
@@ -1823,7 +1822,7 @@ static void tree_element_to_path(TreeElement *te,
/* otherwise use index */
int index = 0;
- for (temsub = tem->subtree.first; temsub; temsub = temsub->next, index++) {
+ LISTBASE_FOREACH (TreeElement *, temsub, &tem->subtree) {
if (temsub == temnext) {
break;
}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 0294b4836c8..339cc3068d0 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -42,6 +42,7 @@ struct TreeElement;
struct TreeStoreElem;
struct ViewLayer;
struct bContext;
+struct bContextDataResult;
struct bPoseChannel;
struct wmKeyConfig;
struct wmOperatorType;
@@ -561,6 +562,12 @@ void outliner_tag_redraw_avoid_rebuild_on_open_change(const struct SpaceOutliner
void outliner_sync_selection(const struct bContext *C, struct SpaceOutliner *space_outliner);
+/* outliner_context.c ------------------------------------------- */
+
+int outliner_context(const struct bContext *C,
+ const char *member,
+ struct bContextDataResult *result);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index fa8bce9df6a..6380bb9505e 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -72,6 +72,7 @@
#include "ED_sequencer.h"
#include "ED_undo.h"
+#include "SEQ_select.h"
#include "SEQ_sequencer.h"
#include "WM_api.h"
@@ -870,13 +871,13 @@ static eOLDrawState tree_element_active_sequence(bContext *C,
const eOLSetState set)
{
Sequence *seq = (Sequence *)te->directdata;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (set != OL_SETSEL_NONE) {
/* only check on setting */
if (BLI_findindex(ed->seqbasep, seq) != -1) {
if (set == OL_SETSEL_EXTEND) {
- BKE_sequencer_active_set(scene, NULL);
+ SEQ_select_active_set(scene, NULL);
}
ED_sequencer_deselect_all(scene);
@@ -885,7 +886,7 @@ static eOLDrawState tree_element_active_sequence(bContext *C,
}
else {
seq->flag |= SELECT;
- BKE_sequencer_active_set(scene, seq);
+ SEQ_select_active_set(scene, seq);
}
}
@@ -905,7 +906,7 @@ static eOLDrawState tree_element_active_sequence_dup(Scene *scene,
const eOLSetState set)
{
Sequence *seq, *p;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
seq = (Sequence *)te->directdata;
if (set == OL_SETSEL_NONE) {
@@ -1185,6 +1186,7 @@ static void outliner_set_properties_tab(bContext *C, TreeElement *te, TreeStoreE
}
else {
ModifierData *md = (ModifierData *)te->directdata;
+ BKE_object_modifier_set_active(ob, md);
switch ((ModifierType)md->type) {
case eModifierType_ParticleSystem:
diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c
index 0f5c74a9168..0b2d1ce34ec 100644
--- a/source/blender/editors/space_outliner/outliner_sync.c
+++ b/source/blender/editors/space_outliner/outliner_sync.c
@@ -46,7 +46,7 @@
#include "ED_object.h"
#include "ED_outliner.h"
-#include "SEQ_sequencer.h"
+#include "SEQ_select.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -305,7 +305,7 @@ static void outliner_select_sync_to_sequence(Scene *scene, TreeStoreElem *tselem
Sequence *seq = (Sequence *)tselem->id;
if (tselem->flag & TSE_ACTIVE) {
- BKE_sequencer_active_set(scene, seq);
+ SEQ_select_active_set(scene, seq);
}
if (tselem->flag & TSE_SELECTED) {
@@ -542,7 +542,7 @@ static void get_sync_select_active_data(const bContext *C, SyncSelectActiveData
active_data->object = OBACT(view_layer);
active_data->edit_bone = CTX_data_active_bone(C);
active_data->pose_channel = CTX_data_active_pose_bone(C);
- active_data->sequence = BKE_sequencer_active_get(scene);
+ active_data->sequence = SEQ_select_active_get(scene);
}
/* If outliner is dirty sync selection from view layer and sequwncer */
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 159a4616ba7..d4784a509bf 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -737,7 +737,7 @@ static void id_local_fn(bContext *C,
}
static void object_proxy_to_override_convert_fn(bContext *C,
- ReportList *UNUSED(reports),
+ ReportList *reports,
Scene *UNUSED(scene),
TreeElement *UNUSED(te),
TreeStoreElem *UNUSED(tsep),
@@ -754,8 +754,15 @@ static void object_proxy_to_override_convert_fn(bContext *C,
return;
}
- BKE_lib_override_library_proxy_convert(
- CTX_data_main(C), scene, CTX_data_view_layer(C), ob_proxy);
+ if (!BKE_lib_override_library_proxy_convert(
+ CTX_data_main(C), scene, CTX_data_view_layer(C), ob_proxy)) {
+ BKE_reportf(
+ reports,
+ RPT_ERROR_INVALID_INPUT,
+ "Could not create a library override from proxy '%s' (might use already local data?)",
+ ob_proxy->id.name + 2);
+ return;
+ }
DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_WINDOW, NULL);
@@ -1199,7 +1206,7 @@ static void sequence_fn(int event, TreeElement *te, TreeStoreElem *tselem, void
Sequence *seq = (Sequence *)te->directdata;
if (event == OL_DOP_SELECT) {
Scene *scene = (Scene *)scene_ptr;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (BLI_findindex(ed->seqbasep, seq) != -1) {
ED_sequencer_select_sequence_single(scene, seq, true);
}
@@ -1685,6 +1692,8 @@ typedef enum eOutlinerIdOpTypes {
OUTLINER_IDOP_INVALID = 0,
OUTLINER_IDOP_UNLINK,
+ OUTLINER_IDOP_MARK_ASSET,
+ OUTLINER_IDOP_CLEAR_ASSET,
OUTLINER_IDOP_LOCAL,
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE,
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY,
@@ -1710,6 +1719,8 @@ typedef enum eOutlinerIdOpTypes {
/* TODO: implement support for changing the ID-block used. */
static const EnumPropertyItem prop_id_op_types[] = {
{OUTLINER_IDOP_UNLINK, "UNLINK", 0, "Unlink", ""},
+ {OUTLINER_IDOP_MARK_ASSET, "MARK_ASSET", 0, "Mark Asset", ""},
+ {OUTLINER_IDOP_CLEAR_ASSET, "CLEAR_ASSET", 0, "Clear Asset", ""},
{OUTLINER_IDOP_LOCAL, "LOCAL", 0, "Make Local", ""},
{OUTLINER_IDOP_SINGLE, "SINGLE", 0, "Make Single User", ""},
{OUTLINER_IDOP_DELETE, "DELETE", ICON_X, "Delete", ""},
@@ -1915,6 +1926,14 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
}
break;
}
+ case OUTLINER_IDOP_MARK_ASSET: {
+ WM_operator_name_call(C, "ASSET_OT_mark", WM_OP_EXEC_DEFAULT, NULL);
+ break;
+ }
+ case OUTLINER_IDOP_CLEAR_ASSET: {
+ WM_operator_name_call(C, "ASSET_OT_clear", WM_OP_EXEC_DEFAULT, NULL);
+ break;
+ }
case OUTLINER_IDOP_LOCAL: {
/* make local */
outliner_do_libdata_operation(
@@ -2791,7 +2810,7 @@ static int do_outliner_operation_event(bContext *C,
}
if (datalevel == TSE_ID_BASE) {
/* do nothing... there are no ops needed here yet */
- return 0;
+ return OPERATOR_CANCELLED;
}
if (datalevel == TSE_CONSTRAINT) {
return outliner_operator_menu(C, "OUTLINER_OT_constraint_operation");
@@ -2802,7 +2821,7 @@ static int do_outliner_operation_event(bContext *C,
return outliner_operator_menu(C, "OUTLINER_OT_data_operation");
}
- return 0;
+ return OPERATOR_CANCELLED;
}
static int outliner_operation(bContext *C, wmOperator *op, const wmEvent *event)
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 7308b161d18..56eedcd3748 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -908,9 +908,9 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
/**
* TODO: this function needs to be split up! It's getting a bit too large...
*
- * \note: "ID" is not always a real ID
- * \note: If child items are only added to the tree if the item is open, the TSE_ type _must_ be
- * added to #outliner_element_needs_rebuild_on_open_change().
+ * \note "ID" is not always a real ID.
+ * \note If child items are only added to the tree if the item is open,
+ * the `TSE_` type _must_ be added to #outliner_element_needs_rebuild_on_open_change().
*/
TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
ListBase *lb,
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 3d675fdd9e4..c7c207caca0 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -451,6 +451,7 @@ void ED_spacetype_outliner(void)
st->dropboxes = outliner_dropboxes;
st->id_remap = outliner_id_remap;
st->deactivate = outliner_deactivate;
+ st->context = outliner_context;
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype outliner region");
diff --git a/source/blender/editors/space_outliner/tree/tree_display_data.cc b/source/blender/editors/space_outliner/tree/tree_display_data.cc
index 41ca4f72903..8a5c2e7d9f3 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_data.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_data.cc
@@ -41,7 +41,7 @@ ListBase TreeDisplayDataAPI::buildTree(const TreeSourceData &source_data)
RNA_main_pointer_create(source_data.bmain, &mainptr);
TreeElement *te = outliner_add_element(
- &space_outliner_, &tree, (void *)&mainptr, NULL, TSE_RNA_STRUCT, -1);
+ &space_outliner_, &tree, (void *)&mainptr, nullptr, TSE_RNA_STRUCT, -1);
/* On first view open parent data elements */
const int show_opened = !space_outliner_.treestore ||
diff --git a/source/blender/editors/space_outliner/tree/tree_display_libraries.cc b/source/blender/editors/space_outliner/tree/tree_display_libraries.cc
index bd0870c837c..cb5f42f08e1 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_libraries.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_libraries.cc
@@ -24,6 +24,8 @@
#include "BKE_collection.h"
#include "BKE_main.h"
+#include "DNA_collection_types.h"
+
#include "BLT_translation.h"
#include "../outliner_intern.h"
diff --git a/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc b/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc
index 71c1d344057..0b17ea98831 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc
@@ -68,7 +68,7 @@ ListBase TreeDisplayIDOrphans::buildTree(const TreeSourceData &source_data)
TreeElement *te = nullptr;
if (!filter_id_type) {
ID *id = (ID *)lbarray[a]->first;
- te = outliner_add_element(&space_outliner_, &tree, lbarray[a], NULL, TSE_ID_BASE, 0);
+ te = outliner_add_element(&space_outliner_, &tree, lbarray[a], nullptr, TSE_ID_BASE, 0);
te->directdata = lbarray[a];
te->name = outliner_idcode_to_plural(GS(id->name));
}
diff --git a/source/blender/editors/space_outliner/tree/tree_display_scenes.cc b/source/blender/editors/space_outliner/tree/tree_display_scenes.cc
index c4a5688504d..f377512d81e 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_scenes.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_scenes.cc
@@ -46,7 +46,7 @@ ListBase TreeDisplayScenes::buildTree(const TreeSourceData &source_data)
for (ID *id : List<ID>(source_data.bmain->scenes)) {
Scene *scene = reinterpret_cast<Scene *>(id);
- TreeElement *te = outliner_add_element(&space_outliner_, &tree, scene, NULL, 0, 0);
+ TreeElement *te = outliner_add_element(&space_outliner_, &tree, scene, nullptr, 0, 0);
TreeStoreElem *tselem = TREESTORE(te);
/* New scene elements open by default */
@@ -60,4 +60,4 @@ ListBase TreeDisplayScenes::buildTree(const TreeSourceData &source_data)
return tree;
}
-} // namespace blender::ed::outliner \ No newline at end of file
+} // namespace blender::ed::outliner
diff --git a/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc b/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc
index 486f735be9f..40f329d72c3 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc
@@ -18,7 +18,7 @@
* \ingroup spoutliner
*/
-#include <string.h>
+#include <cstring>
#include "BLI_listbase.h"
#include "BLI_listbase_wrapper.hh"
@@ -43,7 +43,7 @@ ListBase TreeDisplaySequencer::buildTree(const TreeSourceData &source_data)
{
ListBase tree = {nullptr};
- Editing *ed = BKE_sequencer_editing_get(source_data.scene, false);
+ Editing *ed = SEQ_editing_get(source_data.scene, false);
if (ed == nullptr) {
return tree;
}
@@ -51,11 +51,11 @@ ListBase TreeDisplaySequencer::buildTree(const TreeSourceData &source_data)
for (Sequence *seq : List<Sequence>(ed->seqbasep)) {
SequenceAddOp op = need_add_seq_dup(seq);
if (op == SEQUENCE_DUPLICATE_NONE) {
- outliner_add_element(&space_outliner_, &tree, seq, NULL, TSE_SEQUENCE, 0);
+ outliner_add_element(&space_outliner_, &tree, seq, nullptr, TSE_SEQUENCE, 0);
}
else if (op == SEQUENCE_DUPLICATE_ADD) {
TreeElement *te = outliner_add_element(
- &space_outliner_, &tree, seq, NULL, TSE_SEQUENCE_DUP, 0);
+ &space_outliner_, &tree, seq, nullptr, TSE_SEQUENCE_DUP, 0);
add_seq_dup(seq, te, 0);
}
}
diff --git a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc
index c88eb957dd1..f7740f4648f 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc
@@ -20,6 +20,7 @@
#include <iostream>
+#include "DNA_collection_types.h"
#include "DNA_scene_types.h"
#include "BKE_layer.h"
diff --git a/source/blender/editors/space_outliner/tree/tree_element.h b/source/blender/editors/space_outliner/tree/tree_element.h
index 9012321a323..d88c37180b3 100644
--- a/source/blender/editors/space_outliner/tree/tree_element.h
+++ b/source/blender/editors/space_outliner/tree/tree_element.h
@@ -36,7 +36,7 @@ extern "C" {
typedef struct TreeElementType TreeElementType;
TreeElementType *outliner_tree_element_type_create(int type, TreeElement *legacy_te, void *idv);
-void outliner_tree_element_type_free(TreeElementType **element);
+void outliner_tree_element_type_free(TreeElementType **type);
void outliner_tree_element_type_expand(TreeElementType *type, SpaceOutliner *space_outliner);
diff --git a/source/blender/editors/space_outliner/tree/tree_element_nla.hh b/source/blender/editors/space_outliner/tree/tree_element_nla.hh
index 3ca62b13bd8..c94287ce576 100644
--- a/source/blender/editors/space_outliner/tree/tree_element_nla.hh
+++ b/source/blender/editors/space_outliner/tree/tree_element_nla.hh
@@ -23,7 +23,6 @@
#include "tree_element.hh"
struct NlaTrack;
-struct NlaStrip;
namespace blender::ed::outliner {
diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c
index bde7bdb77f1..50cfa2e71c7 100644
--- a/source/blender/editors/space_script/script_edit.c
+++ b/source/blender/editors/space_script/script_edit.c
@@ -152,7 +152,7 @@ void SCRIPT_OT_reload(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Reload Scripts";
- ot->description = "Reload Scripts";
+ ot->description = "Reload scripts";
ot->idname = "SCRIPT_OT_reload";
/* api callbacks */
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 37dfcdbc765..f9076145f2f 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -50,7 +50,15 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "SEQ_add.h"
+#include "SEQ_effects.h"
+#include "SEQ_relations.h"
+#include "SEQ_render.h"
+#include "SEQ_select.h"
#include "SEQ_sequencer.h"
+#include "SEQ_time.h"
+#include "SEQ_transform.h"
+#include "SEQ_utils.h"
/* For menu, popup, icons, etc. */
#include "ED_screen.h"
@@ -81,9 +89,18 @@ typedef struct SequencerAddData {
#define SEQPROP_ENDFRAME (1 << 1)
#define SEQPROP_NOPATHS (1 << 2)
#define SEQPROP_NOCHAN (1 << 3)
+#define SEQPROP_FIT_METHOD (1 << 4)
#define SELECT 1
+static const EnumPropertyItem scale_fit_methods[] = {
+ {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image to fit within the canvas"},
+ {SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image to completely fill the canvas"},
+ {SEQ_STRETCH_TO_FILL, "STRETCH", 0, "Stretch to Fill", "Stretch image to fill the canvas"},
+ {SEQ_USE_ORIGINAL_SIZE, "ORIGINAL", 0, "Use Original Size", "Keep image at its original size"},
+ {0, NULL, 0, NULL, NULL},
+};
+
static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
{
PropertyRNA *prop;
@@ -123,6 +140,15 @@ static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
prop = RNA_def_boolean(
ot->srna, "overlap", 0, "Allow Overlap", "Don't correct overlap on new sequence strips");
RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ if (flag & SEQPROP_FIT_METHOD) {
+ ot->prop = RNA_def_enum(ot->srna,
+ "fit_method",
+ scale_fit_methods,
+ SEQ_SCALE_TO_FIT,
+ "Fit Method",
+ "Scale fit method");
+ }
}
static void sequencer_generic_invoke_path__internal(bContext *C,
@@ -131,7 +157,7 @@ static void sequencer_generic_invoke_path__internal(bContext *C,
{
if (RNA_struct_find_property(op->ptr, identifier)) {
Scene *scene = CTX_data_scene(C);
- Sequence *last_seq = BKE_sequencer_active_get(scene);
+ Sequence *last_seq = SEQ_select_active_get(scene);
if (last_seq && last_seq->strip && SEQ_HAS_PATH(last_seq)) {
Main *bmain = CTX_data_main(C);
char path[FILE_MAX];
@@ -147,7 +173,7 @@ static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type)
Sequence *tgt = NULL;
Sequence *seq;
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true);
+ Editing *ed = SEQ_editing_get(scene, true);
int timeline_frame = (int)CFRA;
int proximity = INT_MAX;
@@ -206,6 +232,8 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato
seq_load->end_frame = seq_load->start_frame;
seq_load->channel = RNA_int_get(op->ptr, "channel");
seq_load->len = 1;
+ seq_load->fit_method = RNA_enum_get(op->ptr, "fit_method");
+ SEQ_tool_settings_fit_method_set(CTX_data_scene(C), seq_load->fit_method);
if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
/* Full path, file is set by the caller. */
@@ -286,11 +314,11 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato
static void sequencer_add_apply_overlap(bContext *C, wmOperator *op, Sequence *seq)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (RNA_boolean_get(op->ptr, "overlap") == false) {
- if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
+ if (SEQ_transform_test_overlap(ed->seqbasep, seq)) {
+ SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
}
}
}
@@ -301,7 +329,7 @@ static void sequencer_add_apply_replace_sel(bContext *C, wmOperator *op, Sequenc
if (RNA_boolean_get(op->ptr, "replace_sel")) {
ED_sequencer_deselect_all(scene);
- BKE_sequencer_active_set(scene, seq);
+ SEQ_select_active_set(scene, seq);
seq->flag |= SELECT;
}
}
@@ -314,7 +342,7 @@ static bool seq_effect_add_properties_poll(const bContext *UNUSED(C),
int type = RNA_enum_get(op->ptr, "type");
/* Hide start/end frames for effect strips that are locked to their parents' location. */
- if (BKE_sequence_effect_get_num_inputs(type) != 0) {
+ if (SEQ_effect_get_num_inputs(type) != 0) {
if (STR_ELEM(prop_id, "frame_start", "frame_end")) {
return false;
}
@@ -330,7 +358,7 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true);
+ Editing *ed = SEQ_editing_get(scene, true);
Scene *sce_seq;
Sequence *seq;
@@ -344,20 +372,20 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_SCENE);
+ seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_SCENE);
seq->blend_mode = SEQ_TYPE_CROSS;
seq->scene = sce_seq;
seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2);
- BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
+ SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq);
- BKE_sequence_calc_disp(scene, seq);
- BKE_sequencer_sort(scene);
+ SEQ_time_update_sequence_bounds(scene, seq);
+ SEQ_sort(scene);
sequencer_add_apply_replace_sel(C, op, seq);
sequencer_add_apply_overlap(C, op, seq);
- BKE_sequence_invalidate_cache_composite(scene, seq);
+ SEQ_relations_invalidate_cache_composite(scene, seq);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
DEG_relations_tag_update(bmain);
@@ -404,7 +432,7 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true);
+ Editing *ed = SEQ_editing_get(scene, true);
MovieClip *clip;
Sequence *seq;
@@ -418,7 +446,7 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MOVIECLIP);
+ seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MOVIECLIP);
seq->blend_mode = SEQ_TYPE_CROSS;
seq->clip = clip;
seq->len = BKE_movieclip_get_duration(clip);
@@ -426,14 +454,14 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
id_us_ensure_real(&seq->clip->id);
BLI_strncpy(seq->name + 2, clip->id.name + 2, sizeof(seq->name) - 2);
- BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
+ SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq);
- BKE_sequence_calc_disp(scene, seq);
- BKE_sequencer_sort(scene);
+ SEQ_time_update_sequence_bounds(scene, seq);
+ SEQ_sort(scene);
sequencer_add_apply_replace_sel(C, op, seq);
sequencer_add_apply_overlap(C, op, seq);
- BKE_sequence_invalidate_cache_composite(scene, seq);
+ SEQ_relations_invalidate_cache_composite(scene, seq);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -480,7 +508,7 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true);
+ Editing *ed = SEQ_editing_get(scene, true);
Mask *mask;
Sequence *seq;
@@ -494,7 +522,7 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MASK);
+ seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MASK);
seq->blend_mode = SEQ_TYPE_CROSS;
seq->mask = mask;
seq->len = BKE_mask_get_duration(mask);
@@ -502,14 +530,14 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
id_us_ensure_real(&seq->mask->id);
BLI_strncpy(seq->name + 2, mask->id.name + 2, sizeof(seq->name) - 2);
- BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
+ SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq);
- BKE_sequence_calc_disp(scene, seq);
- BKE_sequencer_sort(scene);
+ SEQ_time_update_sequence_bounds(scene, seq);
+ SEQ_sort(scene);
sequencer_add_apply_replace_sel(C, op, seq);
sequencer_add_apply_overlap(C, op, seq);
- BKE_sequence_invalidate_cache_composite(scene, seq);
+ SEQ_relations_invalidate_cache_composite(scene, seq);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -554,7 +582,7 @@ void SEQUENCER_OT_mask_strip_add(struct wmOperatorType *ot)
static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoadFn seq_load_fn)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true);
+ Editing *ed = SEQ_editing_get(scene, true);
SeqLoadInfo seq_load;
int tot_files;
@@ -612,7 +640,7 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad
return OPERATOR_CANCELLED;
}
- BKE_sequencer_sort(scene);
+ SEQ_sort(scene);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -644,7 +672,7 @@ static bool sequencer_add_draw_check_fn(PointerRNA *UNUSED(ptr),
static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
{
- return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_movie_strip);
+ return sequencer_add_generic_strip_exec(C, op, SEQ_add_movie_strip);
}
static int sequencer_add_movie_strip_invoke(bContext *C,
@@ -653,12 +681,13 @@ static int sequencer_add_movie_strip_invoke(bContext *C,
{
PropertyRNA *prop;
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
/* Only enable "use_framerate" if there aren't any existing strips, unless overridden by user. */
if (ed && ed->seqbasep && ed->seqbasep->first) {
RNA_boolean_set(op->ptr, "use_framerate", false);
}
+ RNA_enum_set(op->ptr, "fit_method", SEQ_tool_settings_fit_method_get(scene));
/* This is for drag and drop. */
if ((RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) ||
@@ -725,7 +754,7 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY,
FILE_DEFAULTDISPLAY,
FILE_SORT_DEFAULT);
- sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_FIT_METHOD);
RNA_def_boolean(ot->srna, "sound", true, "Sound", "Load sound with the movie");
RNA_def_boolean(ot->srna,
"use_framerate",
@@ -736,7 +765,7 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op)
{
- return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_sound_strip);
+ return sequencer_add_generic_strip_exec(C, op, SEQ_add_sound_strip);
}
static int sequencer_add_sound_strip_invoke(bContext *C,
@@ -850,7 +879,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
{
int minframe, numdigits;
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true);
+ Editing *ed = SEQ_editing_get(scene, true);
SeqLoadInfo seq_load;
Sequence *seq;
Strip *strip;
@@ -878,7 +907,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
}
/* Main adding function. */
- seq = BKE_sequencer_add_image_strip(C, ed->seqbasep, &seq_load);
+ seq = SEQ_add_image_strip(C, ed->seqbasep, &seq_load);
strip = seq->strip;
se = strip->stripdata;
seq->blend_mode = SEQ_TYPE_ALPHAOVER;
@@ -903,8 +932,8 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
}
SEQ_render_init_colorspace(seq);
- BKE_sequence_calc_disp(scene, seq);
- BKE_sequencer_sort(scene);
+ SEQ_time_update_sequence_bounds(scene, seq);
+ SEQ_sort(scene);
/* Last active name. */
BLI_strncpy(ed->act_imagedir, strip->dir, sizeof(ed->act_imagedir));
@@ -914,7 +943,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
MEM_freeN(op->customdata);
}
- BKE_sequence_invalidate_cache_composite(scene, seq);
+ SEQ_relations_invalidate_cache_composite(scene, seq);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -928,6 +957,9 @@ static int sequencer_add_image_strip_invoke(bContext *C,
PropertyRNA *prop;
Scene *scene = CTX_data_scene(C);
+ const SequencerToolSettings *tool_settings = scene->toolsettings->sequencer_tool_settings;
+ RNA_enum_set(op->ptr, "fit_method", tool_settings->fit_method);
+
/* Name set already by drag and drop. */
if (RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) {
sequencer_generic_invoke_xy__internal(
@@ -972,7 +1004,8 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY,
FILE_DEFAULTDISPLAY,
FILE_SORT_DEFAULT);
- sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
+ sequencer_generic_props__internal(ot,
+ SEQPROP_STARTFRAME | SEQPROP_ENDFRAME | SEQPROP_FIT_METHOD);
RNA_def_boolean(ot->srna,
"use_placeholders",
@@ -984,7 +1017,7 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true);
+ Editing *ed = SEQ_editing_get(scene, true);
Sequence *seq;
struct SeqEffectHandle sh;
Sequence *seq1, *seq2, *seq3;
@@ -1007,11 +1040,11 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
RNA_int_set(op->ptr, "frame_end", end_frame);
}
- seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel, type);
- BLI_strncpy(seq->name + 2, BKE_sequence_give_name(seq), sizeof(seq->name) - 2);
- BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
+ seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, type);
+ BLI_strncpy(seq->name + 2, SEQ_sequence_give_name(seq), sizeof(seq->name) - 2);
+ SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq);
- sh = BKE_sequence_get_effect(seq);
+ sh = SEQ_effect_handle_get(seq);
sh.init(seq);
seq->seq1 = seq1;
seq->seq2 = seq2;
@@ -1019,11 +1052,11 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
if (!seq1) {
seq->len = 1; /* Effect is generator, set non zero length. */
- BKE_sequence_tx_set_final_right(seq, end_frame);
+ SEQ_transform_set_right_handle_frame(seq, end_frame);
}
seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
- BKE_sequence_calc(scene, seq);
+ SEQ_time_update_sequence(scene, seq);
if (seq->type == SEQ_TYPE_COLOR) {
SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
@@ -1052,10 +1085,10 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
sequencer_add_apply_replace_sel(C, op, seq);
sequencer_add_apply_overlap(C, op, seq);
- BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs BKE_sequence_calc. */
- BKE_sequencer_sort(scene);
+ SEQ_relations_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs SEQ_time_update_sequence. */
+ SEQ_sort(scene);
- BKE_sequence_invalidate_cache_composite(scene, seq);
+ SEQ_relations_invalidate_cache_composite(scene, seq);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1075,7 +1108,7 @@ static int sequencer_add_effect_strip_invoke(bContext *C,
/* When invoking an effect strip which uses inputs, skip initializing the channel from the
* mouse. */
- if (BKE_sequence_effect_get_num_inputs(type) != 0) {
+ if (SEQ_effect_get_num_inputs(type) != 0) {
prop_flag |= SEQPROP_NOCHAN;
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 081714991ff..2ee0dcea5e5 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -68,7 +68,16 @@
#include "BIF_glutil.h"
+#include "SEQ_effects.h"
+#include "SEQ_prefetch.h"
+#include "SEQ_proxy.h"
+#include "SEQ_relations.h"
+#include "SEQ_render.h"
+#include "SEQ_select.h"
#include "SEQ_sequencer.h"
+#include "SEQ_time.h"
+#include "SEQ_transform.h"
+#include "SEQ_utils.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -227,16 +236,16 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, uchar col[3])
* \param x1, x2, y1, y2: The starting and end X value to draw the wave, same for y1 and y2.
* \param stepsize: The width of a pixel.
*/
-static void draw_seq_waveform(View2D *v2d,
- const bContext *C,
- SpaceSeq *sseq,
- Scene *scene,
- Sequence *seq,
- float x1,
- float y1,
- float x2,
- float y2,
- float stepsize)
+static void draw_seq_waveform_overlay(View2D *v2d,
+ const bContext *C,
+ SpaceSeq *sseq,
+ Scene *scene,
+ Sequence *seq,
+ float x1,
+ float y1,
+ float x2,
+ float y2,
+ float stepsize)
{
/* Offset x1 and x2 values, to match view min/max, if strip is out of bounds. */
int x1_offset = max_ff(v2d->cur.xmin, x1);
@@ -371,7 +380,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
ListBase *seqbase;
int offset;
- seqbase = BKE_sequence_seqbase_get(seqm, &offset);
+ seqbase = SEQ_get_seqbase_from_sequence(seqm, &offset);
if (!seqbase || BLI_listbase_is_empty(seqbase)) {
return;
}
@@ -488,7 +497,7 @@ static void draw_seq_handle(View2D *v2d,
whichsel = SEQ_RIGHTSEL;
}
- if (!(seq->type & SEQ_TYPE_EFFECT) || BKE_sequence_effect_get_num_inputs(seq->type) == 0) {
+ if (!(seq->type & SEQ_TYPE_EFFECT) || SEQ_effect_get_num_inputs(seq->type) == 0) {
GPU_blend(GPU_BLEND_ALPHA);
GPU_blend(GPU_BLEND_ALPHA);
@@ -603,121 +612,110 @@ static void draw_seq_outline(Sequence *seq,
}
}
-/* Draw info text on a sequence strip. */
-static void draw_seq_text(View2D *v2d,
- Sequence *seq,
- SpaceSeq *sseq,
- float x1,
- float x2,
- float y1,
- float y2,
- bool seq_active,
- bool y_threshold)
+static const char *draw_seq_text_get_name(Sequence *seq)
{
- rctf rect;
- char str[32 + FILE_MAX];
- size_t str_len;
const char *name = seq->name + 2;
- uchar col[4];
-
- /* All strings should include name. */
if (name[0] == '\0') {
- name = BKE_sequence_give_name(seq);
+ name = SEQ_sequence_give_name(seq);
}
+ return name;
+}
- if (ELEM(seq->type, SEQ_TYPE_META, SEQ_TYPE_ADJUSTMENT)) {
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
+static void draw_seq_text_get_source(Sequence *seq, char *r_source, size_t source_len)
+{
+ /* Set source for the most common types. */
+ if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE)) {
+ BLI_snprintf(r_source, source_len, "%s%s", seq->strip->dir, seq->strip->stripdata->name);
}
- else if (seq->type == SEQ_TYPE_SCENE) {
- if (seq->scene) {
- if (seq->scene_camera) {
- str_len = BLI_snprintf(str,
- sizeof(str),
- "%s: %s (%s) | %d",
- name,
- seq->scene->id.name + 2,
- ((ID *)seq->scene_camera)->name + 2,
- seq->len);
- }
- else {
- str_len = BLI_snprintf(
- str, sizeof(str), "%s: %s | %d", name, seq->scene->id.name + 2, seq->len);
- }
- }
- else {
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
+ else if (seq->type == SEQ_TYPE_SOUND_RAM) {
+ if (seq->sound) {
+ BLI_snprintf(r_source, source_len, "%s", seq->sound->filepath);
}
}
- else if (seq->type == SEQ_TYPE_MOVIECLIP) {
- if (seq->clip && !STREQ(name, seq->clip->id.name + 2)) {
- str_len = BLI_snprintf(
- str, sizeof(str), "%s: %s | %d", name, seq->clip->id.name + 2, seq->len);
- }
- else {
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
- }
+ else if (seq->type == SEQ_TYPE_MULTICAM) {
+ BLI_snprintf(r_source, source_len, "Channel: %d", seq->multicam_source);
}
- else if (seq->type == SEQ_TYPE_MASK) {
- if (seq->mask && !STREQ(name, seq->mask->id.name + 2)) {
- str_len = BLI_snprintf(
- str, sizeof(str), "%s: %s | %d", name, seq->mask->id.name + 2, seq->len);
+ else if (seq->type == SEQ_TYPE_TEXT) {
+ TextVars *textdata = seq->effectdata;
+ BLI_snprintf(r_source, source_len, "%s", textdata->text);
+ }
+ else if (seq->type == SEQ_TYPE_SCENE) {
+ if (seq->scene_camera) {
+ BLI_snprintf(r_source,
+ source_len,
+ "%s (%s)",
+ seq->scene->id.name + 2,
+ ((ID *)seq->scene_camera)->name + 2);
}
else {
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
+ BLI_snprintf(r_source, source_len, "%s", seq->scene->id.name + 2);
}
}
- else if (seq->type == SEQ_TYPE_MULTICAM) {
- str_len = BLI_snprintf(str, sizeof(str), "Cam %s: %d", name, seq->multicam_source);
- }
- else if (seq->type == SEQ_TYPE_IMAGE) {
- str_len = BLI_snprintf(str,
- sizeof(str),
- "%s: %s%s | %d",
- name,
- seq->strip->dir,
- seq->strip->stripdata->name,
- seq->len);
+ else if (seq->type == SEQ_TYPE_MOVIECLIP) {
+ BLI_snprintf(r_source, source_len, "%s", seq->clip->id.name + 2);
}
- else if (seq->type == SEQ_TYPE_TEXT) {
- TextVars *textdata = seq->effectdata;
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d", textdata->text, seq->startdisp);
+ else if (seq->type == SEQ_TYPE_MASK) {
+ BLI_snprintf(r_source, source_len, "%s", seq->mask->id.name + 2);
}
- else if (seq->type & SEQ_TYPE_EFFECT) {
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
+ else {
+ *r_source = '\0';
}
- else if (seq->type == SEQ_TYPE_SOUND_RAM) {
- /* If a waveform is drawn, avoid to draw text when there is not enough vertical space. */
- if (!y_threshold && (sseq->flag & SEQ_NO_WAVEFORMS) == 0 &&
- ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM))) {
+}
- str[0] = 0;
- str_len = 0;
- }
- else if (seq->sound) {
- str_len = BLI_snprintf(
- str, sizeof(str), "%s: %s | %d", name, seq->sound->filepath, seq->len);
+static size_t draw_seq_text_get_overlay_string(SpaceSeq *sseq,
+ Sequence *seq,
+ char *r_overlay_string,
+ size_t overlay_string_len)
+{
+ const char *name = draw_seq_text_get_name(seq);
+ char source[FILE_MAX];
+ int strip_duration = seq->enddisp - seq->startdisp;
+ draw_seq_text_get_source(seq, source, sizeof(source));
+
+ bool show_name = sseq->flag & SEQ_SHOW_STRIP_NAME;
+ bool show_source = (sseq->flag & (SEQ_SHOW_STRIP_SOURCE)) && source[0] != '\0';
+ bool show_duration = sseq->flag & SEQ_SHOW_STRIP_DURATION;
+
+ size_t string_len = 0;
+ if (show_name) {
+ string_len = BLI_snprintf(r_overlay_string, overlay_string_len, "%s", name);
+ if (show_source || show_duration) {
+ string_len += BLI_snprintf(r_overlay_string + string_len, overlay_string_len, " | ");
}
- else {
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
+ }
+ if (show_source) {
+ string_len += BLI_snprintf(r_overlay_string + string_len, overlay_string_len, "%s", source);
+ if (show_duration) {
+ string_len += BLI_snprintf(r_overlay_string + string_len, overlay_string_len, " | ");
}
}
- else if (seq->type == SEQ_TYPE_MOVIE) {
- str_len = BLI_snprintf(str,
- sizeof(str),
- "%s: %s%s | %d",
- name,
- seq->strip->dir,
- seq->strip->stripdata->name,
- seq->len);
+ if (show_duration) {
+ string_len += BLI_snprintf(
+ r_overlay_string + string_len, overlay_string_len, "%d", strip_duration);
}
- else {
- /* Should never get here!, but might with files from future. */
- BLI_assert(0);
+ return string_len;
+}
+
+/* Draw info text on a sequence strip. */
+static void draw_seq_text_overlay(View2D *v2d,
+ Sequence *seq,
+ SpaceSeq *sseq,
+ float x1,
+ float x2,
+ float y1,
+ float y2,
+ bool seq_active)
+{
+ char overlay_string[FILE_MAX];
+ size_t overlay_string_len = draw_seq_text_get_overlay_string(
+ sseq, seq, overlay_string, sizeof(overlay_string));
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
+ if (overlay_string_len == 0) {
+ return;
}
/* White text for the active strip. */
+ uchar col[4];
col[0] = col[1] = col[2] = seq_active ? 255 : 10;
col[3] = 255;
@@ -731,15 +729,16 @@ static void draw_seq_text(View2D *v2d,
}
}
+ rctf rect;
rect.xmin = x1;
rect.ymin = y1;
rect.xmax = x2;
rect.ymax = y2;
- UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col);
+ UI_view2d_text_cache_add_rectf(v2d, &rect, overlay_string, overlay_string_len, col);
}
-static void draw_sequence_extensions(Scene *scene, Sequence *seq, uint pos, float pixely)
+static void draw_sequence_extensions_overlay(Scene *scene, Sequence *seq, uint pos, float pixely)
{
float x1, x2, y1, y2;
uchar col[4], blend_col[3];
@@ -850,9 +849,9 @@ static void draw_seq_background(Scene *scene,
/* Draw the main strip body. */
if (is_single_image) {
immRectf(pos,
- BKE_sequence_tx_get_final_left(seq, false),
+ SEQ_transform_get_left_handle_frame(seq, false),
y1,
- BKE_sequence_tx_get_final_right(seq, false),
+ SEQ_transform_get_right_handle_frame(seq, false),
y2);
}
else {
@@ -988,7 +987,7 @@ static void fcurve_batch_add_verts(GPUVertBuf *vbo,
* - Volume for sound strips.
* - Opacity for the other types.
*/
-static void draw_seq_fcurve(
+static void draw_seq_fcurve_overlay(
Scene *scene, View2D *v2d, Sequence *seq, float x1, float y1, float x2, float y2, float pixelx)
{
FCurve *fcu;
@@ -1077,7 +1076,7 @@ static void draw_seq_strip(const bContext *C,
float pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
/* Check if we are doing "solo preview". */
- bool is_single_image = (char)BKE_sequence_single_check(seq);
+ bool is_single_image = (char)SEQ_transform_single_image_check(seq);
/* Draw strip body. */
x1 = (seq->startstill) ? seq->start : seq->startdisp;
@@ -1085,11 +1084,21 @@ static void draw_seq_strip(const bContext *C,
x2 = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp;
y2 = seq->machine + SEQ_STRIP_OFSTOP;
- /* Calculate height needed for drawing text on strip. */
- float text_margin_y = y2 - min_ff(0.40f, 20 * U.dpi_fac * pixely);
+ float text_margin_y;
+ bool y_threshold;
+ if ((sseq->flag & SEQ_SHOW_STRIP_NAME) || (sseq->flag & SEQ_SHOW_STRIP_SOURCE) ||
+ (sseq->flag & SEQ_SHOW_STRIP_DURATION)) {
- /* Is there enough space for drawing something else than text? */
- bool y_threshold = ((y2 - y1) / pixely) > 20 * U.dpi_fac;
+ /* Calculate height needed for drawing text on strip. */
+ text_margin_y = y2 - min_ff(0.40f, 20 * U.dpi_fac * pixely);
+
+ /* Is there enough space for drawing something else than text? */
+ y_threshold = ((y2 - y1) / pixely) > 20 * U.dpi_fac;
+ }
+ else {
+ text_margin_y = y2;
+ y_threshold = 1;
+ }
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1102,12 +1111,13 @@ static void draw_seq_strip(const bContext *C,
}
/* Draw strip offsets when flag is enabled or during "solo preview". */
- if (!is_single_image && (seq->startofs || seq->endofs) && pixely > 0) {
- if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) {
- draw_sequence_extensions(scene, seq, pos, pixely);
+ if ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY)) {
+ if (!is_single_image && (seq->startofs || seq->endofs) && pixely > 0) {
+ if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) {
+ draw_sequence_extensions_overlay(scene, seq, pos, pixely);
+ }
}
}
-
immUnbindProgram();
x1 = seq->startdisp;
@@ -1118,31 +1128,31 @@ static void draw_seq_strip(const bContext *C,
drawmeta_contents(scene, seq, x1, y1, x2, y2);
}
- if (sseq->flag & SEQ_SHOW_FCURVES) {
- draw_seq_fcurve(scene, v2d, seq, x1, y1, x2, y2, pixelx);
+ if ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY) && (sseq->flag & SEQ_SHOW_FCURVES)) {
+ draw_seq_fcurve_overlay(scene, v2d, seq, x1, y1, x2, y2, pixelx);
}
/* Draw sound strip waveform. */
- if ((seq->type == SEQ_TYPE_SOUND_RAM) && (sseq->flag & SEQ_NO_WAVEFORMS) == 0) {
- draw_seq_waveform(v2d,
- C,
- sseq,
- scene,
- seq,
- x1,
- y_threshold ? y1 + 0.05f : y1,
- x2,
- y_threshold ? text_margin_y : y2,
- BLI_rctf_size_x(&region->v2d.cur) / region->winx);
+ if ((seq->type == SEQ_TYPE_SOUND_RAM) && ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY)) &&
+ (sseq->flag & SEQ_NO_WAVEFORMS) == 0) {
+ draw_seq_waveform_overlay(v2d,
+ C,
+ sseq,
+ scene,
+ seq,
+ x1,
+ y_threshold ? y1 + 0.05f : y1,
+ x2,
+ y_threshold ? text_margin_y : y2,
+ BLI_rctf_size_x(&region->v2d.cur) / region->winx);
}
-
/* Draw locked state. */
if (seq->flag & SEQ_LOCK) {
draw_seq_locked(x1, y1, x2, y2);
}
/* Draw Red line on the top of invalid strip (Missing media). */
- if (!BKE_sequence_is_valid_check(seq)) {
+ if (!SEQ_sequence_has_source(seq)) {
draw_seq_invalid(x1, x2, y2, text_margin_y);
}
@@ -1162,11 +1172,21 @@ static void draw_seq_strip(const bContext *C,
calculate_seq_text_offsets(v2d, seq, &x1, &x2, pixelx);
- /* Don't draw strip if there is not enough vertical or horizontal space. */
- if (((x2 - x1) > 32 * pixelx * U.dpi_fac) && ((y2 - y1) > 8 * pixely * U.dpi_fac)) {
- /* Depending on the vertical space, draw text on top or in the center of strip. */
- draw_seq_text(
- v2d, seq, sseq, x1, x2, y_threshold ? text_margin_y : y1, y2, seq_active, y_threshold);
+ /* If a waveform is drawn, avoid drawing text when there is not enough vertical space. */
+ if (seq->type == SEQ_TYPE_SOUND_RAM) {
+ if (!y_threshold && (sseq->flag & SEQ_NO_WAVEFORMS) == 0 &&
+ ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM))) {
+ return;
+ }
+ }
+
+ if (sseq->flag & SEQ_SHOW_STRIP_OVERLAY) {
+ /* Don't draw strip if there is not enough vertical or horizontal space. */
+ if (((x2 - x1) > 32 * pixelx * U.dpi_fac) && ((y2 - y1) > 8 * pixely * U.dpi_fac)) {
+ /* Depending on the vertical space, draw text on top or in the center of strip. */
+ draw_seq_text_overlay(
+ v2d, seq, sseq, x1, x2, y_threshold ? text_margin_y : y1, y2, seq_active);
+ }
}
}
@@ -1360,7 +1380,7 @@ static void sequencer_display_size(Scene *scene, float r_viewrect[2])
r_viewrect[0] *= scene->r.xasp / scene->r.yasp;
}
-static void sequencer_draw_gpencil(const bContext *C)
+static void sequencer_draw_gpencil_overlay(const bContext *C)
{
/* Draw grease-pencil (image aligned). */
ED_annotation_draw_2dimage(C);
@@ -1373,7 +1393,9 @@ static void sequencer_draw_gpencil(const bContext *C)
}
/* Draw content and safety borders borders. */
-static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, const Scene *scene)
+static void sequencer_draw_borders_overlay(const SpaceSeq *sseq,
+ const View2D *v2d,
+ const Scene *scene)
{
float x1 = v2d->tot.xmin;
float y1 = v2d->tot.ymin;
@@ -1428,7 +1450,7 @@ void sequencer_draw_maskedit(const bContext *C, Scene *scene, ARegion *region, S
// if (sc->mode == SC_MODE_MASKEDIT)
if (0 && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
- Mask *mask = BKE_sequencer_mask_get(scene);
+ Mask *mask = SEQ_active_mask_get(scene);
if (mask) {
int width, height;
@@ -1460,7 +1482,7 @@ void sequencer_draw_maskedit(const bContext *C, Scene *scene, ARegion *region, S
/* Force redraw, when prefetching and using cache view. */
static void seq_prefetch_wm_notify(const bContext *C, Scene *scene)
{
- if (BKE_sequencer_prefetch_need_redraw(CTX_data_main(C), scene)) {
+ if (SEQ_prefetch_need_redraw(CTX_data_main(C), scene)) {
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
}
}
@@ -1825,17 +1847,17 @@ void sequencer_draw_preview(const bContext *C,
C, scene, region, sseq, ibuf, scope, draw_overlay, draw_backdrop);
/* Draw over image. */
- if (sseq->flag & SEQ_SHOW_METADATA) {
+ if (sseq->flag & SEQ_SHOW_METADATA && sseq->flag & SEQ_SHOW_STRIP_OVERLAY) {
ED_region_image_metadata_draw(0.0, 0.0, ibuf, &v2d->tot, 1.0, 1.0);
}
}
- if (show_imbuf) {
- sequencer_draw_borders(sseq, v2d, scene);
+ if (show_imbuf && (sseq->flag & SEQ_SHOW_STRIP_OVERLAY)) {
+ sequencer_draw_borders_overlay(sseq, v2d, scene);
}
- if (draw_gpencil && show_imbuf) {
- sequencer_draw_gpencil(C);
+ if (draw_gpencil && show_imbuf && (sseq->flag & SEQ_SHOW_STRIP_OVERLAY)) {
+ sequencer_draw_gpencil_overlay(C);
}
#if 0
sequencer_draw_maskedit(C, scene, region, sseq);
@@ -1900,7 +1922,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region)
Scene *scene = CTX_data_scene(C);
View2D *v2d = &region->v2d;
SpaceSeq *sseq = CTX_wm_space_seq(C);
- Sequence *last_seq = BKE_sequencer_active_get(scene);
+ Sequence *last_seq = SEQ_select_active_get(scene);
int sel = 0, j;
float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
@@ -1943,7 +1965,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region)
draw_seq_strip(C, sseq, scene, region, last_seq, pixelx, true);
/* When active strip is an effect, highlight its inputs. */
- if (BKE_sequence_effect_get_num_inputs(last_seq->type) > 0) {
+ if (SEQ_effect_get_num_inputs(last_seq->type) > 0) {
draw_effect_inputs_highlight(last_seq);
}
/* When active is a Multi-cam strip, highlight its source channel. */
@@ -1987,7 +2009,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region)
static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
{
- const Editing *ed = BKE_sequencer_editing_get(scene, false);
+ const Editing *ed = SEQ_editing_get(scene, false);
const int frame_sta = scene->r.sfra;
const int frame_end = scene->r.efra + 1;
@@ -2089,8 +2111,10 @@ static bool draw_cache_view_init_fn(void *userdata, size_t item_count)
}
/* Called as a callback */
-static bool draw_cache_view_iter_fn(
- void *userdata, struct Sequence *seq, int timeline_frame, int cache_type, float UNUSED(cost))
+static bool draw_cache_view_iter_fn(void *userdata,
+ struct Sequence *seq,
+ int timeline_frame,
+ int cache_type)
{
CacheDrawData *drawdata = userdata;
struct View2D *v2d = drawdata->v2d;
@@ -2252,7 +2276,7 @@ static void draw_cache_view(const bContext *C)
userdata.composite_vbo = GPU_vertbuf_create_with_format(&format);
userdata.final_out_vbo = GPU_vertbuf_create_with_format(&format);
- BKE_sequencer_cache_iterate(scene, &userdata, draw_cache_view_init_fn, draw_cache_view_iter_fn);
+ SEQ_cache_iterate(scene, &userdata, draw_cache_view_init_fn, draw_cache_view_iter_fn);
draw_cache_view_batch(userdata.raw_vbo, userdata.raw_vert_count, 1.0f, 0.1f, 0.02f, 0.4f);
draw_cache_view_batch(
@@ -2269,7 +2293,7 @@ static void draw_cache_view(const bContext *C)
void draw_timeline_seq(const bContext *C, ARegion *region)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
SpaceSeq *sseq = CTX_wm_space_seq(C);
View2D *v2d = &region->v2d;
short cfra_flag = 0;
@@ -2292,7 +2316,7 @@ void draw_timeline_seq(const bContext *C, ARegion *region)
UI_view2d_view_ortho(v2d);
/* Get timeline bound-box, needed for the scroll-bars. */
- boundbox_seq(scene, &v2d->tot);
+ SEQ_timeline_boundbox(scene, SEQ_active_seqbase_get(ed), &v2d->tot);
draw_seq_backdrop(v2d);
UI_view2d_constant_grid_draw(v2d, FPS);
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 93b17830c0f..c3553ac88ad 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -45,7 +45,19 @@
#include "BKE_report.h"
#include "BKE_sound.h"
+#include "SEQ_add.h"
+#include "SEQ_clipboard.h"
+#include "SEQ_edit.h"
+#include "SEQ_effects.h"
+#include "SEQ_iterator.h"
+#include "SEQ_prefetch.h"
+#include "SEQ_relations.h"
+#include "SEQ_render.h"
+#include "SEQ_select.h"
#include "SEQ_sequencer.h"
+#include "SEQ_time.h"
+#include "SEQ_transform.h"
+#include "SEQ_utils.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -96,7 +108,7 @@ bool ED_space_sequencer_maskedit_mask_poll(bContext *C)
bool ED_space_sequencer_check_show_maskedit(SpaceSeq *sseq, Scene *scene)
{
if (sseq && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
- return (BKE_sequencer_mask_get(scene) != NULL);
+ return (SEQ_active_mask_get(scene) != NULL);
}
return false;
@@ -136,14 +148,14 @@ bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq)
/* Operator functions. */
bool sequencer_edit_poll(bContext *C)
{
- return (BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL);
+ return (SEQ_editing_get(CTX_data_scene(C), false) != NULL);
}
#if 0 /* UNUSED */
bool sequencer_strip_poll(bContext *C)
{
Editing *ed;
- return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) &&
+ return (((ed = SEQ_editing_get(CTX_data_scene(C), false)) != NULL) &&
(ed->act_seq != NULL));
}
#endif
@@ -152,14 +164,14 @@ bool sequencer_strip_has_path_poll(bContext *C)
{
Editing *ed;
Sequence *seq;
- return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) &&
+ return (((ed = SEQ_editing_get(CTX_data_scene(C), false)) != NULL) &&
((seq = ed->act_seq) != NULL) && (SEQ_HAS_PATH(seq)));
}
bool sequencer_view_preview_poll(bContext *C)
{
SpaceSeq *sseq = CTX_wm_space_seq(C);
- Editing *ed = BKE_sequencer_editing_get(CTX_data_scene(C), false);
+ Editing *ed = SEQ_editing_get(CTX_data_scene(C), false);
if (ed && sseq && (sseq->mainb == SEQ_DRAW_IMG_IMBUF)) {
return 1;
}
@@ -183,117 +195,13 @@ bool sequencer_view_strips_poll(bContext *C)
/** \name Remove Gaps Operator
* \{ */
-static bool sequence_offset_after_frame(Scene *scene, const int delta, const int timeline_frame)
-{
- Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- bool done = false;
- TimeMarker *marker;
-
- /* All strips >= timeline_frame are shifted. */
-
- if (ed == NULL) {
- return 0;
- }
-
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->startdisp >= timeline_frame) {
- BKE_sequence_translate(scene, seq, delta);
- BKE_sequence_calc(scene, seq);
- BKE_sequence_invalidate_cache_preprocessed(scene, seq);
- done = true;
- }
- }
-
- if (!scene->toolsettings->lock_markers) {
- for (marker = scene->markers.first; marker; marker = marker->next) {
- if (marker->frame >= timeline_frame) {
- marker->frame += delta;
- }
- }
- }
-
- return done;
-}
-
-void boundbox_seq(Scene *scene, rctf *rect)
-{
- Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- float min[2], max[2];
-
- if (ed == NULL) {
- return;
- }
-
- min[0] = SFRA;
- max[0] = EFRA + 1;
- min[1] = 0.0;
- max[1] = 8.0;
-
- seq = ed->seqbasep->first;
- while (seq) {
-
- if (min[0] > seq->startdisp - 1) {
- min[0] = seq->startdisp - 1;
- }
- if (max[0] < seq->enddisp + 1) {
- max[0] = seq->enddisp + 1;
- }
- if (max[1] < seq->machine + 2) {
- max[1] = seq->machine + 2;
- }
-
- seq = seq->next;
- }
-
- rect->xmin = min[0];
- rect->xmax = max[0];
- rect->ymin = min[1];
- rect->ymax = max[1];
-}
-
static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- rctf rectf;
- int timeline_frame, efra, sfra;
- bool first = false, done;
- bool do_all = RNA_boolean_get(op->ptr, "all");
-
- /* Get first and last frame. */
- boundbox_seq(scene, &rectf);
- sfra = (int)rectf.xmin;
- efra = (int)rectf.xmax;
-
- /* Check if the current frame has a gap already. */
- for (timeline_frame = CFRA; timeline_frame >= sfra; timeline_frame--) {
- if (SEQ_render_evaluate_frame(scene, timeline_frame)) {
- first = true;
- break;
- }
- }
+ const bool do_all = RNA_boolean_get(op->ptr, "all");
+ const Editing *ed = SEQ_editing_get(scene, false);
- for (; timeline_frame < efra; timeline_frame++) {
- /* There's still no strip to remove a gap for. */
- if (first == false) {
- if (SEQ_render_evaluate_frame(scene, timeline_frame)) {
- first = true;
- }
- }
- else if (SEQ_render_evaluate_frame(scene, timeline_frame) == 0) {
- done = true;
- while (SEQ_render_evaluate_frame(scene, timeline_frame) == 0) {
- done = sequence_offset_after_frame(scene, -1, timeline_frame);
- if (done == false) {
- break;
- }
- }
- if (done == false || do_all == false) {
- break;
- }
- }
- }
+ SEQ_edit_remove_gaps(scene, ed->seqbasep, CFRA, do_all);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
@@ -330,9 +238,9 @@ void SEQUENCER_OT_gap_remove(struct wmOperatorType *ot)
static int sequencer_gap_insert_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- int frames = RNA_int_get(op->ptr, "frames");
-
- sequence_offset_after_frame(scene, frames, CFRA);
+ const int frames = RNA_int_get(op->ptr, "frames");
+ const Editing *ed = SEQ_editing_get(scene, false);
+ SEQ_transform_offset_after_frame(scene, ed->seqbasep, frames, CFRA);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -377,7 +285,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
int snap_frame;
@@ -386,22 +294,22 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
/* Check metas. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK) &&
- BKE_sequence_tx_test(seq)) {
+ SEQ_transform_sequence_can_be_translated(seq)) {
if ((seq->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) {
- BKE_sequence_translate(
+ SEQ_transform_translate_sequence(
scene, seq, (snap_frame - seq->startofs + seq->startstill) - seq->start);
}
else {
if (seq->flag & SEQ_LEFTSEL) {
- BKE_sequence_tx_set_final_left(seq, snap_frame);
+ SEQ_transform_set_left_handle_frame(seq, snap_frame);
}
else { /* SEQ_RIGHTSEL */
- BKE_sequence_tx_set_final_right(seq, snap_frame);
+ SEQ_transform_set_right_handle_frame(seq, snap_frame);
}
- BKE_sequence_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
- BKE_sequence_single_fix(seq);
+ SEQ_transform_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
+ SEQ_transform_fix_single_image_seq_offsets(seq);
}
- BKE_sequence_calc(scene, seq);
+ SEQ_time_update_sequence(scene, seq);
}
}
@@ -410,8 +318,8 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK)) {
seq->flag &= ~SEQ_OVERLAP;
- if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
+ if (SEQ_transform_test_overlap(ed->seqbasep, seq)) {
+ SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
}
}
}
@@ -420,21 +328,21 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->type & SEQ_TYPE_EFFECT) {
if (seq->seq1 && (seq->seq1->flag & SELECT)) {
- BKE_sequencer_offset_animdata(scene, seq, (snap_frame - seq->startdisp));
- BKE_sequence_calc(scene, seq);
+ SEQ_offset_animdata(scene, seq, (snap_frame - seq->startdisp));
+ SEQ_time_update_sequence(scene, seq);
}
else if (seq->seq2 && (seq->seq2->flag & SELECT)) {
- BKE_sequencer_offset_animdata(scene, seq, (snap_frame - seq->startdisp));
- BKE_sequence_calc(scene, seq);
+ SEQ_offset_animdata(scene, seq, (snap_frame - seq->startdisp));
+ SEQ_time_update_sequence(scene, seq);
}
else if (seq->seq3 && (seq->seq3->flag & SELECT)) {
- BKE_sequencer_offset_animdata(scene, seq, (snap_frame - seq->startdisp));
- BKE_sequence_calc(scene, seq);
+ SEQ_offset_animdata(scene, seq, (snap_frame - seq->startdisp));
+ SEQ_time_update_sequence(scene, seq);
}
}
}
- BKE_sequencer_sort(scene);
+ SEQ_sort(scene);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -537,7 +445,7 @@ static int slip_add_sequences_recursive(
for (seq = seqbasep->first; seq; seq = seq->next) {
if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
seq_array[offset + num_items] = seq;
- trim[offset + num_items] = do_trim;
+ trim[offset + num_items] = do_trim && ((seq->type & SEQ_TYPE_EFFECT) == 0);
num_items++;
if (seq->type == SEQ_TYPE_META) {
@@ -545,9 +453,6 @@ static int slip_add_sequences_recursive(
num_items += slip_add_sequences_recursive(
&seq->seqbase, seq_array, trim, num_items + offset, false);
}
- else if (seq->type & SEQ_TYPE_EFFECT) {
- trim[offset + num_items] = false;
- }
}
}
@@ -577,7 +482,7 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
{
SlipData *data;
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
float mouseloc[2];
int num_seq;
View2D *v2d = UI_view2d_fromcontext(C);
@@ -625,7 +530,7 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
{
/* Only data types supported for now. */
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
bool changed = false;
/* Iterate in reverse so meta-strips are iterated after their children. */
@@ -675,11 +580,11 @@ static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
* we can skip calculating for effects.
* This way we can avoid an extra loop just for effects. */
if (!(seq->type & SEQ_TYPE_EFFECT)) {
- BKE_sequence_calc(scene, seq);
+ SEQ_time_update_sequence(scene, seq);
}
}
if (changed) {
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
}
return changed;
}
@@ -709,7 +614,7 @@ static void sequencer_slip_apply_limits(SlipData *data, int *offset)
static int sequencer_slip_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
int offset = RNA_int_get(op->ptr, "offset");
bool success = false;
@@ -844,7 +749,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
case EVT_ESCKEY:
case RIGHTMOUSE: {
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
for (int i = 0; i < data->num_seq; i++) {
transseq_restore(data->ts + i, data->seq_array[i]);
@@ -852,8 +757,8 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
for (int i = 0; i < data->num_seq; i++) {
Sequence *seq = data->seq_array[i];
- BKE_sequence_reload_new_file(bmain, scene, seq, false);
- BKE_sequence_calc(scene, seq);
+ SEQ_add_reload_new_file(bmain, scene, seq, false);
+ SEQ_time_update_sequence(scene, seq);
}
MEM_freeN(data->seq_array);
@@ -864,7 +769,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
if (area) {
ED_area_status_text(area, NULL);
@@ -946,7 +851,7 @@ void SEQUENCER_OT_slip(struct wmOperatorType *ot)
static int sequencer_mute_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
bool selected;
@@ -957,13 +862,13 @@ static int sequencer_mute_exec(bContext *C, wmOperator *op)
if (selected) {
if (seq->flag & SELECT) {
seq->flag |= SEQ_MUTE;
- BKE_sequence_invalidate_dependent(scene, seq);
+ SEQ_relations_invalidate_dependent(scene, seq);
}
}
else {
if ((seq->flag & SELECT) == 0) {
seq->flag |= SEQ_MUTE;
- BKE_sequence_invalidate_dependent(scene, seq);
+ SEQ_relations_invalidate_dependent(scene, seq);
}
}
}
@@ -1002,7 +907,7 @@ void SEQUENCER_OT_mute(struct wmOperatorType *ot)
static int sequencer_unmute_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
bool selected;
@@ -1013,13 +918,13 @@ static int sequencer_unmute_exec(bContext *C, wmOperator *op)
if (selected) {
if (seq->flag & SELECT) {
seq->flag &= ~SEQ_MUTE;
- BKE_sequence_invalidate_dependent(scene, seq);
+ SEQ_relations_invalidate_dependent(scene, seq);
}
}
else {
if ((seq->flag & SELECT) == 0) {
seq->flag &= ~SEQ_MUTE;
- BKE_sequence_invalidate_dependent(scene, seq);
+ SEQ_relations_invalidate_dependent(scene, seq);
}
}
}
@@ -1058,7 +963,7 @@ void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
static int sequencer_lock_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
@@ -1096,7 +1001,7 @@ void SEQUENCER_OT_lock(struct wmOperatorType *ot)
static int sequencer_unlock_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
@@ -1135,18 +1040,18 @@ static int sequencer_reload_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
const bool adjust_length = RNA_boolean_get(op->ptr, "adjust_length");
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT) {
- BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
- BKE_sequence_reload_new_file(bmain, scene, seq, !adjust_length);
+ SEQ_relations_update_changed_seq_and_deps(scene, seq, 0, 1);
+ SEQ_add_reload_new_file(bmain, scene, seq, !adjust_length);
if (adjust_length) {
- if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
+ if (SEQ_transform_test_overlap(ed->seqbasep, seq)) {
+ SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
}
}
}
@@ -1198,9 +1103,9 @@ static bool sequencer_refresh_all_poll(bContext *C)
static int sequencer_refresh_all_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1233,18 +1138,18 @@ int seq_effect_find_selected(Scene *scene,
Sequence **r_selseq3,
const char **r_error_str)
{
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq1 = NULL, *seq2 = NULL, *seq3 = NULL, *seq;
*r_error_str = NULL;
if (!activeseq) {
- seq2 = BKE_sequencer_active_get(scene);
+ seq2 = SEQ_select_active_get(scene);
}
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT) {
- if (seq->type == SEQ_TYPE_SOUND_RAM && BKE_sequence_effect_get_num_inputs(type) != 0) {
+ if (seq->type == SEQ_TYPE_SOUND_RAM && SEQ_effect_get_num_inputs(type) != 0) {
*r_error_str = N_("Cannot apply effects to audio sequence strips");
return 0;
}
@@ -1274,7 +1179,7 @@ int seq_effect_find_selected(Scene *scene,
seq3 = tmp;
}
- switch (BKE_sequence_effect_get_num_inputs(type)) {
+ switch (SEQ_effect_get_num_inputs(type)) {
case 0:
*r_selseq1 = *r_selseq2 = *r_selseq3 = NULL;
return 1; /* Success. */
@@ -1311,10 +1216,10 @@ int seq_effect_find_selected(Scene *scene,
*r_selseq3 = seq3;
/* TODO(Richard): This function needs some refactoring, this is just quick hack for T73828. */
- if (BKE_sequence_effect_get_num_inputs(type) < 3) {
+ if (SEQ_effect_get_num_inputs(type) < 3) {
*r_selseq3 = NULL;
}
- if (BKE_sequence_effect_get_num_inputs(type) < 2) {
+ if (SEQ_effect_get_num_inputs(type) < 2) {
*r_selseq2 = NULL;
}
@@ -1324,24 +1229,24 @@ int seq_effect_find_selected(Scene *scene,
static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Sequence *seq1, *seq2, *seq3, *last_seq = BKE_sequencer_active_get(scene);
+ Sequence *seq1, *seq2, *seq3, *last_seq = SEQ_select_active_get(scene);
const char *error_msg;
- if (BKE_sequence_effect_get_num_inputs(last_seq->type) == 0) {
+ if (SEQ_effect_get_num_inputs(last_seq->type) == 0) {
BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: strip has no inputs");
return OPERATOR_CANCELLED;
}
if (!seq_effect_find_selected(
scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg) ||
- BKE_sequence_effect_get_num_inputs(last_seq->type) == 0) {
+ SEQ_effect_get_num_inputs(last_seq->type) == 0) {
BKE_report(op->reports, RPT_ERROR, error_msg);
return OPERATOR_CANCELLED;
}
/* Check if reassigning would create recursivity. */
- if (BKE_sequencer_render_loop_check(seq1, last_seq) ||
- BKE_sequencer_render_loop_check(seq2, last_seq) ||
- BKE_sequencer_render_loop_check(seq3, last_seq)) {
+ if (SEQ_relations_render_loop_check(seq1, last_seq) ||
+ SEQ_relations_render_loop_check(seq2, last_seq) ||
+ SEQ_relations_render_loop_check(seq3, last_seq)) {
BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: recursion detected");
return OPERATOR_CANCELLED;
}
@@ -1350,7 +1255,7 @@ static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
last_seq->seq2 = seq2;
last_seq->seq3 = seq3;
- BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
+ SEQ_relations_update_changed_seq_and_deps(scene, last_seq, 1, 1);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1360,10 +1265,10 @@ static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
static bool sequencer_effect_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (ed) {
- Sequence *last_seq = BKE_sequencer_active_get(scene);
+ Sequence *last_seq = SEQ_select_active_get(scene);
if (last_seq && (last_seq->type & SEQ_TYPE_EFFECT)) {
return 1;
}
@@ -1396,7 +1301,7 @@ void SEQUENCER_OT_reassign_inputs(struct wmOperatorType *ot)
static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
+ Sequence *seq, *last_seq = SEQ_select_active_get(scene);
if (last_seq->seq1 == NULL || last_seq->seq2 == NULL) {
BKE_report(op->reports, RPT_ERROR, "No valid inputs to swap");
@@ -1407,7 +1312,7 @@ static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op)
last_seq->seq1 = last_seq->seq2;
last_seq->seq2 = seq;
- BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
+ SEQ_relations_update_changed_seq_and_deps(scene, last_seq, 1, 1);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1467,7 +1372,7 @@ static int sequencer_split_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
bool changed = false;
bool seq_selected = false;
@@ -1478,7 +1383,7 @@ static int sequencer_split_exec(bContext *C, wmOperator *op)
const int split_side = RNA_enum_get(op->ptr, "side");
const bool ignore_selection = RNA_boolean_get(op->ptr, "ignore_selection");
- BKE_sequencer_prefetch_stop(scene);
+ SEQ_prefetch_stop(scene);
LISTBASE_FOREACH_BACKWARD (Sequence *, seq, ed->seqbasep) {
if (use_cursor_position && seq->machine != split_channel) {
@@ -1530,7 +1435,7 @@ static int sequencer_split_exec(bContext *C, wmOperator *op)
}
}
- BKE_sequencer_sort(scene);
+ SEQ_sort(scene);
}
if (changed) {
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1673,15 +1578,15 @@ static int apply_unique_name_fn(Sequence *seq, void *arg_pt)
char name[sizeof(seq->name) - 2];
BLI_strncpy_utf8(name, seq->name + 2, sizeof(name));
- BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
- BKE_sequencer_dupe_animdata(scene, name, seq->name + 2);
+ SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
+ SEQ_dupe_animdata(scene, name, seq->name + 2);
return 1;
}
static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
ListBase nseqbase = {NULL, NULL};
@@ -1689,16 +1594,16 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT, 0);
+ SEQ_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT, 0);
if (nseqbase.first) {
Sequence *seq = nseqbase.first;
/* Rely on the nseqbase list being added at the end.
- * Their UUIDs has been re-generated by the BKE_sequence_base_dupli_recursive(), */
+ * Their UUIDs has been re-generated by the SEQ_sequence_base_dupli_recursive(), */
BLI_movelisttolist(ed->seqbasep, &nseqbase);
for (; seq; seq = seq->next) {
- BKE_sequencer_recursive_apply(seq, apply_unique_name_fn, scene);
+ SEQ_iterator_recursive_apply(seq, apply_unique_name_fn, scene);
}
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1733,18 +1638,18 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
- BKE_sequencer_prefetch_stop(scene);
+ SEQ_prefetch_stop(scene);
SEQ_CURRENT_BEGIN (scene->ed, seq) {
if (seq->flag & SELECT) {
- BKE_sequencer_flag_for_removal(scene, ed->seqbasep, seq);
+ SEQ_edit_flag_for_removal(scene, ed->seqbasep, seq);
}
}
SEQ_CURRENT_END;
- BKE_sequencer_remove_flagged_sequences(scene, ed->seqbasep);
+ SEQ_edit_remove_flagged_sequences(scene, ed->seqbasep);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
DEG_relations_tag_update(bmain);
@@ -1794,7 +1699,7 @@ void SEQUENCER_OT_delete(wmOperatorType *ot)
static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
/* For effects, try to find a replacement input. */
@@ -1807,14 +1712,14 @@ static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op))
/* Update lengths, etc. */
seq = ed->seqbasep->first;
while (seq) {
- BKE_sequence_calc(scene, seq);
+ SEQ_time_update_sequence(scene, seq);
seq = seq->next;
}
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
- if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
+ if (SEQ_transform_test_overlap(ed->seqbasep, seq)) {
+ SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
}
}
}
@@ -1849,7 +1754,7 @@ void SEQUENCER_OT_offset_clear(wmOperatorType *ot)
static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq, *seq_new;
Strip *strip_new;
@@ -1859,7 +1764,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
seq = ed->seqbasep->first; /* Poll checks this is valid. */
- BKE_sequencer_prefetch_stop(scene);
+ SEQ_prefetch_stop(scene);
while (seq) {
if ((seq->flag & SELECT) && (seq->type == SEQ_TYPE_IMAGE) && (seq->len > 1)) {
@@ -1871,14 +1776,14 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
/* if (seq->ipo) id_us_min(&seq->ipo->id); */
/* XXX, remove fcurve and assign to split image strips */
- start_ofs = timeline_frame = BKE_sequence_tx_get_final_left(seq, false);
- frame_end = BKE_sequence_tx_get_final_right(seq, false);
+ start_ofs = timeline_frame = SEQ_transform_get_left_handle_frame(seq, false);
+ frame_end = SEQ_transform_get_right_handle_frame(seq, false);
while (timeline_frame < frame_end) {
/* New seq. */
se = SEQ_render_give_stripelem(seq, timeline_frame);
- seq_new = BKE_sequence_dupli_recursive(
+ seq_new = SEQ_sequence_dupli_recursive(
scene, scene, ed->seqbasep, seq, SEQ_DUPE_UNIQUE_NAME);
seq_new->start = start_ofs;
@@ -1897,12 +1802,12 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
BLI_strncpy(se_new->name, se->name, sizeof(se_new->name));
strip_new->stripdata = se_new;
- BKE_sequence_calc(scene, seq_new);
+ SEQ_time_update_sequence(scene, seq_new);
if (step > 1) {
seq_new->flag &= ~SEQ_OVERLAP;
- if (BKE_sequence_test_overlap(ed->seqbasep, seq_new)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seq_new, scene);
+ if (SEQ_transform_test_overlap(ed->seqbasep, seq_new)) {
+ SEQ_transform_seqbase_shuffle(ed->seqbasep, seq_new, scene);
}
}
@@ -1913,7 +1818,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
}
seq_next = seq->next;
- BKE_sequence_free(scene, seq, true);
+ SEQ_sequence_free(scene, seq, true);
seq = seq_next;
}
else {
@@ -1921,7 +1826,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
}
}
- BKE_sequencer_sort(scene);
+ SEQ_sort(scene);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1980,8 +1885,8 @@ void recurs_sel_seq(Sequence *seqm)
static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *last_seq = BKE_sequencer_active_get(scene);
+ Editing *ed = SEQ_editing_get(scene, false);
+ Sequence *last_seq = SEQ_select_active_get(scene);
MetaStack *ms;
if (last_seq && last_seq->type == SEQ_TYPE_META && last_seq->flag & SELECT) {
@@ -1994,7 +1899,7 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
ed->seqbasep = &last_seq->seqbase;
- BKE_sequencer_active_set(scene, NULL);
+ SEQ_select_active_set(scene, NULL);
}
else {
/* Exit metastrip if possible. */
@@ -2017,23 +1922,23 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
/* Recalc all: the meta can have effects connected to it. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- BKE_sequence_calc(scene, seq);
+ SEQ_time_update_sequence(scene, seq);
}
/* 2.73+, keeping endpoints is important!
* Moving them around means you can't usefully use metas in a complex edit. */
#if 1
- BKE_sequence_tx_set_final_left(ms->parseq, ms->disp_range[0]);
- BKE_sequence_tx_set_final_right(ms->parseq, ms->disp_range[1]);
- BKE_sequence_single_fix(ms->parseq);
- BKE_sequence_calc(scene, ms->parseq);
+ SEQ_transform_set_left_handle_frame(ms->parseq, ms->disp_range[0]);
+ SEQ_transform_set_right_handle_frame(ms->parseq, ms->disp_range[1]);
+ SEQ_transform_fix_single_image_seq_offsets(ms->parseq);
+ SEQ_time_update_sequence(scene, ms->parseq);
#else
- if (BKE_sequence_test_overlap(ed->seqbasep, ms->parseq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, ms->parseq, scene);
+ if (SEQ_transform_test_overlap(ed->seqbasep, ms->parseq)) {
+ SEQ_transform_seqbase_shuffle(ed->seqbasep, ms->parseq, scene);
}
#endif
- BKE_sequencer_active_set(scene, ms->parseq);
+ SEQ_select_active_set(scene, ms->parseq);
ms->parseq->flag |= SELECT;
recurs_sel_seq(ms->parseq);
@@ -2071,21 +1976,21 @@ void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
- Sequence *seq, *seqm, *next, *last_seq = BKE_sequencer_active_get(scene);
+ Sequence *seq, *seqm, *next, *last_seq = SEQ_select_active_get(scene);
int channel_max = 1;
- if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
+ if (SEQ_transform_seqbase_isolated_sel_check(ed->seqbasep) == false) {
BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
return OPERATOR_CANCELLED;
}
- BKE_sequencer_prefetch_stop(scene);
+ SEQ_prefetch_stop(scene);
/* Remove all selected from main list, and put in meta. */
- seqm = BKE_sequence_alloc(ed->seqbasep, 1, 1, SEQ_TYPE_META); /* Channel number set later. */
+ seqm = SEQ_sequence_alloc(ed->seqbasep, 1, 1, SEQ_TYPE_META); /* Channel number set later. */
strcpy(seqm->name + 2, "MetaStrip");
seqm->flag = SELECT;
@@ -2093,7 +1998,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
while (seq) {
next = seq->next;
if (seq != seqm && (seq->flag & SELECT)) {
- BKE_sequence_invalidate_cache_composite(scene, seq);
+ SEQ_relations_invalidate_cache_composite(scene, seq);
channel_max = max_ii(seq->machine, channel_max);
/* Sequence is moved within the same edit, no need to re-generate the UUID. */
BLI_remlink(ed->seqbasep, seq);
@@ -2102,18 +2007,18 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
seq = next;
}
seqm->machine = last_seq ? last_seq->machine : channel_max;
- BKE_sequence_calc(scene, seqm);
+ SEQ_time_update_sequence(scene, seqm);
- BKE_sequencer_active_set(scene, seqm);
+ SEQ_select_active_set(scene, seqm);
- if (BKE_sequence_test_overlap(ed->seqbasep, seqm)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seqm, scene);
+ if (SEQ_transform_test_overlap(ed->seqbasep, seqm)) {
+ SEQ_transform_seqbase_shuffle(ed->seqbasep, seqm, scene);
}
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
- BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqm);
- BKE_sequence_invalidate_cache_composite(scene, seqm);
+ SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqm);
+ SEQ_relations_invalidate_cache_composite(scene, seqm);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -2160,7 +2065,7 @@ static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
{
Sequence *seq, *seqn;
- Sequence *last_seq = BKE_sequencer_active_get(scene);
+ Sequence *last_seq = SEQ_select_active_get(scene);
seq = lb->first;
while (seq) {
@@ -2168,12 +2073,12 @@ static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short de
if ((seq->flag & flag) || deleteall) {
BLI_remlink(lb, seq);
if (seq == last_seq) {
- BKE_sequencer_active_set(scene, NULL);
+ SEQ_select_active_set(scene, NULL);
}
if (seq->type == SEQ_TYPE_META) {
recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
}
- BKE_sequence_free(scene, seq, true);
+ SEQ_sequence_free(scene, seq, true);
}
seq = seqn;
}
@@ -2182,18 +2087,18 @@ static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short de
static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
- Sequence *seq, *last_seq = BKE_sequencer_active_get(scene); /* last_seq checks (ed == NULL) */
+ Sequence *seq, *last_seq = SEQ_select_active_get(scene); /* last_seq checks (ed == NULL) */
if (last_seq == NULL || last_seq->type != SEQ_TYPE_META) {
return OPERATOR_CANCELLED;
}
- BKE_sequencer_prefetch_stop(scene);
+ SEQ_prefetch_stop(scene);
for (seq = last_seq->seqbase.first; seq != NULL; seq = seq->next) {
- BKE_sequence_invalidate_cache_composite(scene, seq);
+ SEQ_relations_invalidate_cache_composite(scene, seq);
}
/* This moves strips from meta to parent, sating within same edit and no new strips are
@@ -2204,7 +2109,7 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
BLI_listbase_clear(&last_seq->seqbase);
BLI_remlink(ed->seqbasep, last_seq);
- BKE_sequence_free(scene, last_seq, true);
+ SEQ_sequence_free(scene, last_seq, true);
/* Empty meta strip, delete all effects depending on it. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
@@ -2220,13 +2125,13 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT) {
seq->flag &= ~SEQ_OVERLAP;
- if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
+ if (SEQ_transform_test_overlap(ed->seqbasep, seq)) {
+ SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
}
}
}
- BKE_sequencer_sort(scene);
+ SEQ_sort(scene);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -2262,7 +2167,7 @@ static bool strip_jump_internal(Scene *scene,
{
bool changed = false;
int timeline_frame = CFRA;
- int next_frame = BKE_sequencer_find_next_prev_edit(
+ int next_frame = SEQ_time_find_next_prev_edit(
scene, timeline_frame, side, do_skip_mute, do_center, false);
if (next_frame != timeline_frame) {
@@ -2337,19 +2242,19 @@ static void swap_sequence(Scene *scene, Sequence *seqa, Sequence *seqb)
int seq_b_start;
seq_b_start = (seqb->start - seqb->startdisp) + seqa->startdisp;
- BKE_sequence_translate(scene, seqb, seq_b_start - seqb->start);
- BKE_sequence_calc(scene, seqb);
+ SEQ_transform_translate_sequence(scene, seqb, seq_b_start - seqb->start);
+ SEQ_time_update_sequence(scene, seqb);
seq_a_start = (seqa->start - seqa->startdisp) + seqb->enddisp + gap;
- BKE_sequence_translate(scene, seqa, seq_a_start - seqa->start);
- BKE_sequence_calc(scene, seqa);
+ SEQ_transform_translate_sequence(scene, seqa, seq_a_start - seqa->start);
+ SEQ_time_update_sequence(scene, seqa);
}
static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel)
{
/* sel: 0==unselected, 1==selected, -1==don't care. */
Sequence *seq, *best_seq = NULL;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
int dist, best_dist;
best_dist = MAXFRAME * 2;
@@ -2399,8 +2304,8 @@ static bool seq_is_parent(Sequence *par, Sequence *seq)
static int sequencer_swap_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *active_seq = BKE_sequencer_active_get(scene);
+ Editing *ed = SEQ_editing_get(scene, false);
+ Sequence *active_seq = SEQ_select_active_get(scene);
Sequence *seq, *iseq;
int side = RNA_enum_get(op->ptr, "side");
@@ -2413,11 +2318,11 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op)
if (seq) {
/* Disallow effect strips. */
- if (BKE_sequence_effect_get_num_inputs(seq->type) >= 1 &&
+ if (SEQ_effect_get_num_inputs(seq->type) >= 1 &&
(seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3)) {
return OPERATOR_CANCELLED;
}
- if ((BKE_sequence_effect_get_num_inputs(active_seq->type) >= 1) &&
+ if ((SEQ_effect_get_num_inputs(active_seq->type) >= 1) &&
(active_seq->effectdata || active_seq->seq1 || active_seq->seq2 || active_seq->seq3)) {
return OPERATOR_CANCELLED;
}
@@ -2435,7 +2340,7 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op)
for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) {
if ((iseq->type & SEQ_TYPE_EFFECT) &&
(seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
- BKE_sequence_calc(scene, iseq);
+ SEQ_time_update_sequence(scene, iseq);
}
}
@@ -2444,13 +2349,13 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op)
if ((iseq->type & SEQ_TYPE_EFFECT) &&
(seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
/* This may now overlap. */
- if (BKE_sequence_test_overlap(ed->seqbasep, iseq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene);
+ if (SEQ_transform_test_overlap(ed->seqbasep, iseq)) {
+ SEQ_transform_seqbase_shuffle(ed->seqbasep, iseq, scene);
}
}
}
- BKE_sequencer_sort(scene);
+ SEQ_sort(scene);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -2489,7 +2394,7 @@ static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op))
{
int retval = OPERATOR_CANCELLED;
Scene *scene = CTX_data_scene(C);
- Sequence *active_seq = BKE_sequencer_active_get(scene);
+ Sequence *active_seq = SEQ_select_active_get(scene);
StripElem *se = NULL;
if (active_seq == NULL) {
@@ -2565,11 +2470,11 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
- BKE_sequencer_free_clipboard();
+ SEQ_clipboard_free();
- if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
+ if (SEQ_transform_seqbase_isolated_sel_check(ed->seqbasep) == false) {
BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
return OPERATOR_CANCELLED;
}
@@ -2577,7 +2482,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
/* NOTE: The UUID is re-generated on paste, so we can keep UUID in the clipboard since
* nobody can reach them anyway.
* This reduces chance or running out of UUIDs if a cat falls asleep on Ctrl-C. */
- BKE_sequence_base_dupli_recursive(scene,
+ SEQ_sequence_base_dupli_recursive(scene,
scene,
&seqbase_clipboard,
ed->seqbasep,
@@ -2593,7 +2498,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
/* Replace datablock pointers with copies, to keep things working in case
* data-blocks get deleted or another .blend file is opened. */
- BKE_sequencer_base_clipboard_pointers_store(bmain, &seqbase_clipboard);
+ SEQ_clipboard_pointers_store(bmain, &seqbase_clipboard);
return OPERATOR_FINISHED;
}
@@ -2622,7 +2527,7 @@ void SEQUENCER_OT_copy(wmOperatorType *ot)
void ED_sequencer_deselect_all(Scene *scene)
{
Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (ed == NULL) {
return;
@@ -2634,40 +2539,57 @@ void ED_sequencer_deselect_all(Scene *scene)
SEQ_CURRENT_END;
}
-static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
+static int sequencer_paste_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true); /* Create if needed. */
+ Editing *ed = SEQ_editing_get(scene, true); /* Create if needed. */
ListBase nseqbase = {NULL, NULL};
int ofs;
Sequence *iseq, *iseq_first;
+ if (BLI_listbase_count(&seqbase_clipboard) == 0) {
+ BKE_report(op->reports, RPT_INFO, "No strips to paste");
+ return OPERATOR_CANCELLED;
+ }
+
ED_sequencer_deselect_all(scene);
- ofs = scene->r.cfra - seqbase_clipboard_frame;
+ if (RNA_boolean_get(op->ptr, "keep_offset")) {
+ ofs = scene->r.cfra - seqbase_clipboard_frame;
+ }
+ else {
+ int min_seq_startdisp = INT_MAX;
+ LISTBASE_FOREACH (Sequence *, seq, &seqbase_clipboard) {
+ if (seq->startdisp < min_seq_startdisp) {
+ min_seq_startdisp = seq->startdisp;
+ }
+ }
+ /* Paste strips after playhead. */
+ ofs = scene->r.cfra - min_seq_startdisp;
+ }
/* Copy strips, temporarily restoring pointers to actual data-blocks. This
* must happen on the clipboard itself, so that copying does user counting
* on the actual data-blocks. */
- BKE_sequencer_base_clipboard_pointers_restore(&seqbase_clipboard, bmain);
- BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, &seqbase_clipboard, 0, 0);
- BKE_sequencer_base_clipboard_pointers_store(bmain, &seqbase_clipboard);
+ SEQ_clipboard_pointers_restore(&seqbase_clipboard, bmain);
+ SEQ_sequence_base_dupli_recursive(scene, scene, &nseqbase, &seqbase_clipboard, 0, 0);
+ SEQ_clipboard_pointers_store(bmain, &seqbase_clipboard);
iseq_first = nseqbase.first;
- /* NOTE: BKE_sequence_base_dupli_recursive() takes care of generating new UUIDs for sequences
+ /* NOTE: SEQ_sequence_base_dupli_recursive() takes care of generating new UUIDs for sequences
* in the new list. */
BLI_movelisttolist(ed->seqbasep, &nseqbase);
for (iseq = iseq_first; iseq; iseq = iseq->next) {
/* Make sure, that pasted strips have unique names. */
- BKE_sequencer_recursive_apply(iseq, apply_unique_name_fn, scene);
+ SEQ_iterator_recursive_apply(iseq, apply_unique_name_fn, scene);
/* Translate after name has been changed, otherwise this will affect animdata of original
* strip. */
- BKE_sequence_translate(scene, iseq, ofs);
+ SEQ_transform_translate_sequence(scene, iseq, ofs);
/* Ensure, that pasted strips don't overlap. */
- if (BKE_sequence_test_overlap(ed->seqbasep, iseq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene);
+ if (SEQ_transform_test_overlap(ed->seqbasep, iseq)) {
+ SEQ_transform_seqbase_shuffle(ed->seqbasep, iseq, scene);
}
}
@@ -2692,6 +2614,11 @@ void SEQUENCER_OT_paste(wmOperatorType *ot)
/* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties. */
+ PropertyRNA *prop = RNA_def_boolean(
+ ot->srna, "keep_offset", false, "Keep Offset", "Keep strip offset to playhead when pasting");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */
@@ -2707,12 +2634,12 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
Sequence *seq_other;
const char *error_msg;
- if (BKE_sequencer_active_get_pair(scene, &seq_act, &seq_other) == 0) {
+ if (SEQ_select_active_get_pair(scene, &seq_act, &seq_other) == 0) {
BKE_report(op->reports, RPT_ERROR, "Please select two strips");
return OPERATOR_CANCELLED;
}
- if (BKE_sequence_swap(seq_act, seq_other, &error_msg) == 0) {
+ if (SEQ_edit_sequence_swap(seq_act, seq_other, &error_msg) == 0) {
BKE_report(op->reports, RPT_ERROR, error_msg);
return OPERATOR_CANCELLED;
}
@@ -2728,8 +2655,8 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
seq_act->scene_sound = NULL;
seq_other->scene_sound = NULL;
- BKE_sequence_calc(scene, seq_act);
- BKE_sequence_calc(scene, seq_other);
+ SEQ_time_update_sequence(scene, seq_act);
+ SEQ_time_update_sequence(scene, seq_other);
if (seq_act->sound) {
BKE_sound_add_scene_sound_defaults(scene, seq_act);
@@ -2738,8 +2665,8 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
BKE_sound_add_scene_sound_defaults(scene, seq_other);
}
- BKE_sequence_invalidate_cache_raw(scene, seq_act);
- BKE_sequence_invalidate_cache_raw(scene, seq_other);
+ SEQ_relations_invalidate_cache_raw(scene, seq_act);
+ SEQ_relations_invalidate_cache_raw(scene, seq_other);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -2777,8 +2704,8 @@ static const EnumPropertyItem prop_change_effect_input_types[] = {
static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq = BKE_sequencer_active_get(scene);
+ Editing *ed = SEQ_editing_get(scene, false);
+ Sequence *seq = SEQ_select_active_get(scene);
Sequence **seq_1, **seq_2;
@@ -2804,10 +2731,10 @@ static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op)
SWAP(Sequence *, *seq_1, *seq_2);
- BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
+ SEQ_relations_update_changed_seq_and_deps(scene, seq, 0, 1);
/* Invalidate cache. */
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -2861,8 +2788,8 @@ EnumPropertyItem sequencer_prop_effect_types[] = {
static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq = BKE_sequencer_active_get(scene);
+ Editing *ed = SEQ_editing_get(scene, false);
+ Sequence *seq = SEQ_select_active_get(scene);
const int new_type = RNA_enum_get(op->ptr, "type");
/* Free previous effect and init new effect. */
@@ -2874,23 +2801,22 @@ static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
/* Can someone explain the logic behind only allowing to increase this,
* copied from 2.4x - campbell */
- if (BKE_sequence_effect_get_num_inputs(seq->type) <
- BKE_sequence_effect_get_num_inputs(new_type)) {
+ if (SEQ_effect_get_num_inputs(seq->type) < SEQ_effect_get_num_inputs(new_type)) {
BKE_report(op->reports, RPT_ERROR, "New effect needs more input strips");
return OPERATOR_CANCELLED;
}
- sh = BKE_sequence_get_effect(seq);
+ sh = SEQ_effect_handle_get(seq);
sh.free(seq, true);
seq->type = new_type;
- sh = BKE_sequence_get_effect(seq);
+ sh = SEQ_effect_handle_get(seq);
sh.init(seq);
- BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
+ SEQ_relations_update_changed_seq_and_deps(scene, seq, 0, 1);
/* Invalidate cache. */
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -2928,8 +2854,8 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq = BKE_sequencer_active_get(scene);
+ Editing *ed = SEQ_editing_get(scene, false);
+ Sequence *seq = SEQ_select_active_get(scene);
const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
int minext_frameme, numdigits;
@@ -2982,12 +2908,12 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
/* Correct start/end frames so we don't move.
* Important not to set seq->len = len; allow the function to handle it. */
- BKE_sequence_reload_new_file(bmain, scene, seq, true);
+ SEQ_add_reload_new_file(bmain, scene, seq, true);
- BKE_sequence_calc(scene, seq);
+ SEQ_time_update_sequence(scene, seq);
/* Invalidate cache. */
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
}
else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
bSound *sound = seq->sound;
@@ -3021,7 +2947,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Scene *scene = CTX_data_scene(C);
- Sequence *seq = BKE_sequencer_active_get(scene);
+ Sequence *seq = SEQ_select_active_get(scene);
char filepath[FILE_MAX];
BLI_join_dirfile(filepath, sizeof(filepath), seq->strip->dir, seq->strip->stripdata->name);
@@ -3105,7 +3031,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Sequence *seq, *seq_next;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
ListBase text_seq = {0};
int iter = 0;
FILE *file;
@@ -3144,7 +3070,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BLI_listbase_sort(&text_seq, BKE_sequencer_cmp_time_startdisp);
+ BLI_listbase_sort(&text_seq, SEQ_time_cmp_time_startdisp);
/* Open and write file. */
file = BLI_fopen(filepath, "w");
@@ -3183,7 +3109,7 @@ static bool sequencer_strip_is_text_poll(bContext *C)
{
Editing *ed;
Sequence *seq;
- return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) &&
+ return (((ed = SEQ_editing_get(CTX_data_scene(C), false)) != NULL) &&
((seq = ed->act_seq) != NULL) && (seq->type == SEQ_TYPE_TEXT));
}
@@ -3220,7 +3146,7 @@ void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot)
static int sequencer_set_range_to_strips_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
int sfra = MAXFRAME;
@@ -3291,7 +3217,7 @@ void SEQUENCER_OT_set_range_to_strips(struct wmOperatorType *ot)
static void set_filter_seq(Scene *scene)
{
Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (ed == NULL) {
return;
@@ -3305,8 +3231,8 @@ static void set_filter_seq(Scene *scene)
if (seq->flag & SELECT) {
if (seq->type == SEQ_TYPE_MOVIE) {
seq->flag |= SEQ_FILTERY;
- BKE_sequence_reload_new_file(bmain, scene, seq, false);
- BKE_sequence_calc(scene, seq);
+ SEQ_add_reload_new_file(bmain, scene, seq, false);
+ SEQ_time_update_sequence(scene, seq);
}
}
}
@@ -3315,8 +3241,8 @@ static void set_filter_seq(Scene *scene)
static void UNUSED_FUNCTION(seq_remap_paths)(Scene *scene)
{
- Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq, *last_seq = SEQ_select_active_get(scene);
+ Editing *ed = SEQ_editing_get(scene, false);
char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
if (last_seq == NULL) {
@@ -3355,7 +3281,7 @@ static void UNUSED_FUNCTION(seq_remap_paths)(Scene *scene)
static Sequence *sequence_find_parent(Scene *scene, Sequence *child)
{
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *parent = NULL;
Sequence *seq;
@@ -3407,7 +3333,7 @@ Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int se
{
/* sel: 0==unselected, 1==selected, -1==don't care. */
Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (ed == NULL) {
return NULL;
@@ -3441,7 +3367,7 @@ Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int se
Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[2])
{
Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
float x, y;
float pixelx;
float handsize;
@@ -3463,7 +3389,7 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[
/* Check for both normal strips, and strips that have been flipped horizontally. */
if (((seq->startdisp < seq->enddisp) && (seq->startdisp <= x && seq->enddisp >= x)) ||
((seq->startdisp > seq->enddisp) && (seq->startdisp >= x && seq->enddisp <= x))) {
- if (BKE_sequence_tx_test(seq)) {
+ if (SEQ_transform_sequence_can_be_translated(seq)) {
/* Clamp handles to defined size in pixel space. */
handsize = 2.0f * sequence_handle_size_get_clamped(seq, pixelx);
@@ -3499,3 +3425,148 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Strip Transform Operator
+ * \{ */
+
+enum {
+ STRIP_TRANSFORM_POSITION,
+ STRIP_TRANSFORM_SCALE,
+ STRIP_TRANSFORM_ROTATION,
+ STRIP_TRANSFORM_ALL,
+};
+
+static const EnumPropertyItem transform_reset_properties[] = {
+ {STRIP_TRANSFORM_POSITION, "POSITION", 0, "Position", "Reset strip transform location"},
+ {STRIP_TRANSFORM_SCALE, "SCALE", 0, "Scale", "Reset strip transform scale"},
+ {STRIP_TRANSFORM_ROTATION, "ROTATION", 0, "Rotation", "Reset strip transform rotation"},
+ {STRIP_TRANSFORM_ALL, "ALL", 0, "All", "Reset strip transform location, scale and rotation"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static int sequencer_strip_transform_clear_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ const Editing *ed = SEQ_editing_get(scene, false);
+ Sequence *seq;
+ const int property = RNA_enum_get(op->ptr, "property");
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT && seq->type != SEQ_TYPE_SOUND_RAM) {
+ StripTransform *transform = seq->strip->transform;
+ switch (property) {
+ case STRIP_TRANSFORM_POSITION:
+ transform->xofs = 0;
+ transform->yofs = 0;
+ break;
+ case STRIP_TRANSFORM_SCALE:
+ transform->scale_x = 1.0f;
+ transform->scale_y = 1.0f;
+ break;
+ case STRIP_TRANSFORM_ROTATION:
+ transform->rotation = 0.0f;
+ break;
+ case STRIP_TRANSFORM_ALL:
+ transform->xofs = 0;
+ transform->yofs = 0;
+ transform->scale_x = 1.0f;
+ transform->scale_y = 1.0f;
+ transform->rotation = 0.0f;
+ break;
+ }
+ SEQ_relations_invalidate_cache_preprocessed(scene, seq);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_strip_transform_clear(struct wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Clear Strip Transform";
+ ot->idname = "SEQUENCER_OT_strip_transform_clear";
+ ot->description = "Reset image transformation to default value";
+
+ /* Api callbacks. */
+ ot->exec = sequencer_strip_transform_clear_exec;
+ ot->poll = sequencer_edit_poll;
+
+ /* Flags. */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna,
+ "property",
+ transform_reset_properties,
+ STRIP_TRANSFORM_ALL,
+ "Property",
+ "Strip transform property to be reset");
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform Set Fit Operator
+ * \{ */
+
+static const EnumPropertyItem scale_fit_methods[] = {
+ {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image so fits in preview"},
+ {SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image so it fills preview completely"},
+ {SEQ_STRETCH_TO_FILL, "STRETCH", 0, "Stretch to Fill", "Stretch image so it fills preview"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static int sequencer_strip_transform_fit_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ const Editing *ed = SEQ_editing_get(scene, false);
+ Sequence *seq;
+ const eSeqImageFitMethod fit_method = RNA_enum_get(op->ptr, "fit_method");
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT && seq->type != SEQ_TYPE_SOUND_RAM) {
+ const int timeline_frame = CFRA;
+ StripElem *strip_elem = SEQ_render_give_stripelem(seq, timeline_frame);
+
+ if (strip_elem == NULL) {
+ continue;
+ }
+
+ SEQ_set_scale_to_fit(seq,
+ strip_elem->orig_width,
+ strip_elem->orig_height,
+ scene->r.xsch,
+ scene->r.ysch,
+ fit_method);
+ SEQ_relations_invalidate_cache_preprocessed(scene, seq);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_strip_transform_fit(struct wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Strip Transform Set Fit";
+ ot->idname = "SEQUENCER_OT_strip_transform_fit";
+
+ /* Api callbacks. */
+ ot->exec = sequencer_strip_transform_fit_exec;
+ ot->poll = sequencer_edit_poll;
+
+ /* Flags. */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna,
+ "fit_method",
+ scale_fit_methods,
+ SEQ_SCALE_TO_FIT,
+ "Fit Method",
+ "Scale fit fit_method");
+}
+
+/** \} */
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 1ea4fb05d53..4c942a83f2b 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -71,7 +71,6 @@ struct ImBuf *sequencer_ibuf_get(struct Main *bmain,
/* sequencer_edit.c */
struct View2D;
void seq_rectf(struct Sequence *seq, struct rctf *rectf);
-void boundbox_seq(struct Scene *scene, struct rctf *rect);
struct Sequence *find_nearest_seq(struct Scene *scene,
struct View2D *v2d,
int *hand,
@@ -145,6 +144,8 @@ void SEQUENCER_OT_enable_proxies(struct wmOperatorType *ot);
void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot);
void SEQUENCER_OT_set_range_to_strips(struct wmOperatorType *ot);
+void SEQUENCER_OT_strip_transform_clear(struct wmOperatorType *ot);
+void SEQUENCER_OT_strip_transform_fit(struct wmOperatorType *ot);
/* sequencer_select.c */
void SEQUENCER_OT_select_all(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c
index fb09afc6ca5..f11a879912c 100644
--- a/source/blender/editors/space_sequencer/sequencer_modifier.c
+++ b/source/blender/editors/space_sequencer/sequencer_modifier.c
@@ -34,6 +34,10 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "SEQ_iterator.h"
+#include "SEQ_modifier.h"
+#include "SEQ_relations.h"
+#include "SEQ_select.h"
#include "SEQ_sequencer.h"
/* Own include. */
@@ -44,13 +48,13 @@
static bool strip_modifier_active_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (ed) {
- Sequence *seq = BKE_sequencer_active_get(scene);
+ Sequence *seq = SEQ_select_active_get(scene);
if (seq) {
- return BKE_sequence_supports_modifiers(seq);
+ return SEQ_sequence_supports_modifiers(seq);
}
}
@@ -60,12 +64,12 @@ static bool strip_modifier_active_poll(bContext *C)
static int strip_modifier_add_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Sequence *seq = BKE_sequencer_active_get(scene);
+ Sequence *seq = SEQ_select_active_get(scene);
int type = RNA_enum_get(op->ptr, "type");
- BKE_sequence_modifier_new(seq, NULL, type);
+ SEQ_modifier_new(seq, NULL, type);
- BKE_sequence_invalidate_cache_preprocessed(scene, seq);
+ SEQ_relations_invalidate_cache_preprocessed(scene, seq);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -102,21 +106,21 @@ void SEQUENCER_OT_strip_modifier_add(wmOperatorType *ot)
static int strip_modifier_remove_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Sequence *seq = BKE_sequencer_active_get(scene);
+ Sequence *seq = SEQ_select_active_get(scene);
char name[MAX_NAME];
SequenceModifierData *smd;
RNA_string_get(op->ptr, "name", name);
- smd = BKE_sequence_modifier_find_by_name(seq, name);
+ smd = SEQ_modifier_find_by_name(seq, name);
if (!smd) {
return OPERATOR_CANCELLED;
}
BLI_remlink(&seq->modifiers, smd);
- BKE_sequence_modifier_free(smd);
+ SEQ_modifier_free(smd);
- BKE_sequence_invalidate_cache_preprocessed(scene, seq);
+ SEQ_relations_invalidate_cache_preprocessed(scene, seq);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -153,7 +157,7 @@ enum {
static int strip_modifier_move_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Sequence *seq = BKE_sequencer_active_get(scene);
+ Sequence *seq = SEQ_select_active_get(scene);
char name[MAX_NAME];
int direction;
SequenceModifierData *smd;
@@ -161,7 +165,7 @@ static int strip_modifier_move_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "name", name);
direction = RNA_enum_get(op->ptr, "direction");
- smd = BKE_sequence_modifier_find_by_name(seq, name);
+ smd = SEQ_modifier_find_by_name(seq, name);
if (!smd) {
return OPERATOR_CANCELLED;
}
@@ -179,7 +183,7 @@ static int strip_modifier_move_exec(bContext *C, wmOperator *op)
}
}
- BKE_sequence_invalidate_cache_preprocessed(scene, seq);
+ SEQ_relations_invalidate_cache_preprocessed(scene, seq);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -225,7 +229,7 @@ static int strip_modifier_copy_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Editing *ed = scene->ed;
- Sequence *seq = BKE_sequencer_active_get(scene);
+ Sequence *seq = SEQ_select_active_get(scene);
Sequence *seq_iter;
const int type = RNA_enum_get(op->ptr, "type");
@@ -245,19 +249,19 @@ static int strip_modifier_copy_exec(bContext *C, wmOperator *op)
while (smd) {
smd_tmp = smd->next;
BLI_remlink(&seq_iter->modifiers, smd);
- BKE_sequence_modifier_free(smd);
+ SEQ_modifier_free(smd);
smd = smd_tmp;
}
BLI_listbase_clear(&seq_iter->modifiers);
}
}
- BKE_sequence_modifier_list_copy(seq_iter, seq);
+ SEQ_modifier_list_copy(seq_iter, seq);
}
}
SEQ_CURRENT_END;
- BKE_sequence_invalidate_cache_preprocessed(scene, seq);
+ SEQ_relations_invalidate_cache_preprocessed(scene, seq);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index bdf6e4ece7f..7bfc8600544 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -81,6 +81,8 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_change_path);
WM_operatortype_append(SEQUENCER_OT_set_range_to_strips);
+ WM_operatortype_append(SEQUENCER_OT_strip_transform_clear);
+ WM_operatortype_append(SEQUENCER_OT_strip_transform_fit);
/* sequencer_select.c */
WM_operatortype_append(SEQUENCER_OT_select_all);
diff --git a/source/blender/editors/space_sequencer/sequencer_proxy.c b/source/blender/editors/space_sequencer/sequencer_proxy.c
index 2d23520814a..b04363a4f33 100644
--- a/source/blender/editors/space_sequencer/sequencer_proxy.c
+++ b/source/blender/editors/space_sequencer/sequencer_proxy.c
@@ -34,6 +34,9 @@
#include "BKE_main.h"
#include "BKE_report.h"
+#include "SEQ_iterator.h"
+#include "SEQ_proxy.h"
+#include "SEQ_relations.h"
#include "SEQ_sequencer.h"
#include "WM_api.h"
@@ -90,14 +93,14 @@ static void proxy_startjob(void *pjv, short *stop, short *do_update, float *prog
static void proxy_endjob(void *pjv)
{
ProxyJob *pj = pjv;
- Editing *ed = BKE_sequencer_editing_get(pj->scene, false);
+ Editing *ed = SEQ_editing_get(pj->scene, false);
LinkData *link;
for (link = pj->queue.first; link; link = link->next) {
SEQ_proxy_rebuild_finish(link->data, pj->stop);
}
- BKE_sequencer_free_imbuf(pj->scene, &ed->seqbase, false);
+ SEQ_relations_free_imbuf(pj->scene, &ed->seqbase, false);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
}
@@ -108,7 +111,7 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports)
ProxyJob *pj;
struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
ScrArea *area = CTX_wm_area(C);
Sequence *seq;
GSet *file_list;
@@ -201,7 +204,7 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
Main *bmain = CTX_data_main(C);
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
GSet *file_list;
@@ -225,7 +228,7 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
SEQ_proxy_rebuild(context, &stop, &do_update, &progress);
SEQ_proxy_rebuild_finish(context, 0);
}
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
}
}
SEQ_CURRENT_END;
@@ -266,7 +269,7 @@ static int sequencer_enable_proxies_invoke(bContext *C,
static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
bool proxy_25 = RNA_boolean_get(op->ptr, "proxy_25");
bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50");
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index a6b2d7feae3..edbffa8f693 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -39,6 +39,8 @@
#include "RNA_define.h"
+#include "SEQ_iterator.h"
+#include "SEQ_select.h"
#include "SEQ_sequencer.h"
/* For menu, popup, icons, etc. */
@@ -198,13 +200,13 @@ void select_surround_from_last(Scene *scene)
void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool deselect_all)
{
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (deselect_all) {
ED_sequencer_deselect_all(scene);
}
- BKE_sequencer_active_set(scene, seq);
+ SEQ_select_active_set(scene, seq);
if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE)) {
if (seq->strip) {
@@ -223,7 +225,7 @@ void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool desel
#if 0
static void select_neighbor_from_last(Scene *scene, int lr)
{
- Sequence *seq = BKE_sequencer_active_get(scene);
+ Sequence *seq = SEQ_select_active_get(scene);
Sequence *neighbor;
bool changed = false;
if (seq) {
@@ -264,7 +266,7 @@ static int sequencer_de_select_all_exec(bContext *C, wmOperator *op)
int action = RNA_enum_get(op->ptr, "action");
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
if (action == SEL_TOGGLE) {
@@ -331,7 +333,7 @@ void SEQUENCER_OT_select_all(struct wmOperatorType *ot)
static int sequencer_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
@@ -376,7 +378,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
{
View2D *v2d = UI_view2d_fromcontext(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
const bool extend = RNA_boolean_get(op->ptr, "extend");
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
const bool linked_handle = RNA_boolean_get(op->ptr, "linked_handle");
@@ -464,7 +466,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
ret_value = OPERATOR_FINISHED;
}
- BKE_sequencer_active_set(scene, seq);
+ SEQ_select_active_set(scene, seq);
if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE)) {
if (seq->strip) {
@@ -667,7 +669,7 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
/* Run recursively to select linked. */
static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool linked)
{
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq, *neighbor;
bool changed = false;
int isel;
@@ -900,27 +902,84 @@ void SEQUENCER_OT_select_linked(wmOperatorType *ot)
/** \name Select Handles Operator
* \{ */
+enum {
+ SEQ_SELECT_HANDLES_SIDE_LEFT,
+ SEQ_SELECT_HANDLES_SIDE_RIGHT,
+ SEQ_SELECT_HANDLES_SIDE_BOTH,
+ SEQ_SELECT_HANDLES_SIDE_LEFT_NEIGHBOR,
+ SEQ_SELECT_HANDLES_SIDE_RIGHT_NEIGHBOR,
+ SEQ_SELECT_HANDLES_SIDE_BOTH_NEIGHBORS,
+};
+
+static const EnumPropertyItem prop_select_handles_side_types[] = {
+ {SEQ_SELECT_HANDLES_SIDE_LEFT, "LEFT", 0, "Left", ""},
+ {SEQ_SELECT_HANDLES_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
+ {SEQ_SELECT_HANDLES_SIDE_BOTH, "BOTH", 0, "Both", ""},
+ {SEQ_SELECT_HANDLES_SIDE_LEFT_NEIGHBOR, "LEFT_NEIGHBOR", 0, "Left Neighbor", ""},
+ {SEQ_SELECT_HANDLES_SIDE_RIGHT_NEIGHBOR, "RIGHT_NEIGHBOR", 0, "Right Neighbor", ""},
+ {SEQ_SELECT_HANDLES_SIDE_BOTH_NEIGHBORS, "BOTH_NEIGHBORS", 0, "Both Neighbors", ""},
+ {0, NULL, 0, NULL, NULL},
+};
+
static int sequencer_select_handles_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq;
int sel_side = RNA_enum_get(op->ptr, "side");
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT) {
+ Sequence *l_neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, -1);
+ Sequence *r_neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, -1);
+
switch (sel_side) {
- case SEQ_SIDE_LEFT:
+ case SEQ_SELECT_HANDLES_SIDE_LEFT:
seq->flag &= ~SEQ_RIGHTSEL;
seq->flag |= SEQ_LEFTSEL;
break;
- case SEQ_SIDE_RIGHT:
+ case SEQ_SELECT_HANDLES_SIDE_RIGHT:
seq->flag &= ~SEQ_LEFTSEL;
seq->flag |= SEQ_RIGHTSEL;
break;
- case SEQ_SIDE_BOTH:
+ case SEQ_SELECT_HANDLES_SIDE_BOTH:
seq->flag |= SEQ_LEFTSEL | SEQ_RIGHTSEL;
break;
+ case SEQ_SELECT_HANDLES_SIDE_LEFT_NEIGHBOR:
+ if (l_neighbor) {
+ if (!(l_neighbor->flag & SELECT)) {
+ l_neighbor->flag |= SEQ_RIGHTSEL;
+ }
+ }
+ break;
+ case SEQ_SELECT_HANDLES_SIDE_RIGHT_NEIGHBOR:
+ if (r_neighbor) {
+ if (!(r_neighbor->flag & SELECT)) {
+ r_neighbor->flag |= SEQ_LEFTSEL;
+ }
+ }
+ break;
+ case SEQ_SELECT_HANDLES_SIDE_BOTH_NEIGHBORS:
+ if (l_neighbor) {
+ if (!(l_neighbor->flag & SELECT)) {
+ l_neighbor->flag |= SEQ_RIGHTSEL;
+ }
+ }
+ if (r_neighbor) {
+ if (!(r_neighbor->flag & SELECT)) {
+ r_neighbor->flag |= SEQ_LEFTSEL;
+ }
+ break;
+ }
+ }
+ }
+ }
+ /* Select strips */
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if ((seq->flag & SEQ_LEFTSEL) || (seq->flag & SEQ_RIGHTSEL)) {
+ if (!(seq->flag & SELECT)) {
+ seq->flag |= SELECT;
+ recurs_sel_seq(seq);
}
}
}
@@ -949,8 +1008,8 @@ void SEQUENCER_OT_select_handles(wmOperatorType *ot)
/* Properties. */
RNA_def_enum(ot->srna,
"side",
- prop_side_types,
- SEQ_SIDE_BOTH,
+ prop_select_handles_side_types,
+ SEQ_SELECT_HANDLES_SIDE_BOTH,
"Side",
"The side of the handle that is selected");
}
@@ -964,7 +1023,7 @@ void SEQUENCER_OT_select_handles(wmOperatorType *ot)
static int sequencer_select_side_of_frame_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
const bool extend = RNA_boolean_get(op->ptr, "extend");
const int side = RNA_enum_get(op->ptr, "side");
Sequence *seq;
@@ -1038,7 +1097,7 @@ void SEQUENCER_OT_select_side_of_frame(wmOperatorType *ot)
static int sequencer_select_side_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
const int sel_side = RNA_enum_get(op->ptr, "side");
const int frame_init = sel_side == SEQ_SIDE_LEFT ? INT_MIN : INT_MAX;
@@ -1109,7 +1168,7 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
View2D *v2d = UI_view2d_fromcontext(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Editing *ed = SEQ_editing_get(scene, false);
if (ed == NULL) {
return OPERATOR_CANCELLED;
@@ -1454,8 +1513,7 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int
actseq->tmp = POINTER_FROM_INT(true);
- for (BKE_sequence_iterator_begin(ed, &iter, true); iter.valid;
- BKE_sequence_iterator_next(&iter)) {
+ for (SEQ_iterator_begin(ed, &iter, true); iter.valid; SEQ_iterator_next(&iter)) {
seq = iter.seq;
/* Ignore all seqs already selected. */
@@ -1486,8 +1544,8 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int
changed = true;
/* Unfortunately, we must restart checks from the beginning. */
- BKE_sequence_iterator_end(&iter);
- BKE_sequence_iterator_begin(ed, &iter, true);
+ SEQ_iterator_end(&iter);
+ SEQ_iterator_begin(ed, &iter, true);
}
/* Video strips below active one, or any strip for audio (order doesn't matter here). */
@@ -1496,7 +1554,7 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int
changed = true;
}
}
- BKE_sequence_iterator_end(&iter);
+ SEQ_iterator_end(&iter);
return changed;
}
@@ -1508,8 +1566,8 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int
static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq, *actseq = BKE_sequencer_active_get(scene);
+ Editing *ed = SEQ_editing_get(scene, false);
+ Sequence *seq, *actseq = SEQ_select_active_get(scene);
if (actseq == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active sequence!");
diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c
index 75d92d5f00d..8805d5af227 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -38,7 +38,9 @@
#include "RNA_define.h"
+#include "SEQ_select.h"
#include "SEQ_sequencer.h"
+#include "SEQ_time.h"
/* For menu, popup, icons, etc. */
#include "ED_anim_api.h"
@@ -87,8 +89,10 @@ static int sequencer_view_all_exec(bContext *C, wmOperator *op)
rctf box;
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ Scene *scene = CTX_data_scene(C);
+ const Editing *ed = SEQ_editing_get(scene, false);
- boundbox_seq(CTX_data_scene(C), &box);
+ SEQ_timeline_boundbox(scene, SEQ_active_seqbase_get(ed), &box);
UI_view2d_smooth_view(C, region, &box, smooth_viewtx);
return OPERATOR_FINISHED;
}
@@ -270,8 +274,8 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
View2D *v2d = UI_view2d_fromcontext(C);
ARegion *region = CTX_wm_region(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *last_seq = BKE_sequencer_active_get(scene);
+ Editing *ed = SEQ_editing_get(scene, false);
+ Sequence *last_seq = SEQ_select_active_get(scene);
Sequence *seq;
rctf cur_new = v2d->cur;
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 45c7bac54f8..b11e2a32b87 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -52,6 +52,7 @@
#include "RNA_access.h"
#include "SEQ_sequencer.h"
+#include "SEQ_utils.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -99,7 +100,8 @@ static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *sce
sseq->view = SEQ_VIEW_SEQUENCE;
sseq->mainb = SEQ_DRAW_IMG_IMBUF;
sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKERS | SEQ_SHOW_FCURVES |
- SEQ_ZOOM_TO_FIT;
+ SEQ_ZOOM_TO_FIT | SEQ_SHOW_STRIP_OVERLAY | SEQ_SHOW_STRIP_NAME |
+ SEQ_SHOW_STRIP_SOURCE | SEQ_SHOW_STRIP_DURATION;
/* Tool header. */
region = MEM_callocN(sizeof(ARegion), "tool header for sequencer");
@@ -470,7 +472,7 @@ static int /*eContextResult*/ sequencer_context(const bContext *C,
return CTX_RESULT_OK;
}
if (CTX_data_equals(member, "edit_mask")) {
- Mask *mask = BKE_sequencer_mask_get(scene);
+ Mask *mask = SEQ_active_mask_get(scene);
if (mask) {
CTX_data_id_pointer_set(result, &mask->id);
}
@@ -706,7 +708,8 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *region)
SpaceSeq *sseq = area->spacedata.first;
Scene *scene = CTX_data_scene(C);
wmWindowManager *wm = CTX_wm_manager(C);
- const bool draw_overlay = (scene->ed && (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW));
+ const bool draw_overlay = (scene->ed && (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) &&
+ (sseq->flag & SEQ_SHOW_STRIP_OVERLAY));
/* XXX temp fix for wrong setting in sseq->mainb */
if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index bb71a9b11be..0f5ac5abe1d 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -357,7 +357,7 @@ static bool text_drop_paste_poll(bContext *UNUSED(C),
static void text_drop_paste(wmDrag *drag, wmDropBox *drop)
{
char *text;
- ID *id = WM_drag_ID(drag, 0);
+ ID *id = WM_drag_get_local_ID(drag, 0);
/* copy drag path to properties */
text = RNA_path_full_ID_py(G_MAIN, id);
diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c
index c583634f440..84b7a6f6831 100644
--- a/source/blender/editors/space_text/text_header.c
+++ b/source/blender/editors/space_text/text_header.c
@@ -108,101 +108,3 @@ void TEXT_OT_start_find(wmOperatorType *ot)
ot->exec = text_text_search_exec;
ot->poll = text_properties_poll;
}
-
-/******************** XXX popup menus *******************/
-
-#if 0
-{
- /* RMB */
-
- uiPopupMenu *pup;
-
- if (text) {
- pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE);
- if (txt_has_sel(text)) {
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_cut");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_copy");
- }
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_paste");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save_as");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_run_script");
- UI_popup_menu_end(C, pup);
- }
- else {
- pup = UI_popup_menu_begin(C, IFACE_("File"), ICON_NONE);
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
- UI_popup_menu_end(C, pup);
- }
-}
-
-{
- /* Alt+Shift+E */
-
- uiPopupMenu *pup;
-
- pup = UI_popup_menu_begin(C, IFACE_("Edit"), ICON_NONE);
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_cut");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_copy");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_paste");
- UI_popup_menu_end(C, pup);
-}
-
-{
- /* Alt+Shift+F */
-
- uiPopupMenu *pup;
-
- if (text) {
- pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE);
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save_as");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_run_script");
- UI_popup_menu_end(C, pup);
- }
- else {
- pup = UI_popup_menu_begin(C, IFACE_("File"), ICON_NONE);
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
- UI_popup_menu_end(C, pup);
- }
-}
-
-{
- /* Alt+Shift+V */
-
- uiPopupMenu *pup;
-
- pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE);
- uiItemEnumO(layout,
- "TEXT_OT_move",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Top of File"),
- 0,
- "type",
- FILE_TOP);
- uiItemEnumO(layout,
- "TEXT_OT_move",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Bottom of File"),
- 0,
- "type",
- FILE_BOTTOM);
- uiItemEnumO(layout,
- "TEXT_OT_move",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Page Up"),
- 0,
- "type",
- PREV_PAGE);
- uiItemEnumO(layout,
- "TEXT_OT_move",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Page Down"),
- 0,
- "type",
- NEXT_PAGE);
- UI_popup_menu_end(C, pup);
-}
-#endif
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index f8b7c62686f..932bacfb8a0 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -2588,7 +2588,7 @@ static int text_scroll_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- txt_screen_skip(st, region, lines * U.wheellinescroll);
+ txt_screen_skip(st, region, lines * 3);
ED_area_tag_redraw(CTX_wm_area(C));
diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c
index d823530fd89..f05d6df9944 100644
--- a/source/blender/editors/space_userpref/userpref_ops.c
+++ b/source/blender/editors/space_userpref/userpref_ops.c
@@ -30,6 +30,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_preferences.h"
#include "BKE_report.h"
#include "RNA_access.h"
@@ -92,7 +93,7 @@ static int preferences_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED
static void PREFERENCES_OT_autoexec_path_add(wmOperatorType *ot)
{
- ot->name = "Add Autoexec Path";
+ ot->name = "Add Auto-Execution Path";
ot->idname = "PREFERENCES_OT_autoexec_path_add";
ot->description = "Add path to exclude from auto-execution";
@@ -120,7 +121,7 @@ static int preferences_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op)
static void PREFERENCES_OT_autoexec_path_remove(wmOperatorType *ot)
{
- ot->name = "Remove Autoexec Path";
+ ot->name = "Remove Auto-Execution Path";
ot->idname = "PREFERENCES_OT_autoexec_path_remove";
ot->description = "Remove path to exclude from auto-execution";
@@ -133,9 +134,71 @@ static void PREFERENCES_OT_autoexec_path_remove(wmOperatorType *ot)
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Add Asset Library Operator
+ * \{ */
+
+static int preferences_asset_library_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
+{
+ BKE_preferences_asset_library_add(&U, NULL, NULL);
+ U.runtime.is_dirty = true;
+ return OPERATOR_FINISHED;
+}
+
+static void PREFERENCES_OT_asset_library_add(wmOperatorType *ot)
+{
+ ot->name = "Add Asset Library";
+ ot->idname = "PREFERENCES_OT_asset_library_add";
+ ot->description =
+ "Add a path to a .blend file to be used by the Asset Browser as source of assets";
+
+ ot->exec = preferences_asset_library_add_exec;
+
+ ot->flag = OPTYPE_INTERNAL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Remove Asset Library Operator
+ * \{ */
+
+static int preferences_asset_library_remove_exec(bContext *UNUSED(C), wmOperator *op)
+{
+ const int index = RNA_int_get(op->ptr, "index");
+ bUserAssetLibrary *library = BLI_findlink(&U.asset_libraries, index);
+ if (library) {
+ BKE_preferences_asset_library_remove(&U, library);
+ U.runtime.is_dirty = true;
+ /* Trigger refresh for the Asset Browser. */
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, NULL);
+ }
+ return OPERATOR_FINISHED;
+}
+
+static void PREFERENCES_OT_asset_library_remove(wmOperatorType *ot)
+{
+ ot->name = "Remove Asset Library";
+ ot->idname = "PREFERENCES_OT_asset_library_remove";
+ ot->description =
+ "Remove a path to a .blend file, so the Asset Browser will not attempt to show it anymore";
+
+ ot->exec = preferences_asset_library_remove_exec;
+
+ ot->flag = OPTYPE_INTERNAL;
+
+ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
+}
+
+/** \} */
+
void ED_operatortypes_userpref(void)
{
WM_operatortype_append(PREFERENCES_OT_reset_default_theme);
+
WM_operatortype_append(PREFERENCES_OT_autoexec_path_add);
WM_operatortype_append(PREFERENCES_OT_autoexec_path_remove);
+
+ WM_operatortype_append(PREFERENCES_OT_asset_library_add);
+ WM_operatortype_append(PREFERENCES_OT_asset_library_remove);
}
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 0371b4e271f..9242fc15021 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -22,13 +22,13 @@ set(INC
../../blenlib
../../blentranslation
../../bmesh
+ ../../depsgraph
../../draw
../../gpu
../../imbuf
../../makesdna
../../makesrna
../../render
- ../../depsgraph
../../windowmanager
../../../../intern/glew-mx
../../../../intern/guardedalloc
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 9f31e7a411d..3761f4ad7c6 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -461,6 +461,12 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *region)
ED_view3d_stop_render_preview(wm, region);
}
+static bool view3d_drop_in_main_region_poll(bContext *C, const wmEvent *event)
+{
+ ScrArea *area = CTX_wm_area(C);
+ return ED_region_overlap_isect_any_xy(area, &event->x) == false;
+}
+
static ID *view3d_drop_id_in_main_region_poll_id(bContext *C,
wmDrag *drag,
const wmEvent *event,
@@ -470,7 +476,7 @@ static ID *view3d_drop_id_in_main_region_poll_id(bContext *C,
if (ED_region_overlap_isect_any_xy(area, &event->x)) {
return NULL;
}
- return WM_drag_ID(drag, id_type);
+ return view3d_drop_in_main_region_poll(C, event) ? WM_drag_get_local_ID(drag, id_type) : NULL;
}
static bool view3d_drop_id_in_main_region_poll(bContext *C,
@@ -478,7 +484,11 @@ static bool view3d_drop_id_in_main_region_poll(bContext *C,
const wmEvent *event,
ID_Type id_type)
{
- return (view3d_drop_id_in_main_region_poll_id(C, drag, event, id_type) != NULL);
+ if (!view3d_drop_in_main_region_poll(C, event)) {
+ return false;
+ }
+
+ return WM_drag_get_local_ID(drag, id_type) || WM_drag_get_asset_data(drag, id_type);
}
static bool view3d_ob_drop_poll(bContext *C,
@@ -533,7 +543,7 @@ static bool view3d_ima_drop_poll(bContext *C,
return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE));
}
- return WM_drag_ID(drag, ID_IM) != NULL;
+ return WM_drag_get_local_ID(drag, ID_IM) || WM_drag_get_asset_data(drag, ID_IM);
}
static bool view3d_ima_bg_is_camera_view(bContext *C)
@@ -596,14 +606,14 @@ static bool view3d_volume_drop_poll(bContext *UNUSED(C),
static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, ID_OB);
+ ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, ID_OB);
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, ID_GR);
+ ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, ID_GR);
drop->opcontext = WM_OP_EXEC_DEFAULT;
RNA_string_set(drop->ptr, "name", id->name + 2);
@@ -611,14 +621,14 @@ static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, 0);
+ ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0);
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_id_drop_copy_with_type(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, 0);
+ ID *id = WM_drag_get_local_ID(drag, 0);
RNA_string_set(drop->ptr, "name", id->name + 2);
RNA_enum_set(drop->ptr, "type", GS(id->name));
@@ -626,7 +636,7 @@ static void view3d_id_drop_copy_with_type(wmDrag *drag, wmDropBox *drop)
static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, 0);
+ ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0);
if (id) {
RNA_string_set(drop->ptr, "name", id->name + 2);
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 9429da342a6..ebfa4f6d9af 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -4708,7 +4708,7 @@ static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op))
void VIEW3D_OT_view_persportho(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Persp/Ortho";
+ ot->name = "View Perspective/Orthographic";
ot->description = "Switch the current view from perspective/orthographic projection";
ot->idname = "VIEW3D_OT_view_persportho";
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index fdba74ed3a6..9b0ce27b1e3 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -315,8 +315,6 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
const float eps_bias = 0.0002f;
float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */
- WM_gizmo_set_flag(snap_gizmo, WM_GIZMO_HIDDEN, true);
-
if (ruler_item) {
RulerInteraction *inter = ruler_item->gz.interaction_data;
float *co = ruler_item->co[inter->co_index];
@@ -388,12 +386,8 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
snap_gizmo->ptr, ruler_info->snap_data.prop_prevpoint, prev_point);
}
- short snap_elem = ED_gizmotypes_snap_3d_update(
+ ED_gizmotypes_snap_3d_update(
snap_gizmo, depsgraph, ruler_info->region, v3d, ruler_info->wm, mval_fl, co, NULL);
-
- if (snap_elem) {
- WM_gizmo_set_flag(snap_gizmo, WM_GIZMO_HIDDEN, false);
- }
}
return true;
}
@@ -1074,7 +1068,6 @@ static void gizmo_ruler_exit(bContext *C, wmGizmo *gz, const bool cancel)
if (!cancel) {
if (ruler_info->state == RULER_STATE_DRAG) {
- WM_gizmo_set_flag(ruler_info->snap_data.gizmo, WM_GIZMO_HIDDEN, false);
RNA_property_unset(ruler_info->snap_data.gizmo->ptr, ruler_info->snap_data.prop_prevpoint);
ruler_state_set(ruler_info, RULER_STATE_NORMAL);
}
diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c
index 6d10aa5f957..bd71a768c0f 100644
--- a/source/blender/editors/space_view3d/view3d_placement.c
+++ b/source/blender/editors/space_view3d/view3d_placement.c
@@ -72,7 +72,7 @@ static void preview_plane_cursor_visible_set(wmGizmoGroup *gzgroup, bool do_draw
* In this case we can't usefully project the mouse cursor onto the plane,
* so use a fall-back plane instead.
*/
-const float eps_view_align = 1e-2f;
+static const float eps_view_align = 1e-2f;
/* -------------------------------------------------------------------- */
/** \name Local Types
@@ -1357,7 +1357,6 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve
const float mval_fl[2] = {UNPACK2(event->mval)};
/* Calculate the snap location on mouse-move or when toggling snap. */
- bool is_snap_found_prev = ipd->is_snap_found;
ipd->is_snap_found = false;
if (ipd->use_snap) {
if (ipd->snap_gizmo != NULL) {
@@ -1366,7 +1365,7 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve
CTX_data_ensure_evaluated_depsgraph(C),
ipd->region,
ipd->v3d,
- NULL,
+ G_MAIN->wm.first,
mval_fl,
ipd->snap_co,
NULL)) {
@@ -1376,12 +1375,6 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve
}
}
- /* Workaround because test_select doesn't run at the same time as the modal operator. */
- if (is_snap_found_prev != ipd->is_snap_found) {
- wmGizmoMap *gzmap = ipd->region->gizmo_map;
- WM_gizmo_highlight_set(gzmap, ipd->is_snap_found ? ipd->snap_gizmo : NULL);
- }
-
if (ipd->step_index == STEP_BASE) {
if (ipd->is_snap_found) {
closest_to_plane_normalized_v3(
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 5b400bbf60a..96bd25f85e7 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -2457,13 +2457,16 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
else if (obact && BKE_paint_select_face_test(obact)) {
retval = paintface_mouse_select(C, obact, location, extend, deselect, toggle);
if (!retval && deselect_all) {
- retval = paintface_deselect_all_visible(C, CTX_data_active_object(C), SEL_DESELECT, false);
+ retval = paintface_deselect_all_visible(C, CTX_data_active_object(C), SEL_DESELECT, true);
}
}
else if (BKE_paint_select_vert_test(obact)) {
retval = ed_wpaint_vertex_select_pick(C, location, extend, deselect, toggle, obact);
if (!retval && deselect_all) {
retval = paintvert_deselect_all_visible(obact, SEL_DESELECT, false);
+ if (retval) {
+ paintvert_tag_select_update(C, obact);
+ }
}
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 1be9bd27c7a..2b7b8255068 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -1620,6 +1620,41 @@ void ED_view3d_to_object(const Depsgraph *depsgraph,
BKE_object_apply_mat4_ex(ob, mat, ob_eval->parent, ob_eval->parentinv, true);
}
+bool ED_view3d_camera_to_view_selected(struct Main *bmain,
+ Depsgraph *depsgraph,
+ const Scene *scene,
+ Object *camera_ob)
+{
+ Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob);
+ float co[3]; /* the new location to apply */
+ float scale; /* only for ortho cameras */
+
+ if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, camera_ob_eval, co, &scale)) {
+ ObjectTfmProtectedChannels obtfm;
+ float obmat_new[4][4];
+
+ if ((camera_ob_eval->type == OB_CAMERA) &&
+ (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) {
+ ((Camera *)camera_ob->data)->ortho_scale = scale;
+ }
+
+ copy_m4_m4(obmat_new, camera_ob_eval->obmat);
+ copy_v3_v3(obmat_new[3], co);
+
+ /* only touch location */
+ BKE_object_tfm_protected_backup(camera_ob, &obtfm);
+ BKE_object_apply_mat4(camera_ob, obmat_new, true, true);
+ BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D);
+
+ /* notifiers */
+ DEG_id_tag_update_ex(bmain, &camera_ob->id, ID_RECALC_TRANSFORM);
+
+ return true;
+ }
+
+ return false;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index a24f59019f0..9d947384bf0 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -535,40 +535,18 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot)
* meant to take into account vertex/bone selection for eg. */
static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
Object *camera_ob = v3d ? v3d->camera : scene->camera;
- Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob);
-
- float r_co[3]; /* the new location to apply */
- float r_scale; /* only for ortho cameras */
- if (camera_ob_eval == NULL) {
+ if (camera_ob == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active camera");
return OPERATOR_CANCELLED;
}
- /* this function does all the important stuff */
- if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, camera_ob_eval, r_co, &r_scale)) {
- ObjectTfmProtectedChannels obtfm;
- float obmat_new[4][4];
-
- if ((camera_ob_eval->type == OB_CAMERA) &&
- (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) {
- ((Camera *)camera_ob->data)->ortho_scale = r_scale;
- }
-
- copy_m4_m4(obmat_new, camera_ob_eval->obmat);
- copy_v3_v3(obmat_new[3], r_co);
-
- /* only touch location */
- BKE_object_tfm_protected_backup(camera_ob, &obtfm);
- BKE_object_apply_mat4(camera_ob, obmat_new, true, true);
- BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D);
-
- /* notifiers */
- DEG_id_tag_update(&camera_ob->id, ID_RECALC_TRANSFORM);
+ if (ED_view3d_camera_to_view_selected(bmain, depsgraph, scene, camera_ob)) {
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, camera_ob);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index 73d6a376da6..a2eb68a1b71 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -22,12 +22,12 @@ set(INC
../../blenlib
../../blentranslation
../../bmesh
+ ../../depsgraph
../../gpu
../../ikplugin
../../makesdna
../../makesrna
../../render
- ../../depsgraph
../../sequencer
../../windowmanager
../../../../intern/glew-mx
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 5969de5b5da..2b56b30be90 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -637,6 +637,14 @@ static bool transform_modal_item_poll(const wmOperator *op, int value)
}
break;
}
+ case TFM_MODAL_TRANSLATE:
+ case TFM_MODAL_ROTATE:
+ case TFM_MODAL_RESIZE: {
+ if (!transform_mode_is_changeable(t->mode)) {
+ return false;
+ }
+ break;
+ }
}
return true;
}
@@ -876,11 +884,6 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
}
- else if (t->mode == TFM_SEQ_SLIDE) {
- t->flag ^= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
else if (transform_mode_is_changeable(t->mode)) {
restoreTransObjects(t);
resetTransModal(t);
@@ -922,11 +925,6 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
}
- else if (t->mode == TFM_SHRINKFATTEN) {
- t->flag ^= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
else if (transform_mode_is_changeable(t->mode)) {
/* Scale isn't normally very useful after extrude along normals, see T39756 */
if ((t->con.mode & CON_APPLY) && (t->orient[t->orient_curr].type == V3D_ORIENT_NORMAL)) {
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 227330e8524..91bf2bf8aac 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -52,12 +52,12 @@ struct SnapObjectContext;
struct TransDataContainer;
struct TransInfo;
struct TransSnap;
-struct TransformOrientation;
struct ViewLayer;
struct bContext;
struct wmEvent;
struct wmKeyConfig;
struct wmKeyMap;
+struct wmOperator;
struct wmTimer;
/** #TransInfo.redraw */
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index c23ee5b771c..c81c954bd0a 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -1438,7 +1438,7 @@ void animrecord_check_state(TransInfo *t, struct Object *ob)
/* only push down if action is more than 1-2 frames long */
calc_action_range(adt->action, &astart, &aend, 1);
if (aend > astart + 2.0f) {
- NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action);
+ NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action, ID_IS_OVERRIDE_LIBRARY(id));
/* clear reference to action now that we've pushed it onto the stack */
id_us_min(&adt->action->id);
diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h
index b753572ea7b..59fcd016020 100644
--- a/source/blender/editors/transform/transform_convert.h
+++ b/source/blender/editors/transform/transform_convert.h
@@ -29,12 +29,9 @@ struct FCurve;
struct ListBase;
struct Object;
struct TransData;
-struct TransDataContainer;
struct TransDataCurveHandleFlags;
struct TransInfo;
struct bContext;
-struct bKinematicConstraint;
-struct bPoseChannel;
/* transform_convert.c */
void transform_autoik_update(TransInfo *t, short mode);
diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c
index a7301161570..e9b2273b343 100644
--- a/source/blender/editors/transform/transform_convert_armature.c
+++ b/source/blender/editors/transform/transform_convert_armature.c
@@ -164,21 +164,21 @@ static void autokeyframe_pose(
/* only if bone name matches too...
* NOTE: this will do constraints too, but those are ok to do here too?
*/
- if (pchanName && STREQ(pchanName, pchan->name)) {
- insert_keyframe(bmain,
- reports,
- id,
- act,
- ((fcu->grp) ? (fcu->grp->name) : (NULL)),
- fcu->rna_path,
- fcu->array_index,
- &anim_eval_context,
- ts->keyframe_type,
- &nla_cache,
- flag);
- }
-
if (pchanName) {
+ if (STREQ(pchanName, pchan->name)) {
+ insert_keyframe(bmain,
+ reports,
+ id,
+ act,
+ ((fcu->grp) ? (fcu->grp->name) : (NULL)),
+ fcu->rna_path,
+ fcu->array_index,
+ &anim_eval_context,
+ ts->keyframe_type,
+ &nla_cache,
+ flag);
+ }
+
MEM_freeN(pchanName);
}
}
diff --git a/source/blender/editors/transform/transform_convert_nla.c b/source/blender/editors/transform/transform_convert_nla.c
index 8f18f6a8c96..fa60a88a45b 100644
--- a/source/blender/editors/transform/transform_convert_nla.c
+++ b/source/blender/editors/transform/transform_convert_nla.c
@@ -462,6 +462,12 @@ void recalcData_nla(TransInfo *t)
* - we need to calculate both,
* as only one may have been altered by transform if only 1 handle moved.
*/
+ /* In LibOverride case, we cannot move strips across tracks that come from the linked data. */
+ const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(tdn->id);
+ if (BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, tdn->nlt)) {
+ continue;
+ }
+
delta_y1 = ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
delta_y2 = ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
@@ -477,10 +483,11 @@ void recalcData_nla(TransInfo *t)
if (delta > 0) {
for (track = tdn->nlt->next, n = 0; (track) && (n < delta); track = track->next, n++) {
/* check if space in this track for the strip */
- if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
+ if (BKE_nlatrack_has_space(track, strip->start, strip->end) &&
+ !BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, tdn->nlt)) {
/* move strip to this track */
BLI_remlink(&tdn->nlt->strips, strip);
- BKE_nlatrack_add_strip(track, strip);
+ BKE_nlatrack_add_strip(track, strip, is_liboverride);
tdn->nlt = track;
tdn->trackIndex++;
@@ -496,10 +503,11 @@ void recalcData_nla(TransInfo *t)
for (track = tdn->nlt->prev, n = 0; (track) && (n < delta); track = track->prev, n++) {
/* check if space in this track for the strip */
- if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
+ if (BKE_nlatrack_has_space(track, strip->start, strip->end) &&
+ !BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, tdn->nlt)) {
/* move strip to this track */
BLI_remlink(&tdn->nlt->strips, strip);
- BKE_nlatrack_add_strip(track, strip);
+ BKE_nlatrack_add_strip(track, strip, is_liboverride);
tdn->nlt = track;
tdn->trackIndex--;
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 3f86ef3e81b..ebb0b6823a3 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -32,7 +32,11 @@
#include "ED_markers.h"
+#include "SEQ_relations.h"
#include "SEQ_sequencer.h"
+#include "SEQ_time.h"
+#include "SEQ_transform.h"
+#include "SEQ_utils.h"
#include "UI_view2d.h"
@@ -84,8 +88,8 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_recursive, int *r_c
Scene *scene = t->scene;
int cfra = CFRA;
- int left = BKE_sequence_tx_get_final_left(seq, true);
- int right = BKE_sequence_tx_get_final_right(seq, true);
+ int left = SEQ_transform_get_left_handle_frame(seq, true);
+ int right = SEQ_transform_get_right_handle_frame(seq, true);
if (seq->depth == 0 && ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK))) {
*r_recursive = false;
@@ -186,7 +190,7 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_recursive, int *r_c
/* Meta's can only directly be moved between channels since they
* don't have their start and length set directly (children affect that)
* since this Meta is nested we don't need any of its data in fact.
- * BKE_sequence_calc() will update its settings when run on the top-level meta. */
+ * SEQ_time_update_sequence() will update its settings when run on the top-level meta. */
*r_flag = 0;
*r_count = 0;
*r_recursive = true;
@@ -235,16 +239,16 @@ static TransData *SeqToTransData(
/* Use seq_tx_get_final_left() and an offset here
* so transform has the left hand location of the strip.
* tdsq->start_offset is used when flushing the tx data back */
- start_left = BKE_sequence_tx_get_final_left(seq, false);
+ start_left = SEQ_transform_get_left_handle_frame(seq, false);
td2d->loc[0] = start_left;
tdsq->start_offset = start_left - seq->start; /* use to apply the original location */
break;
case SEQ_LEFTSEL:
- start_left = BKE_sequence_tx_get_final_left(seq, false);
+ start_left = SEQ_transform_get_left_handle_frame(seq, false);
td2d->loc[0] = start_left;
break;
case SEQ_RIGHTSEL:
- td2d->loc[0] = BKE_sequence_tx_get_final_right(seq, false);
+ td2d->loc[0] = SEQ_transform_get_right_handle_frame(seq, false);
break;
}
@@ -366,7 +370,7 @@ static void SeqTransDataBounds(TransInfo *t, ListBase *seqbase, TransSeq *ts)
static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
{
- Editing *ed = BKE_sequencer_editing_get(t->scene, false);
+ Editing *ed = SEQ_editing_get(t->scene, false);
if (ed != NULL) {
@@ -388,7 +392,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
for (a = 0; a < t->total; a++, td++) {
if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
seq = ((TransDataSeq *)td->extra)->seq;
- BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
+ SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene);
}
seq_prev = seq;
@@ -429,7 +433,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
}
else {
/* Tag seq with a non zero value, used by
- * BKE_sequence_base_shuffle_time to identify the ones to shuffle */
+ * SEQ_transform_seqbase_shuffle_time to identify the ones to shuffle */
if (seq->depth == 0) {
seq->tmp = (void *)1;
}
@@ -455,7 +459,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
}
}
- BKE_sequence_base_shuffle_time(seqbasep, t->scene, markers, use_sync_markers);
+ SEQ_transform_seqbase_shuffle_time(seqbasep, t->scene, markers, use_sync_markers);
for (seq = seqbasep->first; seq; seq = seq->next) {
if (seq->machine >= MAXSEQ * 2) {
@@ -467,10 +471,10 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
}
}
- BKE_sequence_base_shuffle_time(seqbasep, t->scene, markers, use_sync_markers);
+ SEQ_transform_seqbase_shuffle_time(seqbasep, t->scene, markers, use_sync_markers);
}
else {
- BKE_sequence_base_shuffle_time(seqbasep, t->scene, markers, use_sync_markers);
+ SEQ_transform_seqbase_shuffle_time(seqbasep, t->scene, markers, use_sync_markers);
}
if (has_effect_any) {
@@ -480,7 +484,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
seq = ((TransDataSeq *)td->extra)->seq;
if ((seq != seq_prev)) {
if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
- BKE_sequence_calc(t->scene, seq);
+ SEQ_time_update_sequence(t->scene, seq);
}
}
}
@@ -493,8 +497,8 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
seq = ((TransDataSeq *)td->extra)->seq;
if ((seq != seq_prev) && (seq->depth == 0)) {
if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
- if (BKE_sequence_test_overlap(seqbasep, seq)) {
- BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
+ if (SEQ_transform_test_overlap(seqbasep, seq)) {
+ SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene);
}
}
}
@@ -509,18 +513,18 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
/* We might want to build a list of effects that need to be updated during transform */
if (seq->type & SEQ_TYPE_EFFECT) {
if (seq->seq1 && seq->seq1->flag & SELECT) {
- BKE_sequence_calc(t->scene, seq);
+ SEQ_time_update_sequence(t->scene, seq);
}
else if (seq->seq2 && seq->seq2->flag & SELECT) {
- BKE_sequence_calc(t->scene, seq);
+ SEQ_time_update_sequence(t->scene, seq);
}
else if (seq->seq3 && seq->seq3->flag & SELECT) {
- BKE_sequence_calc(t->scene, seq);
+ SEQ_time_update_sequence(t->scene, seq);
}
}
}
- BKE_sequencer_sort(t->scene);
+ SEQ_sort(t->scene);
}
else {
/* Canceled, need to update the strips display */
@@ -528,10 +532,10 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
seq = ((TransDataSeq *)td->extra)->seq;
if ((seq != seq_prev) && (seq->depth == 0)) {
if (seq->flag & SEQ_OVERLAP) {
- BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
+ SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene);
}
- BKE_sequence_calc_disp(t->scene, seq);
+ SEQ_time_update_sequence_bounds(t->scene, seq);
}
seq_prev = seq;
}
@@ -553,7 +557,7 @@ void createTransSeqData(TransInfo *t)
#define XXX_DURIAN_ANIM_TX_HACK
Scene *scene = t->scene;
- Editing *ed = BKE_sequencer_editing_get(t->scene, false);
+ Editing *ed = SEQ_editing_get(t->scene, false);
TransData *td = NULL;
TransData2D *td2d = NULL;
TransDataSeq *tdsq = NULL;
@@ -640,21 +644,21 @@ BLI_INLINE void trans_update_seq(Scene *sce, Sequence *seq, int old_start, int s
/* Calculate this strip and all nested strips.
* Children are ALWAYS transformed first so we don't need to do this in another loop.
*/
- BKE_sequence_calc(sce, seq);
+ SEQ_time_update_sequence(sce, seq);
}
else {
- BKE_sequence_calc_disp(sce, seq);
+ SEQ_time_update_sequence_bounds(sce, seq);
}
if (sel_flag == SELECT) {
- BKE_sequencer_offset_animdata(sce, seq, seq->start - old_start);
+ SEQ_offset_animdata(sce, seq, seq->start - old_start);
}
}
static void flushTransSeq(TransInfo *t)
{
/* Editing null check already done */
- ListBase *seqbasep = BKE_sequencer_editing_get(t->scene, false)->seqbasep;
+ ListBase *seqbasep = SEQ_editing_get(t->scene, false)->seqbasep;
int a, new_frame;
TransData *td = NULL;
@@ -681,7 +685,7 @@ static void flushTransSeq(TransInfo *t)
switch (tdsq->sel_flag) {
case SELECT:
#ifdef SEQ_TX_NESTED_METAS
- if ((seq->depth != 0 || BKE_sequence_tx_test(seq))) {
+ if ((seq->depth != 0 || SEQ_transform_sequence_can_be_translated(seq))) {
/* for meta's, their children move */
seq->start = new_frame - tdsq->start_offset;
}
@@ -697,18 +701,18 @@ static void flushTransSeq(TransInfo *t)
}
break;
case SEQ_LEFTSEL: /* no vertical transform */
- BKE_sequence_tx_set_final_left(seq, new_frame);
- BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
+ SEQ_transform_set_left_handle_frame(seq, new_frame);
+ SEQ_transform_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
/* todo - move this into aftertrans update? - old seq tx needed it anyway */
- BKE_sequence_single_fix(seq);
+ SEQ_transform_fix_single_image_seq_offsets(seq);
break;
case SEQ_RIGHTSEL: /* no vertical transform */
- BKE_sequence_tx_set_final_right(seq, new_frame);
- BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
+ SEQ_transform_set_right_handle_frame(seq, new_frame);
+ SEQ_transform_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
/* todo - move this into aftertrans update? - old seq tx needed it anyway */
- BKE_sequence_single_fix(seq);
+ SEQ_transform_fix_single_image_seq_offsets(seq);
break;
}
@@ -743,12 +747,12 @@ static void flushTransSeq(TransInfo *t)
/* calc all meta's then effects T27953. */
for (seq = seqbasep->first; seq; seq = seq->next) {
if (seq->type == SEQ_TYPE_META && seq->flag & SELECT) {
- BKE_sequence_calc(t->scene, seq);
+ SEQ_time_update_sequence(t->scene, seq);
}
}
for (seq = seqbasep->first; seq; seq = seq->next) {
if (seq->seq1 || seq->seq2 || seq->seq3) {
- BKE_sequence_calc(t->scene, seq);
+ SEQ_time_update_sequence(t->scene, seq);
}
}
@@ -759,7 +763,7 @@ static void flushTransSeq(TransInfo *t)
seq = tdsq->seq;
if ((seq != seq_prev) && (seq->depth != 0)) {
if (seq->seq1 || seq->seq2 || seq->seq3) {
- BKE_sequence_calc(t->scene, seq);
+ SEQ_time_update_sequence(t->scene, seq);
}
}
}
@@ -777,7 +781,7 @@ static void flushTransSeq(TransInfo *t)
if (seq->depth == 0) {
/* test overlap, displays red outline */
seq->flag &= ~SEQ_OVERLAP;
- if (BKE_sequence_test_overlap(seqbasep, seq)) {
+ if (SEQ_transform_test_overlap(seqbasep, seq)) {
seq->flag |= SEQ_OVERLAP;
}
}
@@ -800,7 +804,7 @@ void recalcData_sequencer(TransInfo *t)
Sequence *seq = tdsq->seq;
if (seq != seq_prev) {
- BKE_sequence_invalidate_cache_composite(t->scene, seq);
+ SEQ_relations_invalidate_cache_composite(t->scene, seq);
}
seq_prev = seq;
diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c
index dfa5c164acf..7ccfd0149bd 100644
--- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c
+++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c
@@ -32,6 +32,7 @@
#include "ED_screen.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "UI_interface.h"
@@ -45,6 +46,18 @@
/** \name Transform (Sequencer Slide)
* \{ */
+static eRedrawFlag seq_slide_handleEvent(struct TransInfo *t, const wmEvent *event)
+{
+ BLI_assert(t->mode == TFM_SEQ_SLIDE);
+ wmKeyMapItem *kmi = t->custom.mode.data;
+ if (kmi && event->type == kmi->type && event->val == kmi->val) {
+ /* Allows the 'Expand to fit' effect to be enabled as a toogle. */
+ t->flag ^= T_ALT_TRANSFORM;
+ return TREDRAW_HARD;
+ }
+ return TREDRAW_NOTHING;
+}
+
static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRAW_STR])
{
char tvec[NUM_STR_REP_LEN * 3];
@@ -60,12 +73,11 @@ static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRA
ofs += BLI_snprintf(
str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text);
- if (t->keymap) {
- wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE);
- if (kmi) {
- ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs);
- }
+ wmKeyMapItem *kmi = t->custom.mode.data;
+ if (kmi) {
+ ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs);
}
+
ofs += BLI_snprintf(str + ofs,
UI_MAX_DRAW_STR - ofs,
TIP_(" or Alt) Expand to fit %s"),
@@ -91,7 +103,7 @@ static void applySeqSlideValue(TransInfo *t, const float val[2])
static void applySeqSlide(TransInfo *t, const int mval[2])
{
char str[UI_MAX_DRAW_STR];
- float values_final[2] = {0.0f};
+ float values_final[3] = {0.0f};
snapSequenceBounds(t, mval);
if (applyNumInput(&t->num, values_final)) {
@@ -126,6 +138,7 @@ static void applySeqSlide(TransInfo *t, const int mval[2])
void initSeqSlide(TransInfo *t)
{
t->transform = applySeqSlide;
+ t->handleEvent = seq_slide_handleEvent;
initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
@@ -142,5 +155,10 @@ void initSeqSlide(TransInfo *t)
* (supporting frames in addition to "natural" time...). */
t->num.unit_type[0] = B_UNIT_NONE;
t->num.unit_type[1] = B_UNIT_NONE;
+
+ if (t->keymap) {
+ /* Workaround to use the same key as the modal keymap. */
+ t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE);
+ }
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c
index cdea388529f..2a5c631df41 100644
--- a/source/blender/editors/transform/transform_mode_shrink_fatten.c
+++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c
@@ -32,6 +32,7 @@
#include "ED_screen.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "UI_interface.h"
@@ -45,6 +46,18 @@
/** \name Transform (Shrink-Fatten)
* \{ */
+static eRedrawFlag shrinkfatten_handleEvent(struct TransInfo *t, const wmEvent *event)
+{
+ BLI_assert(t->mode == TFM_SHRINKFATTEN);
+ wmKeyMapItem *kmi = t->custom.mode.data;
+ if (kmi && event->type == kmi->type && event->val == kmi->val) {
+ /* Allows the 'Even Thickness' effect to be enabled as a toogle. */
+ t->flag ^= T_ALT_TRANSFORM;
+ return TREDRAW_HARD;
+ }
+ return TREDRAW_NOTHING;
+}
+
static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
{
float distance;
@@ -77,12 +90,11 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
}
ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs);
- if (t->keymap) {
- wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE);
- if (kmi) {
- ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs);
- }
+ wmKeyMapItem *kmi = t->custom.mode.data;
+ if (kmi) {
+ ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs);
}
+
BLI_snprintf(str + ofs,
sizeof(str) - ofs,
TIP_(" or Alt) Even Thickness %s"),
@@ -121,6 +133,7 @@ void initShrinkFatten(TransInfo *t)
else {
t->mode = TFM_SHRINKFATTEN;
t->transform = applyShrinkFatten;
+ t->handleEvent = shrinkfatten_handleEvent;
initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
@@ -134,6 +147,11 @@ void initShrinkFatten(TransInfo *t)
t->num.unit_type[0] = B_UNIT_LENGTH;
t->flag |= T_NO_CONSTRAINT;
+
+ if (t->keymap) {
+ /* Workaround to use the same key as the modal keymap. */
+ t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE);
+ }
}
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c
index 90c1f241338..8597c372537 100644
--- a/source/blender/editors/transform/transform_mode_translate.c
+++ b/source/blender/editors/transform/transform_mode_translate.c
@@ -377,6 +377,9 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
else {
mul_v3_m3v3(global_dir, t->spacemtx, global_dir);
}
+ if (t->flag & T_2D_EDIT) {
+ removeAspectRatio(t, global_dir);
+ }
}
else {
copy_v3_v3(global_dir, t->values);
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 5153fdedcae..5d758a6c6c6 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -717,7 +717,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
"use_automerge_and_split",
0,
"Auto Merge & Split",
- "Forces the use of Auto Merge & Split");
+ "Forces the use of Auto Merge and Split");
RNA_def_property_flag(prop, PROP_HIDDEN);
}
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index f1c4c243780..d407cea0033 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -42,6 +42,7 @@
#include "RNA_access.h"
#include "SEQ_sequencer.h"
+#include "SEQ_time.h"
#include "WM_types.h"
@@ -1409,7 +1410,7 @@ void snapSequenceBounds(TransInfo *t, const int mval[2])
const int frame_curr = round_fl_to_int(xmouse);
/* Now find the closest sequence. */
- const int frame_near = BKE_sequencer_find_next_prev_edit(
+ const int frame_near = SEQ_time_find_next_prev_edit(
t->scene, frame_curr, SEQ_SIDE_BOTH, true, false, true);
const int frame_snap = transform_convert_sequencer_get_snap_bound(t);
diff --git a/source/blender/editors/transform/transform_snap.h b/source/blender/editors/transform/transform_snap.h
index 5bee572c603..db8ec943bfd 100644
--- a/source/blender/editors/transform/transform_snap.h
+++ b/source/blender/editors/transform/transform_snap.h
@@ -25,8 +25,6 @@
/* For enum. */
#include "DNA_space_types.h"
-struct SnapObjectParams;
-
bool peelObjectsTransform(struct TransInfo *t,
const float mval[2],
const bool use_peel_object,
diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c
index 49417a54472..4fded419b5b 100644
--- a/source/blender/editors/undo/memfile_undo.c
+++ b/source/blender/editors/undo/memfile_undo.c
@@ -27,6 +27,7 @@
#include "BLI_listbase.h"
#include "DNA_ID.h"
+#include "DNA_collection_types.h"
#include "DNA_node_types.h"
#include "DNA_object_enums.h"
#include "DNA_object_types.h"
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index c88169778f7..0aab3810254 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -39,6 +39,7 @@ set(SRC
ed_transverts.c
ed_util.c
ed_util_imbuf.c
+ ed_util_ops.c
gizmo_utils.c
numinput.c
select_utils.c
@@ -47,6 +48,7 @@ set(SRC
../include/BIF_glutil.h
../include/ED_anim_api.h
../include/ED_armature.h
+ ../include/ED_asset.h
../include/ED_buttons.h
../include/ED_clip.h
../include/ED_curve.h
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 76c261c9cba..5d2584c566d 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -35,6 +35,7 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
+#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
@@ -44,6 +45,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_icons.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -51,6 +53,7 @@
#include "BKE_object.h"
#include "BKE_packedFile.h"
#include "BKE_paint.h"
+#include "BKE_report.h"
#include "BKE_screen.h"
#include "BKE_undo_system.h"
#include "BKE_workspace.h"
@@ -64,6 +67,7 @@
#include "ED_object.h"
#include "ED_outliner.h"
#include "ED_paint.h"
+#include "ED_render.h"
#include "ED_space_api.h"
#include "ED_util.h"
@@ -481,22 +485,102 @@ void ED_spacedata_id_remap(struct ScrArea *area, struct SpaceLink *sl, ID *old_i
}
}
-static int ed_flush_edits_exec(bContext *C, wmOperator *UNUSED(op))
+static bool lib_id_preview_editing_poll(bContext *C)
{
- Main *bmain = CTX_data_main(C);
- ED_editors_flush_edits(bmain);
+ const PointerRNA idptr = CTX_data_pointer_get(C, "id");
+ BLI_assert(!idptr.data || RNA_struct_is_ID(idptr.type));
+
+ const ID *id = idptr.data;
+ if (!id) {
+ return false;
+ }
+ if (ID_IS_LINKED(id)) {
+ CTX_wm_operator_poll_msg_set(C, TIP_("Can't edit external library data"));
+ return false;
+ }
+ if (ID_IS_OVERRIDE_LIBRARY(id)) {
+ CTX_wm_operator_poll_msg_set(C, TIP_("Can't edit previews of overridden library data"));
+ return false;
+ }
+ if (!BKE_previewimg_id_get_p(id)) {
+ CTX_wm_operator_poll_msg_set(C, TIP_("Data-block does not support previews"));
+ return false;
+ }
+
+ return true;
+}
+
+static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op)
+{
+ char path[FILE_MAX];
+
+ RNA_string_get(op->ptr, "filepath", path);
+
+ if (!BLI_is_file(path)) {
+ BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", path);
+ return OPERATOR_CANCELLED;
+ }
+
+ PointerRNA idptr = CTX_data_pointer_get(C, "id");
+ ID *id = idptr.data;
+
+ BKE_previewimg_id_custom_set(id, path);
+
+ WM_event_add_notifier(C, NC_ASSET, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ED_OT_lib_id_load_custom_preview(wmOperatorType *ot)
+{
+ ot->name = "Load Custom Preview";
+ ot->description = "Choose an image to help identify the data-block visually";
+ ot->idname = "ED_OT_lib_id_load_custom_preview";
+
+ /* api callbacks */
+ ot->poll = lib_id_preview_editing_poll;
+ ot->exec = lib_id_load_custom_preview_exec;
+ ot->invoke = WM_operator_filesel;
+
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_IMAGE,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_DEFAULT);
+}
+
+static int lib_id_generate_preview_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PointerRNA idptr = CTX_data_pointer_get(C, "id");
+ ID *id = idptr.data;
+
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+
+ PreviewImage *preview = BKE_previewimg_id_get(id);
+ if (preview) {
+ BKE_previewimg_clear(preview);
+ }
+ UI_icon_render_id(C, NULL, id, true, true);
+
+ WM_event_add_notifier(C, NC_ASSET, NULL);
+
return OPERATOR_FINISHED;
}
-void ED_OT_flush_edits(wmOperatorType *ot)
+void ED_OT_lib_id_generate_preview(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Flush Edits";
- ot->description = "Flush edit data from active editing modes";
- ot->idname = "ED_OT_flush_edits";
+ ot->name = "Generate Preview";
+ ot->description = "Create an automatic preview for the selected data-block";
+ ot->idname = "ED_OT_lib_id_generate_preview";
/* api callbacks */
- ot->exec = ed_flush_edits_exec;
+ ot->poll = lib_id_preview_editing_poll;
+ ot->exec = lib_id_generate_preview_exec;
/* flags */
ot->flag = OPTYPE_INTERNAL;
diff --git a/source/blender/editors/util/ed_util_imbuf.c b/source/blender/editors/util/ed_util_imbuf.c
index b832d9a1d86..0f2e280251f 100644
--- a/source/blender/editors/util/ed_util_imbuf.c
+++ b/source/blender/editors/util/ed_util_imbuf.c
@@ -42,6 +42,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "SEQ_render.h"
#include "SEQ_sequencer.h"
#include "UI_view2d.h"
@@ -564,7 +565,7 @@ bool ED_imbuf_sample_poll(bContext *C)
return false;
}
- return sseq && BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL;
+ return sseq && SEQ_editing_get(CTX_data_scene(C), false) != NULL;
}
return false;
diff --git a/source/blender/editors/util/ed_util_ops.c b/source/blender/editors/util/ed_util_ops.c
new file mode 100644
index 00000000000..d8d1a64c1ee
--- /dev/null
+++ b/source/blender/editors/util/ed_util_ops.c
@@ -0,0 +1,155 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edutil
+ *
+ * Utility operators for UI data or for the UI to use.
+ */
+
+#include <string.h>
+
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_lib_id.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+
+#include "DNA_windowmanager_types.h"
+
+#include "ED_util.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+static int lib_fake_user_toggle_exec(bContext *C, wmOperator *op)
+{
+ PropertyPointerRNA pprop;
+ PointerRNA idptr = PointerRNA_NULL;
+
+ UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop);
+
+ if (pprop.prop) {
+ idptr = RNA_property_pointer_get(&pprop.ptr, pprop.prop);
+ }
+
+ if ((pprop.prop == NULL) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Incorrect context for running data-block fake user toggling");
+ return OPERATOR_CANCELLED;
+ }
+
+ ID *id = idptr.data;
+
+ if ((id->lib != NULL) || (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
+ BKE_report(op->reports, RPT_ERROR, "Data-block type does not support fake user");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (ID_FAKE_USERS(id)) {
+ id_fake_user_clear(id);
+ }
+ else {
+ id_fake_user_set(id);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void ED_OT_lib_fake_user_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Toggle Fake User";
+ ot->description = "Save this data-block even if it has no users";
+ ot->idname = "ED_OT_lib_fake_user_toggle";
+
+ /* api callbacks */
+ ot->exec = lib_fake_user_toggle_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+static int lib_unlink_exec(bContext *C, wmOperator *op)
+{
+ PropertyPointerRNA pprop;
+ PointerRNA idptr;
+
+ UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop);
+
+ if (pprop.prop) {
+ idptr = RNA_property_pointer_get(&pprop.ptr, pprop.prop);
+ }
+
+ if ((pprop.prop == NULL) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Incorrect context for running data-block fake user toggling");
+ return OPERATOR_CANCELLED;
+ }
+
+ memset(&idptr, 0, sizeof(idptr));
+ RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, NULL);
+ RNA_property_update(C, &pprop.ptr, pprop.prop);
+
+ return OPERATOR_FINISHED;
+}
+
+static void ED_OT_lib_unlink(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Unlink Data-Block";
+ ot->description = "Remove a usage of a data-block, clearing the assignment";
+ ot->idname = "ED_OT_lib_unlink";
+
+ /* api callbacks */
+ ot->exec = lib_unlink_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+static int ed_flush_edits_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ ED_editors_flush_edits(bmain);
+ return OPERATOR_FINISHED;
+}
+
+static void ED_OT_flush_edits(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Flush Edits";
+ ot->description = "Flush edit data from active editing modes";
+ ot->idname = "ED_OT_flush_edits";
+
+ /* api callbacks */
+ ot->exec = ed_flush_edits_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
+}
+
+void ED_operatortypes_edutils(void)
+{
+ WM_operatortype_append(ED_OT_lib_fake_user_toggle);
+ WM_operatortype_append(ED_OT_lib_unlink);
+ WM_operatortype_append(ED_OT_flush_edits);
+}
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index 8e4a3df920e..1c8a56e0608 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -35,11 +35,11 @@ set(INC
set(SRC
uvedit_buttons.c
uvedit_draw.c
+ uvedit_islands.c
uvedit_ops.c
uvedit_parametrizer.c
uvedit_path.c
uvedit_rip.c
- uvedit_islands.c
uvedit_select.c
uvedit_smart_stitch.c
uvedit_unwrap_ops.c
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 306f8a2c561..28567234fab 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -25,7 +25,6 @@
struct BMFace;
struct BMLoop;
-struct Image;
struct Object;
struct Scene;
struct SpaceImage;
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 5b3d858329a..aac5b96f737 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -1812,7 +1812,7 @@ static void UV_OT_cursor_set(wmOperatorType *ot)
-FLT_MAX,
FLT_MAX,
"Location",
- "Cursor location in normalized (0.0-1.0) coordinates",
+ "Cursor location in normalized (0.0 to 1.0) coordinates",
-10.0f,
10.0f);
}
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 6dac31794b4..c1d222c9368 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -2808,7 +2808,7 @@ void UV_OT_stitch(wmOperatorType *ot)
RNA_def_boolean(ot->srna,
"midpoint_snap",
0,
- "Snap At Midpoint",
+ "Snap at Midpoint",
"UVs are stitched at midpoint instead of at static island");
RNA_def_boolean(ot->srna, "clear_seams", 1, "Clear Seams", "Clear seams of stitched edges");
RNA_def_enum(ot->srna,