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:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c5
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c5
-rw-r--r--source/blender/editors/animation/anim_ops.c5
-rw-r--r--source/blender/editors/animation/keyframes_draw.c38
-rw-r--r--source/blender/editors/armature/armature_skinning.c1
-rw-r--r--source/blender/editors/curve/CMakeLists.txt2
-rw-r--r--source/blender/editors/curves/CMakeLists.txt4
-rw-r--r--source/blender/editors/curves/intern/curves_add.cc2
-rw-r--r--source/blender/editors/curves/intern/curves_ops.cc140
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt2
-rw-r--r--source/blender/editors/geometry/geometry_attributes.cc12
-rw-r--r--source/blender/editors/gizmo_library/gizmo_draw_utils.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_sculpt_paint.c166
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c5
-rw-r--r--source/blender/editors/include/ED_anim_api.h2
-rw-r--r--source/blender/editors/include/ED_fileselect.h8
-rw-r--r--source/blender/editors/include/ED_mesh.h16
-rw-r--r--source/blender/editors/include/ED_scene.h5
-rw-r--r--source/blender/editors/include/ED_screen.h2
-rw-r--r--source/blender/editors/include/ED_uvedit.h12
-rw-r--r--source/blender/editors/include/ED_view3d.h29
-rw-r--r--source/blender/editors/include/UI_icons.h2
-rw-r--r--source/blender/editors/include/UI_interface.h37
-rw-r--r--source/blender/editors/include/UI_interface_icons.h2
-rw-r--r--source/blender/editors/interface/interface.cc73
-rw-r--r--source/blender/editors/interface/interface_handlers.c28
-rw-r--r--source/blender/editors/interface/interface_intern.h20
-rw-r--r--source/blender/editors/interface/interface_layout.c16
-rw-r--r--source/blender/editors/interface/interface_region_search.cc37
-rw-r--r--source/blender/editors/interface/interface_style.cc2
-rw-r--r--source/blender/editors/interface/interface_templates.c20
-rw-r--r--source/blender/editors/interface/interface_widgets.c461
-rw-r--r--source/blender/editors/interface/view2d_gizmo_navigate.cc7
-rw-r--r--source/blender/editors/io/io_alembic.c3
-rw-r--r--source/blender/editors/io/io_cache.c18
-rw-r--r--source/blender/editors/io/io_usd.c17
-rw-r--r--source/blender/editors/mask/mask_add.c4
-rw-r--r--source/blender/editors/mask/mask_query.c4
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt6
-rw-r--r--source/blender/editors/mesh/editface.cc (renamed from source/blender/editors/mesh/editface.c)170
-rw-r--r--source/blender/editors/mesh/editmesh_add.c18
-rw-r--r--source/blender/editors/mesh/editmesh_add_gizmo.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c2
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c2
-rw-r--r--source/blender/editors/mesh/mesh_data.cc (renamed from source/blender/editors/mesh/mesh_data.c)148
-rw-r--r--source/blender/editors/mesh/mesh_intern.h10
-rw-r--r--source/blender/editors/mesh/meshtools.cc (renamed from source/blender/editors/mesh/meshtools.c)234
-rw-r--r--source/blender/editors/object/object_add.cc88
-rw-r--r--source/blender/editors/object/object_bake_api.c8
-rw-r--r--source/blender/editors/object/object_constraint.c4
-rw-r--r--source/blender/editors/object/object_edit.c24
-rw-r--r--source/blender/editors/object/object_modes.c7
-rw-r--r--source/blender/editors/object/object_relations.c137
-rw-r--r--source/blender/editors/render/render_preview.cc24
-rw-r--r--source/blender/editors/scene/scene_edit.c12
-rw-r--r--source/blender/editors/screen/screen_edit.c2
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt2
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_add.cc237
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_brush.cc (renamed from source/blender/editors/sculpt_paint/curves_sculpt_3d_brush.cc)96
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_comb.cc109
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_delete.cc213
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc249
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_intern.hh33
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_ops.cc51
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc107
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c199
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.cc8
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c43
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_face_set.c35
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_ops.c21
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_paint_image.cc86
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c2
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c6
-rw-r--r--source/blender/editors/space_clip/clip_intern.h6
-rw-r--r--source/blender/editors/space_clip/space_clip.c167
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c367
-rw-r--r--source/blender/editors/space_clip/tracking_select.c83
-rw-r--r--source/blender/editors/space_file/filelist.c20
-rw-r--r--source/blender/editors/space_file/filesel.c18
-rw-r--r--source/blender/editors/space_file/fsmenu.c8
-rw-r--r--source/blender/editors/space_file/fsmenu.h4
-rw-r--r--source/blender/editors/space_image/image_ops.c369
-rw-r--r--source/blender/editors/space_image/image_undo.c2
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c1
-rw-r--r--source/blender/editors/space_nla/nla_channels.c116
-rw-r--r--source/blender/editors/space_node/drawnode.cc40
-rw-r--r--source/blender/editors/space_node/node_context_path.cc2
-rw-r--r--source/blender/editors/space_node/node_draw.cc12
-rw-r--r--source/blender/editors/space_node/node_edit.cc179
-rw-r--r--source/blender/editors/space_node/node_intern.hh16
-rw-r--r--source/blender/editors/space_node/node_select.cc2
-rw-r--r--source/blender/editors/space_node/space_node.cc10
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt2
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.cc3
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.cc8
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.cc12
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.cc231
-rw-r--r--source/blender/editors/space_sequencer/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c127
-rw-r--r--source/blender/editors/space_sequencer/sequencer_channels_draw.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c17
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c196
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_thumbnails.c4
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc22
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc4
-rw-r--r--source/blender/editors/space_text/text_draw.c2
-rw-r--r--source/blender/editors/space_view3d/drawobject.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c2
-rw-r--r--source/blender/editors/transform/transform.c2
-rw-r--r--source/blender/editors/transform/transform_convert.c87
-rw-r--r--source/blender/editors/transform/transform_convert_node.c4
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c18
-rw-r--r--source/blender/editors/transform/transform_convert_tracking.c10
-rw-r--r--source/blender/editors/transform/transform_snap.c58
-rw-r--r--source/blender/editors/util/ed_util_ops.cc10
-rw-r--r--source/blender/editors/uvedit/uvedit_select.c33
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c4
125 files changed, 3559 insertions, 2367 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 7bb1d652bf1..c2d517588b2 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -4020,6 +4020,8 @@ static bool acf_nlaaction_setting_valid(bAnimContext *UNUSED(ac),
else {
return false;
}
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return true;
/* unsupported */
default:
@@ -4040,6 +4042,9 @@ static int acf_nlaaction_setting_flag(bAnimContext *UNUSED(ac),
*neg = true; /* XXX */
return ADT_NLA_EDIT_NOMAP;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
+
default: /* unsupported */
return 0;
}
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 31d90c8bfec..f148bb5b77d 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -125,6 +125,7 @@ void ANIM_set_active_channel(bAnimContext *ac,
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_NLAACTION:
case ANIMTYPE_DSSIMULATION: {
/* need to verify that this data is valid for now */
if (ale->adt) {
@@ -182,6 +183,7 @@ void ANIM_set_active_channel(bAnimContext *ac,
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_NLAACTION:
case ANIMTYPE_DSSIMULATION: {
/* need to verify that this data is valid for now */
if (ale && ale->adt) {
@@ -199,7 +201,6 @@ void ANIM_set_active_channel(bAnimContext *ac,
/* unhandled currently, but may be interesting */
case ANIMTYPE_MASKLAYER:
case ANIMTYPE_SHAPEKEY:
- case ANIMTYPE_NLAACTION:
break;
/* other types */
@@ -312,6 +313,7 @@ static eAnimChannels_SetFlag anim_channels_selection_flag_for_toggle(const ListB
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_NLAACTION:
case ANIMTYPE_DSSIMULATION: {
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) {
return ACHANNEL_SETFLAG_CLEAR;
@@ -420,6 +422,7 @@ static void anim_channels_select_set(bAnimContext *ac,
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_NLAACTION:
case ANIMTYPE_DSSIMULATION: {
/* need to verify that this data is valid for now */
if (ale->adt) {
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 5b0c5eac11b..84f99ec0ac0 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -38,7 +38,6 @@
#include "SEQ_iterator.h"
#include "SEQ_sequencer.h"
#include "SEQ_time.h"
-#include "SEQ_transform.h"
#include "anim_intern.h"
@@ -112,9 +111,9 @@ static int seq_frame_apply_snap(bContext *C, Scene *scene, const int timeline_fr
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
seq_frame_snap_update_best(
- SEQ_transform_get_left_handle_frame(seq), timeline_frame, &best_frame, &best_distance);
+ SEQ_time_left_handle_frame_get(seq), timeline_frame, &best_frame, &best_distance);
seq_frame_snap_update_best(
- SEQ_transform_get_right_handle_frame(seq), timeline_frame, &best_frame, &best_distance);
+ SEQ_time_right_handle_frame_get(seq), timeline_frame, &best_frame, &best_distance);
}
SEQ_collection_free(strips);
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index 58d093c678d..786204a52ed 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -168,11 +168,11 @@ void draw_keyframe_shape(float x,
/* Common attributes shared between the draw calls. */
typedef struct DrawKeylistUIData {
float alpha;
- float icon_sz;
- float half_icon_sz;
- float smaller_sz;
- float ipo_sz;
- float gpencil_sz;
+ float icon_size;
+ float half_icon_size;
+ float smaller_size;
+ float ipo_size;
+ float gpencil_size;
float screenspace_margin;
float sel_color[4];
float unsel_color[4];
@@ -195,11 +195,11 @@ static void draw_keylist_ui_data_init(DrawKeylistUIData *ctx,
/* TODO: allow this opacity factor to be themed? */
ctx->alpha = channel_locked ? 0.25f : 1.0f;
- ctx->icon_sz = U.widget_unit * 0.5f * yscale_fac;
- ctx->half_icon_sz = 0.5f * ctx->icon_sz;
- ctx->smaller_sz = 0.35f * ctx->icon_sz;
- ctx->ipo_sz = 0.1f * ctx->icon_sz;
- ctx->gpencil_sz = ctx->smaller_sz * 0.8f;
+ ctx->icon_size = U.widget_unit * 0.5f * yscale_fac;
+ ctx->half_icon_size = 0.5f * ctx->icon_size;
+ ctx->smaller_size = 0.35f * ctx->icon_size;
+ ctx->ipo_size = 0.1f * ctx->icon_size;
+ ctx->gpencil_size = ctx->smaller_size * 0.8f;
ctx->screenspace_margin = (0.35f * (float)UI_UNIT_X) / UI_view2d_scale_get_x(v2d);
ctx->show_ipo = (saction_flag & SACTION_SHOW_INTERPOLATION) != 0;
@@ -242,8 +242,8 @@ static void draw_keylist_block_gpencil(const DrawKeylistUIData *ctx,
&(const rctf){
.xmin = ab->cfra,
.xmax = min_ff(ab->next->cfra - (ctx->screenspace_margin * size), ab->next->cfra),
- .ymin = ypos - ctx->gpencil_sz,
- .ymax = ypos + ctx->gpencil_sz,
+ .ymin = ypos - ctx->gpencil_size,
+ .ymax = ypos + ctx->gpencil_size,
},
true,
0.25f * (float)UI_UNIT_X,
@@ -259,8 +259,8 @@ static void draw_keylist_block_moving_hold(const DrawKeylistUIData *ctx,
&(const rctf){
.xmin = ab->cfra,
.xmax = ab->next->cfra,
- .ymin = ypos - ctx->smaller_sz,
- .ymax = ypos + ctx->smaller_sz,
+ .ymin = ypos - ctx->smaller_size,
+ .ymax = ypos + ctx->smaller_size,
},
true,
3.0f,
@@ -275,8 +275,8 @@ static void draw_keylist_block_standard(const DrawKeylistUIData *ctx,
&(const rctf){
.xmin = ab->cfra,
.xmax = ab->next->cfra,
- .ymin = ypos - ctx->half_icon_sz,
- .ymax = ypos + ctx->half_icon_sz,
+ .ymin = ypos - ctx->half_icon_size,
+ .ymax = ypos + ctx->half_icon_size,
},
true,
3.0f,
@@ -291,8 +291,8 @@ static void draw_keylist_block_interpolation_line(const DrawKeylistUIData *ctx,
&(const rctf){
.xmin = ab->cfra,
.xmax = ab->next->cfra,
- .ymin = ypos - ctx->ipo_sz,
- .ymax = ypos + ctx->ipo_sz,
+ .ymin = ypos - ctx->ipo_size,
+ .ymax = ypos + ctx->ipo_size,
},
true,
3.0f,
@@ -367,7 +367,7 @@ static void draw_keylist_keys(const DrawKeylistUIData *ctx,
draw_keyframe_shape(ak->cfra,
ypos,
- ctx->icon_sz,
+ ctx->icon_size,
(ak->sel & SELECT),
ak->key_type,
KEYFRAME_SHAPE_BOTH,
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index 64035732a39..3a1e7419d3c 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -9,6 +9,7 @@
#include "DNA_armature_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt
index b21ae305dbe..791e28de694 100644
--- a/source/blender/editors/curve/CMakeLists.txt
+++ b/source/blender/editors/curve/CMakeLists.txt
@@ -23,9 +23,9 @@ set(SRC
editcurve.c
editcurve_add.c
editcurve_paint.c
+ editcurve_pen.c
editcurve_query.c
editcurve_select.c
- editcurve_pen.c
editcurve_undo.c
editfont.c
editfont_undo.c
diff --git a/source/blender/editors/curves/CMakeLists.txt b/source/blender/editors/curves/CMakeLists.txt
index 1731d224b3e..a5d8390e7f2 100644
--- a/source/blender/editors/curves/CMakeLists.txt
+++ b/source/blender/editors/curves/CMakeLists.txt
@@ -11,6 +11,9 @@ set(INC
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+
+ # RNA_prototypes.h
+ ${CMAKE_BINARY_DIR}/source/blender/makesrna
)
set(SRC
@@ -24,3 +27,4 @@ set(LIB
)
blender_add_lib(bf_editor_curves "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
+add_dependencies(bf_editor_curves bf_rna)
diff --git a/source/blender/editors/curves/intern/curves_add.cc b/source/blender/editors/curves/intern/curves_add.cc
index 7d9e663c444..552ef1d96c8 100644
--- a/source/blender/editors/curves/intern/curves_add.cc
+++ b/source/blender/editors/curves/intern/curves_add.cc
@@ -20,7 +20,7 @@ bke::CurvesGeometry primitive_random_sphere(const int curves_size, const int poi
MutableSpan<float3> positions = curves.positions_for_write();
float *radius_data = (float *)CustomData_add_layer_named(
- &curves.point_data, CD_PROP_FLOAT, CD_DEFAULT, nullptr, curves.point_size, "radius");
+ &curves.point_data, CD_PROP_FLOAT, CD_DEFAULT, nullptr, curves.point_num, "radius");
MutableSpan<float> radii{radius_data, curves.points_num()};
for (const int i : offsets.index_range()) {
diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc
index 7d07c211542..5588f7440a8 100644
--- a/source/blender/editors/curves/intern/curves_ops.cc
+++ b/source/blender/editors/curves/intern/curves_ops.cc
@@ -20,6 +20,7 @@
#include "BKE_layer.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
+#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_report.h"
@@ -32,9 +33,11 @@
#include "DNA_scene_types.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_prototypes.h"
/**
* The code below uses a suffix naming convention to indicate the coordinate space:
@@ -192,7 +195,7 @@ static void try_convert_single_object(Object &curves_ob,
/* Prepare utility data structure to map hair roots to mfaces. */
const Span<int> mface_to_poly_map{
- static_cast<int *>(CustomData_get_layer(&surface_me.fdata, CD_ORIGINDEX)),
+ static_cast<const int *>(CustomData_get_layer(&surface_me.fdata, CD_ORIGINDEX)),
surface_me.totface};
Array<Vector<int>> poly_to_mface_map(surface_me.totpoly);
for (const int mface_i : mface_to_poly_map.index_range()) {
@@ -315,6 +318,140 @@ static void CURVES_OT_convert_to_particle_system(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
}
+namespace convert_from_particle_system {
+
+static bke::CurvesGeometry particles_to_curves(Object &object, ParticleSystem &psys)
+{
+ ParticleSettings &settings = *psys.part;
+ if (psys.part->type != PART_HAIR) {
+ return {};
+ }
+
+ const bool transfer_parents = (settings.draw & PART_DRAW_PARENT) || settings.childtype == 0;
+
+ const Span<ParticleCacheKey *> parents_cache{psys.pathcache, psys.totcached};
+ const Span<ParticleCacheKey *> children_cache{psys.childcache, psys.totchildcache};
+
+ int points_num = 0;
+ Vector<int> curve_offsets;
+ Vector<int> parents_to_transfer;
+ Vector<int> children_to_transfer;
+ if (transfer_parents) {
+ for (const int parent_i : parents_cache.index_range()) {
+ const int segments = parents_cache[parent_i]->segments;
+ if (segments <= 0) {
+ continue;
+ }
+ parents_to_transfer.append(parent_i);
+ curve_offsets.append(points_num);
+ points_num += segments + 1;
+ }
+ }
+ for (const int child_i : children_cache.index_range()) {
+ const int segments = children_cache[child_i]->segments;
+ if (segments <= 0) {
+ continue;
+ }
+ children_to_transfer.append(child_i);
+ curve_offsets.append(points_num);
+ points_num += segments + 1;
+ }
+ const int curves_num = parents_to_transfer.size() + children_to_transfer.size();
+ curve_offsets.append(points_num);
+ BLI_assert(curve_offsets.size() == curves_num + 1);
+ bke::CurvesGeometry curves(points_num, curves_num);
+ curves.offsets_for_write().copy_from(curve_offsets);
+
+ const float4x4 object_to_world_mat = object.obmat;
+ const float4x4 world_to_object_mat = object_to_world_mat.inverted();
+
+ MutableSpan<float3> positions = curves.positions_for_write();
+
+ const auto copy_hair_to_curves = [&](const Span<ParticleCacheKey *> hair_cache,
+ const Span<int> indices_to_transfer,
+ const int curve_index_offset) {
+ threading::parallel_for(indices_to_transfer.index_range(), 256, [&](const IndexRange range) {
+ for (const int i : range) {
+ const int hair_i = indices_to_transfer[i];
+ const int curve_i = i + curve_index_offset;
+ const IndexRange points = curves.points_for_curve(curve_i);
+ const Span<ParticleCacheKey> keys{hair_cache[hair_i], points.size()};
+ for (const int key_i : keys.index_range()) {
+ const float3 key_pos_wo = keys[key_i].co;
+ positions[points[key_i]] = world_to_object_mat * key_pos_wo;
+ }
+ }
+ });
+ };
+
+ if (transfer_parents) {
+ copy_hair_to_curves(parents_cache, parents_to_transfer, 0);
+ }
+ copy_hair_to_curves(children_cache, children_to_transfer, parents_to_transfer.size());
+
+ curves.update_curve_types();
+ curves.tag_topology_changed();
+ return curves;
+}
+
+static int curves_convert_from_particle_system_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main &bmain = *CTX_data_main(C);
+ ViewLayer &view_layer = *CTX_data_view_layer(C);
+ Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
+ Object *ob_from_orig = ED_object_active_context(C);
+ ParticleSystem *psys_orig = static_cast<ParticleSystem *>(
+ CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data);
+ if (psys_orig == nullptr) {
+ psys_orig = psys_get_current(ob_from_orig);
+ }
+ if (psys_orig == nullptr) {
+ return OPERATOR_CANCELLED;
+ }
+ Object *ob_from_eval = DEG_get_evaluated_object(&depsgraph, ob_from_orig);
+ ParticleSystem *psys_eval = nullptr;
+ LISTBASE_FOREACH (ModifierData *, md, &ob_from_eval->modifiers) {
+ if (md->type != eModifierType_ParticleSystem) {
+ continue;
+ }
+ ParticleSystemModifierData *psmd = reinterpret_cast<ParticleSystemModifierData *>(md);
+ if (!STREQ(psmd->psys->name, psys_orig->name)) {
+ continue;
+ }
+ psys_eval = psmd->psys;
+ }
+
+ Object *ob_new = BKE_object_add(&bmain, &view_layer, OB_CURVES, psys_eval->name);
+ ob_new->dtx |= OB_DRAWBOUNDOX; /* TODO: Remove once there is actual drawing. */
+ Curves *curves_id = static_cast<Curves *>(ob_new->data);
+ BKE_object_apply_mat4(ob_new, ob_from_orig->obmat, true, false);
+ bke::CurvesGeometry::wrap(curves_id->geometry) = particles_to_curves(*ob_from_eval, *psys_eval);
+
+ DEG_relations_tag_update(&bmain);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, nullptr);
+
+ return OPERATOR_FINISHED;
+}
+
+static bool curves_convert_from_particle_system_poll(bContext *C)
+{
+ return ED_object_active_context(C) != nullptr;
+}
+
+} // namespace convert_from_particle_system
+
+static void CURVES_OT_convert_from_particle_system(wmOperatorType *ot)
+{
+ ot->name = "Convert Particle System to Curves";
+ ot->idname = "CURVES_OT_convert_from_particle_system";
+ ot->description = "Add a new curves object based on the current state of the particle system";
+
+ ot->poll = convert_from_particle_system::curves_convert_from_particle_system_poll;
+ ot->exec = convert_from_particle_system::curves_convert_from_particle_system_exec;
+
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+}
+
namespace snap_curves_to_surface {
enum class AttachMode {
@@ -514,5 +651,6 @@ void ED_operatortypes_curves()
{
using namespace blender::ed::curves;
WM_operatortype_append(CURVES_OT_convert_to_particle_system);
+ WM_operatortype_append(CURVES_OT_convert_from_particle_system);
WM_operatortype_append(CURVES_OT_snap_curves_to_surface);
}
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 9e7e00d5656..9bedfb6ee58 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -777,12 +777,14 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
ops.curves.sculpt_cut
ops.curves.sculpt_delete
ops.curves.sculpt_grow_shrink
+ ops.curves.sculpt_puff
ops.curves.sculpt_snake_hook
ops.generic.cursor
ops.generic.select
ops.generic.select_box
ops.generic.select_circle
ops.generic.select_lasso
+ ops.generic.select_paint
ops.gpencil.draw
ops.gpencil.draw.eraser
ops.gpencil.draw.line
diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc
index 05f9e19da71..cfc158b117f 100644
--- a/source/blender/editors/geometry/geometry_attributes.cc
+++ b/source/blender/editors/geometry/geometry_attributes.cc
@@ -385,24 +385,16 @@ void GEOMETRY_OT_color_attribute_add(wmOperatorType *ot)
ot->srna, "name", "Color", MAX_NAME, "Name", "Name of new color attribute");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- static EnumPropertyItem domains[3] = {{ATTR_DOMAIN_POINT, "POINT", 0, "Vertex", ""},
- {ATTR_DOMAIN_CORNER, "CORNER", 0, "Face Corner", ""},
- {0, nullptr, 0, nullptr, nullptr}};
-
- static EnumPropertyItem types[3] = {{CD_PROP_COLOR, "COLOR", 0, "Color", ""},
- {CD_PROP_BYTE_COLOR, "BYTE_COLOR", 0, "Byte Color", ""},
- {0, nullptr, 0, nullptr, nullptr}};
-
prop = RNA_def_enum(ot->srna,
"domain",
- domains,
+ rna_enum_color_attribute_domain_items,
ATTR_DOMAIN_POINT,
"Domain",
"Type of element that attribute is stored on");
prop = RNA_def_enum(ot->srna,
"data_type",
- types,
+ rna_enum_color_attribute_type_items,
CD_PROP_COLOR,
"Data Type",
"Type of data stored in attribute");
diff --git a/source/blender/editors/gizmo_library/gizmo_draw_utils.c b/source/blender/editors/gizmo_library/gizmo_draw_utils.c
index c6303c197e7..178a2b52b62 100644
--- a/source/blender/editors/gizmo_library/gizmo_draw_utils.c
+++ b/source/blender/editors/gizmo_library/gizmo_draw_utils.c
@@ -95,7 +95,7 @@ void wm_gizmo_vec_draw(
immEnd();
}
else if (primitive_type == GPU_PRIM_TRI_FAN) {
- /* Note(Metal): Tri-fan alternative for Metal. Triangle List is more efficient for small
+ /* NOTE(Metal): Tri-fan alternative for Metal. Triangle List is more efficient for small
* primitive counts. */
int tri_count = vert_count - 2;
immBegin(GPU_PRIM_TRIS, tri_count * 3);
diff --git a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
index b326d6d1859..a0e30c7518a 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
@@ -74,7 +74,7 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz,
GPU_viewport_size_get_f(viewport);
GPUVertFormat *format = immVertexFormat();
- /* Note(Metal): Prefer 3D coordinate for 2D rendering when using 3D shader. */
+ /* NOTE(Metal): Prefer 3D coordinate for 2D rendering when using 3D shader. */
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
/* TODO: other draw styles. */
diff --git a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
index a76242404ba..1d9fc35eda8 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
@@ -96,7 +96,7 @@ static void dial_geom_draw(const float color[4],
ED_GIZMO_DIAL_DRAW_FLAG_FILL)));
GPUVertFormat *format = immVertexFormat();
- /* Note(Metal): Prefer using 3D coordinates with 3D shader, even if rendering 2D gizmo's. */
+ /* NOTE(Metal): Prefer using 3D coordinates with 3D shader, even if rendering 2D gizmo's. */
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
if (clip_plane) {
diff --git a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
index 5fb1173521a..46fede8f6be 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
@@ -98,7 +98,7 @@ static void move_geom_draw(const wmGizmo *gz,
ED_GIZMO_MOVE_DRAW_FLAG_FILL)));
GPUVertFormat *format = immVertexFormat();
- /* Note(Metal): Prefer using 3D coordinates with 3D shader, even if rendering 2D gizmo's. */
+ /* NOTE(Metal): Prefer using 3D coordinates with 3D shader, even if rendering 2D gizmo's. */
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(filled ? GPU_SHADER_3D_UNIFORM_COLOR :
diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
index 3cdf364e4b2..01ac02a9a1d 100644
--- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c
+++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
@@ -146,6 +146,10 @@ typedef struct tGP_BrushEditData {
float inv_mat[4][4];
RNG *rng;
+ /* Auto-masking strokes. */
+ struct GHash *automasking_strokes;
+ bool automasking_ready;
+
} tGP_BrushEditData;
/* Callback for performing some brush operation on a single point */
@@ -1182,9 +1186,18 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op)
gso->region = CTX_wm_region(C);
Paint *paint = &ts->gp_sculptpaint->paint;
- gso->brush = paint->brush;
+ Brush *brush = paint->brush;
+ gso->brush = brush;
BKE_curvemapping_init(gso->brush->curve);
+ if (brush->gpencil_settings->sculpt_mode_flag &
+ (GP_SCULPT_FLAGMODE_AUTOMASK_STROKE | GP_SCULPT_FLAGMODE_AUTOMASK_LAYER |
+ GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL)) {
+ gso->automasking_strokes = BLI_ghash_ptr_new(__func__);
+ }
+ else {
+ gso->automasking_strokes = NULL;
+ }
/* save mask */
gso->mask = ts->gpencil_selectmode_sculpt;
@@ -1285,6 +1298,10 @@ static void gpencil_sculpt_brush_exit(bContext *C, wmOperator *op)
BLI_rng_free(gso->rng);
}
+ if (gso->automasking_strokes != NULL) {
+ BLI_ghash_free(gso->automasking_strokes, NULL, NULL);
+ }
+
/* Disable headerprints. */
ED_workspace_status_text(C, NULL);
@@ -1570,11 +1587,15 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C,
bool redo_geom = false;
Object *ob = gso->object;
bGPdata *gpd = ob->data;
- char tool = gso->brush->gpencil_sculpt_tool;
+ const char tool = gso->brush->gpencil_sculpt_tool;
GP_SpaceConversion *gsc = &gso->gsc;
Brush *brush = gso->brush;
const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
gso->brush->size;
+ const bool is_automasking = (brush->gpencil_settings->sculpt_mode_flag &
+ (GP_SCULPT_FLAGMODE_AUTOMASK_STROKE |
+ GP_SCULPT_FLAGMODE_AUTOMASK_LAYER |
+ GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL)) != 0;
/* Calc bound box matrix. */
float bound_mat[4][4];
BKE_gpencil_layer_transform_matrix_get(gso->depsgraph, gso->object, gpl, bound_mat);
@@ -1589,6 +1610,13 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C,
continue;
}
+ {
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
+ if ((is_automasking) && (!BLI_ghash_haskey(gso->automasking_strokes, gps_active))) {
+ continue;
+ }
+ }
+
/* Check if the stroke collide with brush. */
if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) {
continue;
@@ -1699,6 +1727,132 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C,
return changed;
}
+/* Get list of Auto-Masking strokes. */
+static bool get_automasking_strokes_list(tGP_BrushEditData *gso)
+{
+ bGPdata *gpd = gso->gpd;
+ GP_SpaceConversion *gsc = &gso->gsc;
+ Brush *brush = gso->brush;
+ Object *ob = gso->object;
+ Material *mat_active = BKE_gpencil_material(ob, ob->actcol);
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const bool is_masking_stroke = (brush->gpencil_settings->sculpt_mode_flag &
+ GP_SCULPT_FLAGMODE_AUTOMASK_STROKE) != 0;
+ const bool is_masking_layer = (brush->gpencil_settings->sculpt_mode_flag &
+ GP_SCULPT_FLAGMODE_AUTOMASK_LAYER) != 0;
+ const bool is_masking_material = (brush->gpencil_settings->sculpt_mode_flag &
+ GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL) != 0;
+ int mval_i[2];
+ round_v2i_v2fl(mval_i, gso->mval);
+
+ /* Define a fix number of pixel as cursor radius. */
+ const int radius = 10;
+ bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ /* Only editable and visible layers are considered. */
+ if (!BKE_gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+ continue;
+ }
+ /* Calculate bound box matrix. */
+ float bound_mat[4][4];
+ BKE_gpencil_layer_transform_matrix_get(gso->depsgraph, gso->object, gpl, bound_mat);
+
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->totpoints == 0) {
+ continue;
+ }
+ /* Check if the color is editable. */
+ if (ED_gpencil_stroke_material_editable(gso->object, gpl, gps) == false) {
+ continue;
+ }
+
+ /* Layer Auto-Masking. */
+ if ((is_masking_layer) && (gpl == gpl_active)) {
+ BLI_ghash_insert(gso->automasking_strokes, gps, gps);
+ continue;
+ }
+ /* Material Auto-Masking. */
+ if (is_masking_material) {
+ Material *mat = BKE_object_material_get(ob, gps->mat_nr + 1);
+ if (mat == mat_active) {
+ BLI_ghash_insert(gso->automasking_strokes, gps, gps);
+ continue;
+ }
+ }
+
+ /* If Stroke Auto-Masking is not enabled, nothing else to do. */
+ if (!is_masking_stroke) {
+ continue;
+ }
+
+ /* Check if the stroke collide with brush. */
+ if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) {
+ continue;
+ }
+
+ bGPDspoint *pt1, *pt2;
+ int pc1[2] = {0};
+ int pc2[2] = {0};
+ bGPDspoint npt;
+
+ if (gps->totpoints == 1) {
+ gpencil_point_to_parent_space(gps->points, bound_mat, &npt);
+ gpencil_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]);
+
+ /* Only check if point is inside. */
+ if (len_v2v2_int(mval_i, pc1) <= radius) {
+ BLI_ghash_insert(gso->automasking_strokes, gps, gps);
+ }
+ }
+ else {
+ /* Loop over the points in the stroke, checking for intersections
+ * - an intersection means that we touched the stroke.
+ */
+ for (int i = 0; (i + 1) < gps->totpoints; i++) {
+ /* Get points to work with. */
+ pt1 = gps->points + i;
+ pt2 = gps->points + i + 1;
+
+ /* Check first point. */
+ gpencil_point_to_parent_space(pt1, bound_mat, &npt);
+ gpencil_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]);
+ if (len_v2v2_int(mval_i, pc1) <= radius) {
+ BLI_ghash_insert(gso->automasking_strokes, gps, gps);
+ i = gps->totpoints;
+ continue;
+ }
+
+ /* Check second point. */
+ gpencil_point_to_parent_space(pt2, bound_mat, &npt);
+ gpencil_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]);
+ if (len_v2v2_int(mval_i, pc2) <= radius) {
+ BLI_ghash_insert(gso->automasking_strokes, gps, gps);
+ i = gps->totpoints;
+ continue;
+ }
+
+ /* Check segment. */
+ if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
+ BLI_ghash_insert(gso->automasking_strokes, gps, gps);
+ i = gps->totpoints;
+ continue;
+ }
+ }
+ }
+ }
+ /* If not multi-edit, exit loop. */
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
/* Perform two-pass brushes which modify the existing strokes */
static bool gpencil_sculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
{
@@ -1840,6 +1994,14 @@ static void gpencil_sculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *
gso->brush_rect.xmax = mouse[0] + radius;
gso->brush_rect.ymax = mouse[1] + radius;
+ /* Get list of Auto-Masking strokes. */
+ if ((!gso->automasking_ready) &&
+ (brush->gpencil_settings->sculpt_mode_flag &
+ (GP_SCULPT_FLAGMODE_AUTOMASK_STROKE | GP_SCULPT_FLAGMODE_AUTOMASK_LAYER |
+ GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL))) {
+ gso->automasking_ready = get_automasking_strokes_list(gso);
+ }
+
/* Apply brush */
char tool = gso->brush->gpencil_sculpt_tool;
if (tool == GPSCULPT_TOOL_CLONE) {
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 2dc12125f40..23c385c1213 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -3077,6 +3077,11 @@ bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C,
continue;
}
+ /* Check that stroke is not closed. Closed strokes must not be included in the merge. */
+ if (gps_target->flag & GP_STROKE_CYCLIC) {
+ continue;
+ }
+
/* Check if one of the ends is inside target stroke bounding box. */
if ((!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_start, radius, diff_mat)) &&
(!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_end, radius, diff_mat))) {
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 60af05baed7..da40eef87fd 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -549,7 +549,7 @@ typedef enum eAnimChannels_SetFlag {
/* types of settings for AnimChannels */
typedef enum eAnimChannel_Settings {
ACHANNEL_SETTING_SELECT = 0,
- /** warning: for drawing UI's, need to check if this is off (maybe inverse this later) */
+ /** WARNING: for drawing UI's, need to check if this is off (maybe inverse this later). */
ACHANNEL_SETTING_PROTECT = 1,
ACHANNEL_SETTING_MUTE = 2,
ACHANNEL_SETTING_EXPAND = 3,
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index c367072e6e7..e9fcd2bd5fe 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -164,8 +164,16 @@ void ED_fileselect_window_params_get(const struct wmWindow *win,
int win_size[2],
bool *is_maximized);
+/**
+ * Return the File Browser area in which \a file_operator is active.
+ */
struct ScrArea *ED_fileselect_handler_area_find(const struct wmWindow *win,
const struct wmOperator *file_operator);
+/**
+ * Check if there is any area in \a win that acts as a modal File Browser (#SpaceFile.op is set)
+ * and return it.
+ */
+struct ScrArea *ED_fileselect_handler_area_find_any_with_op(const struct wmWindow *win);
/* TODO: Maybe we should move this to BLI?
* On the other hand, it's using defines from space-file area, so not sure... */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 59a24ed22b6..30a98129ee6 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -384,7 +384,7 @@ void ED_operatormacros_mesh(void);
*/
void ED_keymap_mesh(struct wmKeyConfig *keyconf);
-/* editface.c */
+/* editface.cc */
/**
* Copy the face flags, most importantly selection from the mesh to the final derived mesh,
@@ -520,7 +520,7 @@ float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vert
*/
void ED_vgroup_vert_active_mirror(struct Object *ob, int def_nr);
-/* mesh_data.c */
+/* mesh_data.cc */
void ED_mesh_verts_add(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_edges_add(struct Mesh *mesh, struct ReportList *reports, int count);
@@ -536,12 +536,12 @@ void ED_mesh_geometry_clear(struct Mesh *mesh);
void ED_mesh_update(struct Mesh *mesh, struct bContext *C, bool calc_edges, bool calc_edges_loose);
-void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name);
-int ED_mesh_uv_texture_add(
+void ED_mesh_uv_ensure(struct Mesh *me, const char *name);
+int ED_mesh_uv_add(
struct Mesh *me, const char *name, bool active_set, bool do_init, struct ReportList *reports);
-bool ED_mesh_uv_texture_remove_index(struct Mesh *me, int n);
-bool ED_mesh_uv_texture_remove_active(struct Mesh *me);
-bool ED_mesh_uv_texture_remove_named(struct Mesh *me, const char *name);
+bool ED_mesh_uv_remove_index(struct Mesh *me, int n);
+bool ED_mesh_uv_remove_active(struct Mesh *me);
+bool ED_mesh_uv_remove_named(struct Mesh *me, const char *name);
void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me);
/**
* Without a #bContext, called when UV-editing.
@@ -591,7 +591,7 @@ void EDBM_redo_state_restore_and_free(struct BMBackup *backup,
bool recalc_looptri) ATTR_NONNULL(1, 2);
void EDBM_redo_state_free(struct BMBackup *backup) ATTR_NONNULL(1);
-/* *** meshtools.c *** */
+/* *** meshtools.cc *** */
int ED_mesh_join_objects_exec(struct bContext *C, struct wmOperator *op);
int ED_mesh_shapes_join_objects_exec(struct bContext *C, struct wmOperator *op);
diff --git a/source/blender/editors/include/ED_scene.h b/source/blender/editors/include/ED_scene.h
index f1a2e5795ee..f67bdb9c1d7 100644
--- a/source/blender/editors/include/ED_scene.h
+++ b/source/blender/editors/include/ED_scene.h
@@ -18,6 +18,11 @@ struct Scene *ED_scene_add(struct Main *bmain,
struct bContext *C,
struct wmWindow *win,
enum eSceneCopyMethod method) ATTR_NONNULL();
+/** Special mode for adding a scene assigned to sequencer strip. */
+struct Scene *ED_scene_sequencer_add(struct Main *bmain,
+ struct bContext *C,
+ enum eSceneCopyMethod method,
+ const bool assign_strip);
/**
* \note Only call outside of area/region loops.
* \return true if successful.
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 41123aff79f..f909a13c2cb 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -666,7 +666,7 @@ bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_re
bool ED_region_panel_category_gutter_isect_xy(const ARegion *region, const int event_xy[2]);
/**
- * \note: This may return true for multiple overlapping regions.
+ * \note This may return true for multiple overlapping regions.
* If it matters, check overlapped regions first (#ARegion.overlap).
*/
bool ED_region_contains_xy(const struct ARegion *region, const int event_xy[2]);
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 06134f1d7b5..80a75da27f8 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -24,6 +24,7 @@ struct Object;
struct Scene;
struct SpaceImage;
struct ToolSettings;
+struct View2D;
struct ViewLayer;
struct bContext;
struct bNode;
@@ -242,15 +243,12 @@ void uvedit_deselect_flush(const struct Scene *scene, struct BMEditMesh *em);
*/
void uvedit_select_flush(const struct Scene *scene, struct BMEditMesh *em);
-bool ED_uvedit_nearest_uv(const struct Scene *scene,
- struct Object *obedit,
- const float co[2],
- float *dist_sq,
- float r_uv[2]);
-bool ED_uvedit_nearest_uv_multi(const struct Scene *scene,
+bool ED_uvedit_nearest_uv_multi(const struct View2D *v2d,
+ const struct Scene *scene,
struct Object **objects,
uint objects_len,
- const float co[2],
+ const int mval[2],
+ const bool ignore_selected,
float *dist_sq,
float r_uv[2]);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 51fd8e6c533..8695e03a57f 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -7,6 +7,8 @@
#pragma once
+#include "BLI_utildefines.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -256,6 +258,7 @@ typedef enum {
*/
V3D_PROJ_TEST_CLIP_CONTENT = (1 << 5),
} eV3DProjTest;
+ENUM_OPERATORS(eV3DProjTest, V3D_PROJ_TEST_CLIP_CONTENT);
#define V3D_PROJ_TEST_CLIP_DEFAULT \
(V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR)
@@ -443,14 +446,14 @@ void pose_foreachScreenBone(struct ViewContext *vc,
void ED_view3d_project_float_v2_m4(const struct ARegion *region,
const float co[3],
float r_co[2],
- float mat[4][4]);
+ const float mat[4][4]);
/**
* \note use #ED_view3d_ob_project_mat_get to get projecting mat
*/
void ED_view3d_project_float_v3_m4(const struct ARegion *region,
const float co[3],
float r_co[3],
- float mat[4][4]);
+ const float mat[4][4]);
eV3DProjStatus ED_view3d_project_base(const struct ARegion *region, struct Base *base);
@@ -700,9 +703,9 @@ void ED_view3d_win_to_vector(const struct ARegion *region, const float mval[2],
* \param do_clip_planes: Optionally clip the ray by the view clipping planes.
* \return success, false if the segment is totally clipped.
*/
-bool ED_view3d_win_to_segment_clipped(struct Depsgraph *depsgraph,
+bool ED_view3d_win_to_segment_clipped(const struct Depsgraph *depsgraph,
const struct ARegion *region,
- struct View3D *v3d,
+ const struct View3D *v3d,
const float mval[2],
float r_ray_start[3],
float r_ray_end[3],
@@ -733,7 +736,7 @@ void ED_view3d_dist_range_get(const struct View3D *v3d, float r_dist_range[2]);
/**
* \note copies logic of #ED_view3d_viewplane_get(), keep in sync.
*/
-bool ED_view3d_clip_range_get(struct Depsgraph *depsgraph,
+bool ED_view3d_clip_range_get(const struct Depsgraph *depsgraph,
const struct View3D *v3d,
const struct RegionView3D *rv3d,
float *r_clipsta,
@@ -952,6 +955,22 @@ float ED_view3d_select_dist_px(void);
void ED_view3d_viewcontext_init(struct bContext *C,
struct ViewContext *vc,
struct Depsgraph *depsgraph);
+
+/**
+ * Re-initialize `vc` with `obact` as if it's active object (with some differences).
+ *
+ * This is often used when operating on multiple objects in modes (edit, pose mode etc)
+ * where the `vc` is passed in as an argument which then references it's object data.
+ *
+ * \note members #ViewContext.obedit & #ViewContext.em are only initialized if they're already set,
+ * by #ED_view3d_viewcontext_init in most cases.
+ * This is necessary because the active object defines the current object-mode.
+ * When iterating over objects in object-mode it doesn't make sense to perform
+ * an edit-mode action on an object that happens to contain edit-mode data.
+ * In some cases these values are cleared allowing the owner of `vc` to explicitly
+ * disable edit-mode operation (to force object selection in edit-mode for e.g.).
+ * So object-mode specific values should remain cleared when initialized with another object.
+ */
void ED_view3d_viewcontext_init_object(struct ViewContext *vc, struct Object *obact);
/**
* Use this call when executing an operator,
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index d1a6501408c..ea1095b26ff 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -164,7 +164,7 @@ DEF_ICON(NLA)
DEF_ICON(PREFERENCES)
DEF_ICON(TIME)
DEF_ICON(NODETREE)
-DEF_ICON_BLANK(181)
+DEF_ICON(GEOMETRY_NODES)
DEF_ICON(CONSOLE)
DEF_ICON_BLANK(183)
DEF_ICON(TRACKER)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 1b61e87b140..a38dea0ba3d 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -202,7 +202,7 @@ enum {
UI_BUT_INACTIVE = 1 << 18,
UI_BUT_LAST_ACTIVE = 1 << 19,
UI_BUT_UNDO = 1 << 20,
- UI_BUT_IMMEDIATE = 1 << 21,
+ /* UNUSED = 1 << 21, */
UI_BUT_NO_UTF8 = 1 << 22,
/** For popups, pressing return activates this button, overriding the highlighted button.
@@ -221,7 +221,7 @@ enum {
UI_BUT_HAS_SEP_CHAR = 1 << 27,
/** Don't run updates while dragging (needed in rare cases). */
UI_BUT_UPDATE_DELAY = 1 << 28,
- /** When widget is in textedit mode, update value on each char stroke */
+ /** When widget is in text-edit mode, update value on each char stroke. */
UI_BUT_TEXTEDIT_UPDATE = 1 << 29,
/** Show 'x' icon to clear/unlink value of text or search button. */
UI_BUT_VALUE_CLEAR = 1 << 30,
@@ -454,7 +454,6 @@ void UI_draw_safe_areas(uint pos,
enum {
UI_SCROLL_PRESSED = 1 << 0,
UI_SCROLL_ARROWS = 1 << 1,
- UI_SCROLL_NO_OUTLINE = 1 << 2,
};
/**
* Function in use for buttons and for view2d sliders.
@@ -1539,31 +1538,6 @@ uiBut *uiDefIconTextBlockBut(uiBlock *block,
short height,
const char *tip);
-uiBut *uiDefKeyevtButS(uiBlock *block,
- int retval,
- const char *str,
- int x,
- int y,
- short width,
- short height,
- short *spoin,
- const char *tip);
-
-/**
- * Short pointers hard-coded.
- * \param modkeypoin: will be set to #KM_SHIFT, #KM_ALT, #KM_CTRL, #KM_OSKEY bits.
- */
-uiBut *uiDefHotKeyevtButS(uiBlock *block,
- int retval,
- const char *str,
- int x,
- int y,
- short width,
- short height,
- short *keypoin,
- const short *modkeypoin,
- const char *tip);
-
/**
* \param arg: A pointer to string/name, use #UI_but_func_search_set() below to make this work.
* here `a1` and `a2`, if set, control thumbnail preview rows/cols.
@@ -1674,15 +1648,16 @@ void UI_but_func_identity_compare_set(uiBut *but, uiButIdentityCompareFunc cmp_f
* \param name: Text to display for the item.
* \param poin: Opaque pointer (for use by the caller).
* \param iconid: The icon, #ICON_NONE for no icon.
- * \param state: The buttons state flag, compatible with #uiBut.flag,
- * typically #UI_BUT_DISABLED / #UI_BUT_INACTIVE.
+ * \param but_flag: Button flags (#uiBut.flag) indicating the state of the item, typically
+ * #UI_ACTIVE, #UI_BUT_DISABLED, #UI_BUT_INACTIVE.
+ *
* \return false if there is nothing to add.
*/
bool UI_search_item_add(uiSearchItems *items,
const char *name,
void *poin,
int iconid,
- int state,
+ int but_flag,
uint8_t name_prefix_offset);
/**
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 6416421f4f5..a1a98a4b08c 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -92,7 +92,7 @@ void UI_icon_render_id_ex(const struct bContext *C,
int UI_icon_preview_to_render_size(enum eIconSizes size);
/**
- * Draws icon with dpi scale factor.
+ * Draws icon with DPI scale factor.
*/
void UI_icon_draw(float x, float y, int icon_id);
void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha);
diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc
index 480044118f1..d6719f0aa9f 100644
--- a/source/blender/editors/interface/interface.cc
+++ b/source/blender/editors/interface/interface.cc
@@ -3849,21 +3849,22 @@ static void ui_but_update_ex(uiBut *but, const bool validate)
}
case UI_BTYPE_HOTKEY_EVENT:
if (but->flag & UI_SELECT) {
+ const uiButHotkeyEvent *hotkey_but = (uiButHotkeyEvent *)but;
- if (but->modifier_key) {
+ if (hotkey_but->modifier_key) {
char *str = but->drawstr;
but->drawstr[0] = '\0';
- if (but->modifier_key & KM_SHIFT) {
+ if (hotkey_but->modifier_key & KM_SHIFT) {
str += BLI_strcpy_rlen(str, "Shift ");
}
- if (but->modifier_key & KM_CTRL) {
+ if (hotkey_but->modifier_key & KM_CTRL) {
str += BLI_strcpy_rlen(str, "Ctrl ");
}
- if (but->modifier_key & KM_ALT) {
+ if (hotkey_but->modifier_key & KM_ALT) {
str += BLI_strcpy_rlen(str, "Alt ");
}
- if (but->modifier_key & KM_OSKEY) {
+ if (hotkey_but->modifier_key & KM_OSKEY) {
str += BLI_strcpy_rlen(str, "Cmd ");
}
@@ -3989,6 +3990,10 @@ static void ui_but_alloc_info(const eButType type,
alloc_size = sizeof(uiButTreeRow);
alloc_str = "uiButTreeRow";
break;
+ case UI_BTYPE_HOTKEY_EVENT:
+ alloc_size = sizeof(uiButHotkeyEvent);
+ alloc_str = "uiButHotkeyEvent";
+ break;
default:
alloc_size = sizeof(uiBut);
alloc_str = "uiBut";
@@ -6280,64 +6285,6 @@ uiBut *uiDefIconBlockBut(uiBlock *block,
return but;
}
-uiBut *uiDefKeyevtButS(uiBlock *block,
- int retval,
- const char *str,
- int x,
- int y,
- short width,
- short height,
- short *spoin,
- const char *tip)
-{
- uiBut *but = ui_def_but(block,
- UI_BTYPE_KEY_EVENT | UI_BUT_POIN_SHORT,
- retval,
- str,
- x,
- y,
- width,
- height,
- spoin,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- tip);
- ui_but_update(but);
- return but;
-}
-
-uiBut *uiDefHotKeyevtButS(uiBlock *block,
- int retval,
- const char *str,
- int x,
- int y,
- short width,
- short height,
- short *keypoin,
- const short *modkeypoin,
- const char *tip)
-{
- uiBut *but = ui_def_but(block,
- UI_BTYPE_HOTKEY_EVENT | UI_BUT_POIN_SHORT,
- retval,
- str,
- x,
- y,
- width,
- height,
- keypoin,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- tip);
- but->modifier_key = *modkeypoin;
- ui_but_update(but);
- return but;
-}
-
uiBut *uiDefSearchBut(uiBlock *block,
void *arg,
int retval,
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 3e3b30a2c1e..f28f9e4ce0b 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -4507,10 +4507,14 @@ static int ui_do_but_HOTKEYEVT(bContext *C,
uiHandleButtonData *data,
const wmEvent *event)
{
+ uiButHotkeyEvent *hotkey_but = (uiButHotkeyEvent *)but;
+ BLI_assert(but->type == UI_BTYPE_HOTKEY_EVENT);
+
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY, EVT_BUT_OPEN) &&
+ (event->val == KM_PRESS)) {
but->drawstr[0] = 0;
- but->modifier_key = 0;
+ hotkey_but->modifier_key = 0;
button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
return WM_UI_HANDLER_BREAK;
}
@@ -4531,20 +4535,16 @@ static int ui_do_but_HOTKEYEVT(bContext *C,
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
/* only cancel if click outside the button */
if (ui_but_contains_point_px(but, but->active->region, event->xy) == false) {
- /* data->cancel doesn't work, this button opens immediate */
- if (but->flag & UI_BUT_IMMEDIATE) {
- ui_but_value_set(but, 0);
- }
- else {
- data->cancel = true;
- }
+ data->cancel = true;
+ /* Close the containing popup (if any). */
+ data->escapecancel = true;
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
}
}
/* always set */
- but->modifier_key = event->modifier;
+ hotkey_but->modifier_key = event->modifier;
ui_but_update(but);
ED_region_tag_redraw(data->region);
@@ -8498,14 +8498,6 @@ static void button_activate_init(bContext *C,
}
button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
- /* activate right away */
- if (but->flag & UI_BUT_IMMEDIATE) {
- if (but->type == UI_BTYPE_HOTKEY_EVENT) {
- button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
- }
- /* .. more to be added here */
- }
-
if (type == BUTTON_ACTIVATE_OPEN) {
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 1c79d3218fb..1b245ba9e6f 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -229,7 +229,6 @@ struct uiBut {
bool changed;
/** so buttons can support unit systems which are not RNA */
uchar unit_type;
- short modifier_key;
short iconadd;
/** #UI_BTYPE_BLOCK data */
@@ -381,6 +380,13 @@ typedef struct uiButCurveMapping {
eButGradientType gradient_type;
} uiButCurveMapping;
+/** Derived struct for #UI_BTYPE_HOTKEY_EVENT. */
+typedef struct uiButHotkeyEvent {
+ uiBut but;
+
+ short modifier_key;
+} uiButHotkeyEvent;
+
/**
* Additional, superimposed icon for a button, invoking an operator.
*/
@@ -1212,24 +1218,24 @@ typedef enum {
/**
* Helper call to draw a menu item without a button.
*
- * \param state: The state of the button,
- * typically #UI_ACTIVE, #UI_BUT_DISABLED, #UI_BUT_INACTIVE.
+ * \param but_flag: Button flags (#uiBut.flag) indicating the state of the item, typically
+ * #UI_ACTIVE, #UI_BUT_DISABLED, #UI_BUT_INACTIVE.
* \param separator_type: The kind of separator which controls if and how the string is clipped.
- * \param r_xmax: The right hand position of the text, this takes into the icon,
- * padding and text clipping when there is not enough room to display the full text.
+ * \param r_xmax: The right hand position of the text, this takes into the icon, padding and text
+ * clipping when there is not enough room to display the full text.
*/
void ui_draw_menu_item(const struct uiFontStyle *fstyle,
rcti *rect,
const char *name,
int iconid,
- int state,
+ int but_flag,
uiMenuItemSeparatorType separator_type,
int *r_xmax);
void ui_draw_preview_item(const struct uiFontStyle *fstyle,
rcti *rect,
const char *name,
int iconid,
- int state,
+ int but_flag,
eFontStyle_Align text_align);
/**
* Version of #ui_draw_preview_item() that does not draw the menu background and item text based on
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index c1bb2ed6d18..933d7efb4d6 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -961,11 +961,17 @@ static void ui_item_enum_expand_tabs(uiLayout *layout,
static void ui_keymap_but_cb(bContext *UNUSED(C), void *but_v, void *UNUSED(key_v))
{
uiBut *but = but_v;
+ BLI_assert(but->type == UI_BTYPE_HOTKEY_EVENT);
+ const uiButHotkeyEvent *hotkey_but = (uiButHotkeyEvent *)but;
- RNA_int_set(&but->rnapoin, "shift", (but->modifier_key & KM_SHIFT) ? KM_MOD_HELD : KM_NOTHING);
- RNA_int_set(&but->rnapoin, "ctrl", (but->modifier_key & KM_CTRL) ? KM_MOD_HELD : KM_NOTHING);
- RNA_int_set(&but->rnapoin, "alt", (but->modifier_key & KM_ALT) ? KM_MOD_HELD : KM_NOTHING);
- RNA_int_set(&but->rnapoin, "oskey", (but->modifier_key & KM_OSKEY) ? KM_MOD_HELD : KM_NOTHING);
+ RNA_int_set(
+ &but->rnapoin, "shift", (hotkey_but->modifier_key & KM_SHIFT) ? KM_MOD_HELD : KM_NOTHING);
+ RNA_int_set(
+ &but->rnapoin, "ctrl", (hotkey_but->modifier_key & KM_CTRL) ? KM_MOD_HELD : KM_NOTHING);
+ RNA_int_set(
+ &but->rnapoin, "alt", (hotkey_but->modifier_key & KM_ALT) ? KM_MOD_HELD : KM_NOTHING);
+ RNA_int_set(
+ &but->rnapoin, "oskey", (hotkey_but->modifier_key & KM_OSKEY) ? KM_MOD_HELD : KM_NOTHING);
}
/**
@@ -1101,7 +1107,7 @@ static uiBut *ui_item_with_label(uiLayout *layout,
NULL);
UI_but_func_set(but, ui_keymap_but_cb, but, NULL);
if (flag & UI_ITEM_R_IMMEDIATE) {
- UI_but_flag_enable(but, UI_BUT_IMMEDIATE);
+ UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
}
}
else {
diff --git a/source/blender/editors/interface/interface_region_search.cc b/source/blender/editors/interface/interface_region_search.cc
index bc497e2647c..64de31dfe6a 100644
--- a/source/blender/editors/interface/interface_region_search.cc
+++ b/source/blender/editors/interface/interface_region_search.cc
@@ -58,7 +58,7 @@ struct uiSearchItems {
char **names;
void **pointers;
int *icons;
- int *states;
+ int *but_flags;
uint8_t *name_prefix_offsets;
/** Is there any item with an icon? */
@@ -94,7 +94,7 @@ bool UI_search_item_add(uiSearchItems *items,
const char *name,
void *poin,
int iconid,
- int state,
+ const int but_flag,
const uint8_t name_prefix_offset)
{
/* hijack for autocomplete */
@@ -148,10 +148,10 @@ bool UI_search_item_add(uiSearchItems *items,
/* Limit flags that can be set so flags such as 'UI_SELECT' aren't accidentally set
* which will cause problems, add others as needed. */
- BLI_assert(
- (state & ~(UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT | UI_BUT_HAS_SEP_CHAR)) == 0);
- if (items->states) {
- items->states[items->totitem] = state;
+ BLI_assert((but_flag &
+ ~(UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT | UI_BUT_HAS_SEP_CHAR)) == 0);
+ if (items->but_flags) {
+ items->but_flags[items->totitem] = but_flag;
}
items->totitem++;
@@ -556,7 +556,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
if (data->preview) {
/* draw items */
for (int a = 0; a < data->items.totitem; a++) {
- const int state = ((a == data->active) ? UI_ACTIVE : 0) | data->items.states[a];
+ const int but_flag = ((a == data->active) ? UI_ACTIVE : 0) | data->items.but_flags[a];
/* ensure icon is up-to-date */
ui_icon_ensure_deferred(C, data->items.icons[a], data->preview);
@@ -568,7 +568,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
&rect,
data->items.names[a],
data->items.icons[a],
- state,
+ but_flag,
UI_STYLE_TEXT_LEFT);
}
@@ -590,7 +590,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
const int search_sep_len = data->sep_string ? strlen(data->sep_string) : 0;
/* draw items */
for (int a = 0; a < data->items.totitem; a++) {
- const int state = ((a == data->active) ? UI_ACTIVE : 0) | data->items.states[a];
+ const int but_flag = ((a == data->active) ? UI_ACTIVE : 0) | data->items.but_flags[a];
char *name = data->items.names[a];
int icon = data->items.icons[a];
char *name_sep_test = nullptr;
@@ -600,7 +600,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
separator_type = UI_MENU_ITEM_SEPARATOR_SHORTCUT;
}
/* Only set for displaying additional hint (e.g. library name of a linked data-block). */
- else if (state & UI_BUT_HAS_SEP_CHAR) {
+ else if (but_flag & UI_BUT_HAS_SEP_CHAR) {
separator_type = UI_MENU_ITEM_SEPARATOR_HINT;
}
@@ -615,7 +615,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
}
/* Simple menu item. */
- ui_draw_menu_item(&data->fstyle, &rect, name, icon, state, separator_type, nullptr);
+ ui_draw_menu_item(&data->fstyle, &rect, name, icon, but_flag, separator_type, nullptr);
}
else {
/* Split menu item, faded text before the separator. */
@@ -633,7 +633,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
&rect,
name,
0,
- state | UI_BUT_INACTIVE,
+ but_flag | UI_BUT_INACTIVE,
UI_MENU_ITEM_SEPARATOR_NONE,
&name_width);
*name_sep = name_sep_prev;
@@ -646,7 +646,8 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
}
/* The previous menu item draws the active selection. */
- ui_draw_menu_item(&data->fstyle, &rect, name_sep, icon, state, separator_type, nullptr);
+ ui_draw_menu_item(
+ &data->fstyle, &rect, name_sep, icon, but_flag, separator_type, nullptr);
}
}
/* indicate more */
@@ -677,7 +678,7 @@ static void ui_searchbox_region_free_fn(ARegion *region)
MEM_freeN(data->items.names);
MEM_freeN(data->items.pointers);
MEM_freeN(data->items.icons);
- MEM_freeN(data->items.states);
+ MEM_freeN(data->items.but_flags);
if (data->items.name_prefix_offsets != nullptr) {
MEM_freeN(data->items.name_prefix_offsets);
@@ -847,7 +848,7 @@ static ARegion *ui_searchbox_create_generic_ex(bContext *C,
data->items.names = (char **)MEM_callocN(data->items.maxitem * sizeof(void *), __func__);
data->items.pointers = (void **)MEM_callocN(data->items.maxitem * sizeof(void *), __func__);
data->items.icons = (int *)MEM_callocN(data->items.maxitem * sizeof(int), __func__);
- data->items.states = (int *)MEM_callocN(data->items.maxitem * sizeof(int), __func__);
+ data->items.but_flags = (int *)MEM_callocN(data->items.maxitem * sizeof(int), __func__);
data->items.name_prefix_offsets = nullptr; /* Lazy initialized as needed. */
for (int i = 0; i < data->items.maxitem; i++) {
data->items.names[i] = (char *)MEM_callocN(data->items.maxstrlen + 1, __func__);
@@ -913,7 +914,7 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
/* widget itself */
/* NOTE: i18n messages extracting tool does the same, please keep it in sync. */
{
- const int state = ((a == data->active) ? UI_ACTIVE : 0) | data->items.states[a];
+ const int but_flag = ((a == data->active) ? UI_ACTIVE : 0) | data->items.but_flags[a];
wmOperatorType *ot = static_cast<wmOperatorType *>(data->items.pointers[a]);
char text_pre[128];
@@ -936,14 +937,14 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
&rect_pre,
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, text_pre),
data->items.icons[a],
- state,
+ but_flag,
UI_MENU_ITEM_SEPARATOR_NONE,
nullptr);
ui_draw_menu_item(&data->fstyle,
&rect_post,
data->items.names[a],
0,
- state,
+ but_flag,
data->use_shortcut_sep ? UI_MENU_ITEM_SEPARATOR_SHORTCUT :
UI_MENU_ITEM_SEPARATOR_NONE,
nullptr);
diff --git a/source/blender/editors/interface/interface_style.cc b/source/blender/editors/interface/interface_style.cc
index 0156a943015..291ede05730 100644
--- a/source/blender/editors/interface/interface_style.cc
+++ b/source/blender/editors/interface/interface_style.cc
@@ -376,7 +376,7 @@ void uiStyleInit(void)
{
const uiStyle *style = static_cast<uiStyle *>(U.uistyles.first);
- /* recover from uninitialized dpi */
+ /* Recover from uninitialized DPI. */
if (U.dpi == 0) {
U.dpi = 72;
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 4e6437e043a..cafc87e9c7f 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -742,7 +742,7 @@ static void template_id_liboverride_hierarchy_create(bContext *C,
object_active->id.tag |= LIB_TAG_DOIT;
}
BKE_lib_override_library_create(
- bmain, scene, view_layer, NULL, id, &collection_active->id, NULL, &id_override);
+ bmain, scene, view_layer, NULL, id, &collection_active->id, NULL, &id_override, false);
}
else if (object_active != NULL && !ID_IS_LINKED(object_active) &&
&object_active->instance_collection->id == id) {
@@ -754,7 +754,8 @@ static void template_id_liboverride_hierarchy_create(bContext *C,
id,
&object_active->id,
&object_active->id,
- &id_override);
+ &id_override,
+ false);
}
break;
case ID_OB:
@@ -765,7 +766,7 @@ static void template_id_liboverride_hierarchy_create(bContext *C,
object_active->id.tag |= LIB_TAG_DOIT;
}
BKE_lib_override_library_create(
- bmain, scene, view_layer, NULL, id, &collection_active->id, NULL, &id_override);
+ bmain, scene, view_layer, NULL, id, &collection_active->id, NULL, &id_override, false);
}
break;
case ID_ME:
@@ -787,13 +788,20 @@ static void template_id_liboverride_hierarchy_create(bContext *C,
if (object_active != NULL) {
object_active->id.tag |= LIB_TAG_DOIT;
}
- BKE_lib_override_library_create(
- bmain, scene, view_layer, NULL, id, &collection_active->id, NULL, &id_override);
+ BKE_lib_override_library_create(bmain,
+ scene,
+ view_layer,
+ NULL,
+ id,
+ &collection_active->id,
+ NULL,
+ &id_override,
+ false);
}
else {
object_active->id.tag |= LIB_TAG_DOIT;
BKE_lib_override_library_create(
- bmain, scene, view_layer, NULL, id, &object_active->id, NULL, &id_override);
+ bmain, scene, view_layer, NULL, id, &object_active->id, NULL, &id_override, false);
}
}
break;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 98ecf91adbc..e53d90a233e 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -107,22 +107,22 @@ typedef enum {
UI_WTYPE_TREEROW,
} uiWidgetTypeEnum;
-/* Button state argument shares bits with 'uiBut.flag'.
- * reuse flags that aren't needed for drawing to avoid collision. */
-enum {
- /* Show that holding the button opens a menu. */
- UI_STATE_HOLD_ACTION = UI_BUT_UPDATE_DELAY,
- UI_STATE_TEXT_INPUT = UI_BUT_UNDO,
- UI_STATE_ACTIVE_LEFT = UI_BUT_VALUE_CLEAR,
- UI_STATE_ACTIVE_RIGHT = UI_BUT_TEXTEDIT_UPDATE,
- UI_STATE_TEXT_BEFORE_WIDGET = UI_BUT_IMMEDIATE,
-
- UI_STATE_FLAGS_ALL = (UI_STATE_HOLD_ACTION | UI_STATE_TEXT_INPUT | UI_STATE_ACTIVE_LEFT |
- UI_STATE_ACTIVE_RIGHT | UI_STATE_TEXT_BEFORE_WIDGET),
-};
-/* Prevent accidental use. */
-#define UI_BUT_UPDATE_DELAY ((void)0)
-#define UI_BUT_UNDO ((void)0)
+/**
+ * The button's state information adapted for drawing. Use #STATE_INFO_NULL for empty state.
+ */
+typedef struct {
+ /** Copy of #uiBut.flag (possibly with overrides for drawing). */
+ int but_flag;
+ /** Copy of #uiBut.drawflag (possibly with overrides for drawing). */
+ int but_drawflag;
+
+ /** Show that holding the button opens a menu. */
+ bool has_hold_action : 1;
+ /** The button is in text input mode. */
+ bool is_text_input : 1;
+} uiWidgetStateInfo;
+
+static const uiWidgetStateInfo STATE_INFO_NULL = {0};
/** \} */
@@ -256,10 +256,21 @@ typedef struct uiWidgetType {
/* converted colors for state */
uiWidgetColors wcol;
- void (*state)(struct uiWidgetType *, int state, int drawflag, eUIEmbossType emboss);
- void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign, const float zoom);
- void (*custom)(
- uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign, const float zoom);
+ void (*state)(struct uiWidgetType *, const uiWidgetStateInfo *state, eUIEmbossType emboss)
+ ATTR_NONNULL();
+ void (*draw)(uiWidgetColors *,
+ rcti *,
+ const uiWidgetStateInfo *,
+ int roundboxalign,
+ const float zoom) ATTR_NONNULL();
+ void (*custom)(uiBut *,
+ uiWidgetColors *,
+ rcti *,
+ const uiWidgetStateInfo *,
+ int roundboxalign,
+ const float zoom) ATTR_NONNULL();
+ void (*draw_block)(
+ uiWidgetColors *, rcti *, int block_flag, int roundboxalign, const float zoom);
void (*text)(const uiFontStyle *, const uiWidgetColors *, uiBut *, rcti *);
} uiWidgetType;
@@ -1289,16 +1300,16 @@ static void widgetbase_draw(uiWidgetBase *wtb, const uiWidgetColors *wcol)
#define PREVIEW_PAD 4
-static float widget_alpha_factor(const int state)
+static float widget_alpha_factor(const uiWidgetStateInfo *state)
{
- if (state & (UI_BUT_INACTIVE | UI_BUT_DISABLED)) {
- if (state & UI_SEARCH_FILTER_NO_MATCH) {
+ if (state->but_drawflag & (UI_BUT_INACTIVE | UI_BUT_DISABLED)) {
+ if (state->but_drawflag & UI_SEARCH_FILTER_NO_MATCH) {
return 0.25f;
}
return 0.5f;
}
- if (state & UI_SEARCH_FILTER_NO_MATCH) {
+ if (state->but_drawflag & UI_SEARCH_FILTER_NO_MATCH) {
return 0.5f;
}
@@ -1367,7 +1378,10 @@ static void widget_draw_icon(
}
}
else if (ELEM(but->type, UI_BTYPE_BUT, UI_BTYPE_DECORATOR)) {
- alpha *= widget_alpha_factor(but->flag);
+ uiWidgetStateInfo state = {0};
+ state.but_flag = but->flag;
+ state.but_drawflag = but->drawflag;
+ alpha *= widget_alpha_factor(&state);
}
GPU_blend(GPU_BLEND_ALPHA);
@@ -2446,7 +2460,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
* \{ */
/* put all widget colors on half alpha, use local storage */
-static void ui_widget_color_disabled(uiWidgetType *wt, const int state)
+static void ui_widget_color_disabled(uiWidgetType *wt, const uiWidgetStateInfo *state)
{
static uiWidgetColors wcol_theme_s;
@@ -2473,8 +2487,7 @@ static void widget_active_color(uiWidgetColors *wcol)
}
static const uchar *widget_color_blend_from_flags(const uiWidgetStateColors *wcol_state,
- int state,
- int drawflag,
+ const uiWidgetStateInfo *state,
const eUIEmbossType emboss)
{
/* Explicitly require #UI_EMBOSS_NONE_OR_STATUS for color blending with no emboss. */
@@ -2482,44 +2495,44 @@ static const uchar *widget_color_blend_from_flags(const uiWidgetStateColors *wco
return NULL;
}
- if (drawflag & UI_BUT_ANIMATED_CHANGED) {
+ if (state->but_drawflag & UI_BUT_ANIMATED_CHANGED) {
return wcol_state->inner_changed_sel;
}
- if (state & UI_BUT_ANIMATED_KEY) {
+ if (state->but_flag & UI_BUT_ANIMATED_KEY) {
return wcol_state->inner_key_sel;
}
- if (state & UI_BUT_ANIMATED) {
+ if (state->but_flag & UI_BUT_ANIMATED) {
return wcol_state->inner_anim_sel;
}
- if (state & UI_BUT_DRIVEN) {
+ if (state->but_flag & UI_BUT_DRIVEN) {
return wcol_state->inner_driven_sel;
}
- if (state & UI_BUT_OVERRIDDEN) {
+ if (state->but_flag & UI_BUT_OVERRIDDEN) {
return wcol_state->inner_overridden_sel;
}
return NULL;
}
/* copy colors from theme, and set changes in it based on state */
-static void widget_state(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
+static void widget_state(uiWidgetType *wt, const uiWidgetStateInfo *state, eUIEmbossType emboss)
{
uiWidgetStateColors *wcol_state = wt->wcol_state;
- if (state & UI_BUT_LIST_ITEM) {
+ if (state->but_flag & UI_BUT_LIST_ITEM) {
/* Override default widget's colors. */
bTheme *btheme = UI_GetTheme();
wt->wcol_theme = &btheme->tui.wcol_list_item;
- if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_SEARCH_FILTER_NO_MATCH)) {
+ if (state->but_flag & (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_SEARCH_FILTER_NO_MATCH)) {
ui_widget_color_disabled(wt, state);
}
}
wt->wcol = *(wt->wcol_theme);
- const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, drawflag, emboss);
+ const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, emboss);
- if (state & UI_SELECT) {
+ if (state->but_flag & UI_SELECT) {
copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel);
if (color_blend != NULL) {
color_blend_v3_v3(wt->wcol.inner, color_blend, wcol_state->blend);
@@ -2527,12 +2540,12 @@ static void widget_state(uiWidgetType *wt, int state, int drawflag, eUIEmbossTyp
copy_v3_v3_uchar(wt->wcol.text, wt->wcol.text_sel);
- if (state & UI_SELECT) {
+ if (state->but_flag & UI_SELECT) {
SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
}
}
else {
- if (state & UI_BUT_ACTIVE_DEFAULT) {
+ if (state->but_flag & UI_BUT_ACTIVE_DEFAULT) {
copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel);
copy_v4_v4_uchar(wt->wcol.text, wt->wcol.text_sel);
}
@@ -2544,12 +2557,12 @@ static void widget_state(uiWidgetType *wt, int state, int drawflag, eUIEmbossTyp
* even if UI_SELECT. But currently this causes some flickering
* as buttons can be created and updated without respect to mouse
* position and so can draw without UI_ACTIVE set. See D6503. */
- if (state & UI_ACTIVE) {
+ if (state->but_flag & UI_ACTIVE) {
widget_active_color(&wt->wcol);
}
}
- if (state & UI_BUT_REDALERT) {
+ if (state->but_flag & UI_BUT_REDALERT) {
const uchar red[4] = {255, 0, 0};
if (wt->draw && emboss != UI_EMBOSS_NONE) {
color_blend_v3_v3(wt->wcol.inner, red, 0.4f);
@@ -2559,14 +2572,14 @@ static void widget_state(uiWidgetType *wt, int state, int drawflag, eUIEmbossTyp
}
}
- if (state & UI_BUT_DRAG_MULTI) {
+ if (state->but_flag & UI_BUT_DRAG_MULTI) {
/* the button isn't SELECT but we're editing this so draw with sel color */
copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel);
SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
color_blend_v3_v3(wt->wcol.text, wt->wcol.text_sel, 0.85f);
}
- if (state & UI_BUT_NODE_ACTIVE) {
+ if (state->but_flag & UI_BUT_NODE_ACTIVE) {
const uchar blue[4] = {86, 128, 194};
color_blend_v3_v3(wt->wcol.inner, blue, 0.3f);
}
@@ -2600,14 +2613,16 @@ static float widget_radius_from_rcti(const rcti *rect, const uiWidgetColors *wco
* \{ */
/* sliders use special hack which sets 'item' as inner when drawing filling */
-static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
+static void widget_state_numslider(uiWidgetType *wt,
+ const uiWidgetStateInfo *state,
+ eUIEmbossType emboss)
{
uiWidgetStateColors *wcol_state = wt->wcol_state;
/* call this for option button */
- widget_state(wt, state, drawflag, emboss);
+ widget_state(wt, state, emboss);
- const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, drawflag, emboss);
+ const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, 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,
@@ -2617,15 +2632,14 @@ static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag, eU
color_ensure_contrast_v3(wt->wcol.item, wt->wcol.inner, 30);
}
- if (state & UI_SELECT) {
+ if (state->but_flag & UI_SELECT) {
SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
}
}
/* labels use theme colors for text */
static void widget_state_option_menu(uiWidgetType *wt,
- int state,
- int drawflag,
+ const uiWidgetStateInfo *state,
eUIEmbossType emboss)
{
const bTheme *btheme = UI_GetTheme();
@@ -2638,14 +2652,13 @@ static void widget_state_option_menu(uiWidgetType *wt,
copy_v3_v3_uchar(wcol_menu_option.text_sel, btheme->tui.wcol_menu_back.text_sel);
wt->wcol_theme = &wcol_menu_option;
- widget_state(wt, state, drawflag, emboss);
+ widget_state(wt, state, emboss);
wt->wcol_theme = old_wcol;
}
static void widget_state_nothing(uiWidgetType *wt,
- int UNUSED(state),
- int UNUSED(drawflag),
+ const uiWidgetStateInfo *UNUSED(state),
eUIEmbossType UNUSED(emboss))
{
wt->wcol = *(wt->wcol_theme);
@@ -2653,8 +2666,7 @@ static void widget_state_nothing(uiWidgetType *wt,
/* special case, button that calls pulldown */
static void widget_state_pulldown(uiWidgetType *wt,
- int UNUSED(state),
- int UNUSED(drawflag),
+ const uiWidgetStateInfo *UNUSED(state),
eUIEmbossType UNUSED(emboss))
{
wt->wcol = *(wt->wcol_theme);
@@ -2662,14 +2674,13 @@ static void widget_state_pulldown(uiWidgetType *wt,
/* special case, pie menu items */
static void widget_state_pie_menu_item(uiWidgetType *wt,
- int state,
- int UNUSED(drawflag),
+ const uiWidgetStateInfo *state,
eUIEmbossType UNUSED(emboss))
{
wt->wcol = *(wt->wcol_theme);
/* active and disabled (not so common) */
- if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) {
+ if ((state->but_flag & UI_BUT_DISABLED) && (state->but_flag & UI_ACTIVE)) {
color_blend_v3_v3(wt->wcol.text, wt->wcol.text_sel, 0.5f);
/* draw the backdrop at low alpha, helps navigating with keys
* when disabled items are active */
@@ -2678,18 +2689,18 @@ static void widget_state_pie_menu_item(uiWidgetType *wt,
}
else {
/* regular active */
- if (state & (UI_SELECT | UI_ACTIVE)) {
+ if (state->but_flag & (UI_SELECT | UI_ACTIVE)) {
copy_v3_v3_uchar(wt->wcol.text, wt->wcol.text_sel);
}
- else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ else if (state->but_flag & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
/* regular disabled */
color_blend_v3_v3(wt->wcol.text, wt->wcol.inner, 0.5f);
}
- if (state & UI_SELECT) {
+ if (state->but_flag & UI_SELECT) {
copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel);
}
- else if (state & UI_ACTIVE) {
+ else if (state->but_flag & UI_ACTIVE) {
copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.item);
}
}
@@ -2697,14 +2708,13 @@ static void widget_state_pie_menu_item(uiWidgetType *wt,
/* special case, menu items */
static void widget_state_menu_item(uiWidgetType *wt,
- int state,
- int UNUSED(drawflag),
+ const uiWidgetStateInfo *state,
eUIEmbossType UNUSED(emboss))
{
wt->wcol = *(wt->wcol_theme);
/* active and disabled (not so common) */
- if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) {
+ if ((state->but_flag & UI_BUT_DISABLED) && (state->but_flag & UI_ACTIVE)) {
/* draw the backdrop at low alpha, helps navigating with keys
* when disabled items are active */
wt->wcol.text[3] = 128;
@@ -2713,15 +2723,15 @@ static void widget_state_menu_item(uiWidgetType *wt,
}
else {
/* regular active */
- if (state & UI_ACTIVE) {
+ if (state->but_flag & UI_ACTIVE) {
copy_v3_v3_uchar(wt->wcol.text, wt->wcol.text_sel);
}
- else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ else if (state->but_flag & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
/* regular disabled */
color_blend_v3_v3(wt->wcol.text, wt->wcol.inner, 0.5f);
}
- if (state & UI_ACTIVE) {
+ if (state->but_flag & UI_ACTIVE) {
copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel);
}
}
@@ -2787,7 +2797,7 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r
}
static void widget_menu_back(
- uiWidgetColors *wcol, rcti *rect, int flag, int direction, const float zoom)
+ uiWidgetColors *wcol, rcti *rect, const int block_flag, const int direction, const float zoom)
{
uiWidgetBase wtb;
int roundboxalign = UI_CNR_ALL;
@@ -2795,7 +2805,7 @@ static void widget_menu_back(
widget_init(&wtb);
/* menu is 2nd level or deeper */
- if (flag & UI_BLOCK_POPUP) {
+ if (block_flag & UI_BLOCK_POPUP) {
// rect->ymin -= 4.0;
// rect->ymax += 4.0;
}
@@ -3321,13 +3331,17 @@ static void ui_draw_separator(const rcti *rect, const uiWidgetColors *wcol)
#define NUM_BUT_PADDING_FACTOR 0.425f
-static void widget_numbut_draw(
- uiWidgetColors *wcol, rcti *rect, const float zoom, int state, int roundboxalign, bool emboss)
+static void widget_numbut_draw(uiWidgetColors *wcol,
+ rcti *rect,
+ const float zoom,
+ const uiWidgetStateInfo *state,
+ int roundboxalign,
+ bool emboss)
{
const float rad = widget_radius_from_zoom(zoom, wcol);
const int handle_width = min_ii(BLI_rcti_size_x(rect) / 3, BLI_rcti_size_y(rect) * 0.7f);
- if (state & UI_SELECT) {
+ if (state->but_flag & UI_SELECT) {
SWAP(short, wcol->shadetop, wcol->shadedown);
}
@@ -3343,7 +3357,7 @@ static void widget_numbut_draw(
}
/* decoration */
- if ((state & UI_ACTIVE) && !(state & UI_STATE_TEXT_INPUT)) {
+ if ((state->but_flag & UI_ACTIVE) && !state->is_text_input) {
uiWidgetColors wcol_zone;
uiWidgetBase wtb_zone;
rcti rect_zone;
@@ -3356,7 +3370,7 @@ static void widget_numbut_draw(
wcol_zone = *wcol;
copy_v3_v3_uchar(wcol_zone.item, wcol->text);
- if (state & UI_STATE_ACTIVE_LEFT) {
+ if (state->but_drawflag & UI_BUT_ACTIVE_LEFT) {
widget_active_color(&wcol_zone);
}
@@ -3376,7 +3390,7 @@ static void widget_numbut_draw(
wcol_zone = *wcol;
copy_v3_v3_uchar(wcol_zone.item, wcol->text);
- if (state & UI_STATE_ACTIVE_RIGHT) {
+ if (state->but_drawflag & UI_BUT_ACTIVE_RIGHT) {
widget_active_color(&wcol_zone);
}
@@ -3395,7 +3409,7 @@ static void widget_numbut_draw(
wcol_zone = *wcol;
copy_v3_v3_uchar(wcol_zone.item, wcol->text);
- if (!(state & (UI_STATE_ACTIVE_LEFT | UI_STATE_ACTIVE_RIGHT))) {
+ if (!(state->but_drawflag & (UI_BUT_ACTIVE_LEFT | UI_BUT_ACTIVE_RIGHT))) {
widget_active_color(&wcol_zone);
}
@@ -3414,7 +3428,7 @@ static void widget_numbut_draw(
widgetbase_draw(&wtb, wcol);
}
- if (!(state & UI_STATE_TEXT_INPUT)) {
+ if (!state->is_text_input) {
const float text_padding = NUM_BUT_PADDING_FACTOR * BLI_rcti_size_y(rect);
rect->xmin += text_padding;
@@ -3422,14 +3436,20 @@ static void widget_numbut_draw(
}
}
-static void widget_numbut(
- uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, const float zoom)
+static void widget_numbut(uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *state,
+ int roundboxalign,
+ const float zoom)
{
widget_numbut_draw(wcol, rect, zoom, state, roundboxalign, false);
}
-static void widget_menubut(
- uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign, const float zoom)
+static void widget_menubut(uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *UNUSED(state),
+ int roundboxalign,
+ const float zoom)
{
uiWidgetBase wtb;
widget_init(&wtb);
@@ -3454,7 +3474,7 @@ static void widget_menubut(
static void widget_menubut_embossn(const uiBut *UNUSED(but),
uiWidgetColors *wcol,
rcti *rect,
- int UNUSED(state),
+ const uiWidgetStateInfo *UNUSED(state),
int UNUSED(roundboxalign))
{
uiWidgetBase wtb;
@@ -3476,7 +3496,7 @@ static void widget_menubut_embossn(const uiBut *UNUSED(but),
static void widget_numbut_embossn(const uiBut *UNUSED(but),
uiWidgetColors *wcol,
rcti *rect,
- int state,
+ const uiWidgetStateInfo *state,
int roundboxalign,
const float zoom)
{
@@ -3486,7 +3506,6 @@ static void widget_numbut_embossn(const uiBut *UNUSED(but),
void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *slider, int state)
{
uiWidgetBase wtb;
- bool outline = false;
widget_init(&wtb);
@@ -3531,11 +3550,6 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
/* draw */
wtb.draw_emboss = false; /* only emboss once */
- /* exception for progress bar */
- if (state & UI_SCROLL_NO_OUTLINE) {
- SWAP(bool, outline, wtb.draw_outline);
- }
-
round_box_edges(&wtb, UI_CNR_ALL, slider, rad);
if (state & UI_SCROLL_ARROWS) {
@@ -3563,17 +3577,13 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
}
}
widgetbase_draw(&wtb, wcol);
-
- if (state & UI_SCROLL_NO_OUTLINE) {
- SWAP(bool, outline, wtb.draw_outline);
- }
}
}
static void widget_scroll(uiBut *but,
uiWidgetColors *wcol,
rcti *rect,
- int state,
+ const uiWidgetStateInfo *state,
int UNUSED(roundboxalign),
const float UNUSED(zoom))
{
@@ -3623,19 +3633,13 @@ static void widget_scroll(uiBut *but,
}
}
- if (state & UI_SELECT) {
- state = UI_SCROLL_PRESSED;
- }
- else {
- state = 0;
- }
- UI_draw_widget_scroll(wcol, rect, &rect1, state);
+ UI_draw_widget_scroll(wcol, rect, &rect1, (state->but_flag & UI_SELECT) ? UI_SCROLL_PRESSED : 0);
}
static void widget_progressbar(uiBut *but,
uiWidgetColors *wcol,
rcti *rect,
- int UNUSED(state),
+ const uiWidgetStateInfo *UNUSED(state),
int roundboxalign,
const float zoom)
{
@@ -3669,7 +3673,7 @@ static void widget_progressbar(uiBut *but,
static void widget_treerow_exec(uiWidgetColors *wcol,
rcti *rect,
- int state,
+ const uiWidgetStateInfo *state,
int UNUSED(roundboxalign),
int indentation,
const float zoom)
@@ -3682,7 +3686,7 @@ static void widget_treerow_exec(uiWidgetColors *wcol,
const float rad = widget_radius_from_zoom(zoom, wcol);
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
- if ((state & UI_ACTIVE) || (state & UI_SELECT)) {
+ if ((state->but_flag & UI_ACTIVE) || (state->but_flag & UI_SELECT)) {
widgetbase_draw(&wtb, wcol);
}
@@ -3690,8 +3694,12 @@ static void widget_treerow_exec(uiWidgetColors *wcol,
BLI_rcti_translate(rect, 0.5f * UI_UNIT_X * indentation, 0);
}
-static void widget_treerow(
- uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, const float zoom)
+static void widget_treerow(uiBut *but,
+ uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *state,
+ int roundboxalign,
+ const float zoom)
{
uiButTreeRow *tree_row = (uiButTreeRow *)but;
BLI_assert(but->type == UI_BTYPE_TREEROW);
@@ -3701,7 +3709,7 @@ static void widget_treerow(
static void widget_nodesocket(uiBut *but,
uiWidgetColors *wcol,
rcti *rect,
- int UNUSED(state),
+ const uiWidgetStateInfo *UNUSED(state),
int UNUSED(roundboxalign),
const float UNUSED(zoom))
{
@@ -3737,8 +3745,12 @@ static void widget_nodesocket(uiBut *but,
copy_v3_v3_uchar(wcol->outline, old_outline);
}
-static void widget_numslider(
- uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, const float zoom)
+static void widget_numslider(uiBut *but,
+ uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *state,
+ int roundboxalign,
+ const float zoom)
{
uiWidgetBase wtb, wtb1;
widget_init(&wtb);
@@ -3752,7 +3764,7 @@ static void widget_numslider(
widgetbase_draw(&wtb, wcol);
/* Draw slider part only when not in text editing. */
- if (!(state & UI_STATE_TEXT_INPUT)) {
+ if (!state->is_text_input) {
int roundboxalign_slider = roundboxalign;
uchar outline[3];
@@ -3760,7 +3772,7 @@ static void widget_numslider(
copy_v3_v3_uchar(wcol->outline, wcol->item);
copy_v3_v3_uchar(wcol->inner, wcol->item);
- if (!(state & UI_SELECT)) {
+ if (!(state->but_flag & UI_SELECT)) {
SWAP(short, wcol->shadetop, wcol->shadedown);
}
@@ -3828,7 +3840,7 @@ static void widget_numslider(
copy_v3_v3_uchar(wcol->outline, outline);
- if (!(state & UI_SELECT)) {
+ if (!(state->but_flag & UI_SELECT)) {
SWAP(short, wcol->shadetop, wcol->shadedown);
}
}
@@ -3840,7 +3852,7 @@ static void widget_numslider(
/* Add space at either side of the button so text aligns with number-buttons
* (which have arrow icons). */
- if (!(state & UI_STATE_TEXT_INPUT)) {
+ if (!state->is_text_input) {
const float text_padding = NUM_BUT_PADDING_FACTOR * BLI_rcti_size_y(rect);
rect->xmax -= text_padding;
rect->xmin += text_padding;
@@ -3850,8 +3862,12 @@ static void widget_numslider(
/* I think 3 is sufficient border to indicate keyed status */
#define SWATCH_KEYED_BORDER 3
-static void widget_swatch(
- uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, const float zoom)
+static void widget_swatch(uiBut *but,
+ uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *state,
+ int roundboxalign,
+ const float zoom)
{
BLI_assert(but->type == UI_BTYPE_COLOR);
uiButColor *color_but = (uiButColor *)but;
@@ -3875,9 +3891,9 @@ static void widget_swatch(
ui_but_v3_get(but, col);
- if ((state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_OVERRIDDEN |
- UI_BUT_REDALERT)) ||
- (but->drawflag & UI_BUT_ANIMATED_CHANGED)) {
+ if ((state->but_flag & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN |
+ UI_BUT_OVERRIDDEN | UI_BUT_REDALERT)) ||
+ (state->but_drawflag & UI_BUT_ANIMATED_CHANGED)) {
/* draw based on state - color for keyed etc */
widgetbase_draw(&wtb, wcol);
@@ -3938,7 +3954,7 @@ static void widget_swatch(
static void widget_unitvec(uiBut *but,
uiWidgetColors *wcol,
rcti *rect,
- int UNUSED(state),
+ const uiWidgetStateInfo *UNUSED(state),
int UNUSED(roundboxalign),
const float zoom)
{
@@ -3946,10 +3962,15 @@ static void widget_unitvec(uiBut *but,
ui_draw_but_UNITVEC(but, wcol, rect, rad);
}
-static void widget_icon_has_anim(
- uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, const float zoom)
+static void widget_icon_has_anim(uiBut *but,
+ uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *state,
+ int roundboxalign,
+ const float zoom)
{
- if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT) &&
+ if (state->but_flag &
+ (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT) &&
but->emboss != UI_EMBOSS_NONE) {
uiWidgetBase wtb;
widget_init(&wtb);
@@ -3970,10 +3991,13 @@ static void widget_icon_has_anim(
}
}
-static void widget_textbut(
- uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, const float zoom)
+static void widget_textbut(uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *state,
+ int roundboxalign,
+ const float zoom)
{
- if (state & UI_SELECT) {
+ if (state->but_flag & UI_SELECT) {
SWAP(short, wcol->shadetop, wcol->shadedown);
}
@@ -3989,7 +4013,7 @@ static void widget_textbut(
static void widget_preview_tile(uiBut *but,
uiWidgetColors *wcol,
rcti *rect,
- int UNUSED(state),
+ const uiWidgetStateInfo *UNUSED(state),
int UNUSED(roundboxalign),
const float UNUSED(zoom))
{
@@ -3998,8 +4022,11 @@ static void widget_preview_tile(uiBut *but,
&style->widget, rect, but->drawstr, but->icon, wcol->text, UI_STYLE_TEXT_CENTER);
}
-static void widget_menuiconbut(
- uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign, const float zoom)
+static void widget_menuiconbut(uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *UNUSED(state),
+ int roundboxalign,
+ const float zoom)
{
uiWidgetBase wtb;
widget_init(&wtb);
@@ -4011,17 +4038,20 @@ static void widget_menuiconbut(
widgetbase_draw(&wtb, wcol);
}
-static void widget_pulldownbut(
- uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, const float zoom)
+static void widget_pulldownbut(uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *state,
+ int roundboxalign,
+ const float zoom)
{
float back[4];
UI_GetThemeColor4fv(TH_BACK, back);
- if ((state & UI_ACTIVE) || (back[3] < 1.0f)) {
+ if ((state->but_flag & UI_ACTIVE) || (back[3] < 1.0f)) {
uiWidgetBase wtb;
const float rad = widget_radius_from_zoom(zoom, wcol);
- if (state & UI_ACTIVE) {
+ if (state->but_flag & UI_ACTIVE) {
copy_v4_v4_uchar(wcol->inner, wcol->inner_sel);
copy_v3_v3_uchar(wcol->text, wcol->text_sel);
copy_v3_v3_uchar(wcol->outline, wcol->inner);
@@ -4042,7 +4072,7 @@ static void widget_pulldownbut(
static void widget_menu_itembut(uiWidgetColors *wcol,
rcti *rect,
- int UNUSED(state),
+ const uiWidgetStateInfo *UNUSED(state),
int UNUSED(roundboxalign),
const float zoom)
{
@@ -4066,7 +4096,7 @@ static void widget_menu_itembut(uiWidgetColors *wcol,
static void widget_menu_itembut_unpadded(uiWidgetColors *wcol,
rcti *rect,
- int UNUSED(state),
+ const uiWidgetStateInfo *UNUSED(state),
int UNUSED(roundboxalign),
const float zoom)
{
@@ -4088,7 +4118,7 @@ static void widget_menu_itembut_unpadded(uiWidgetColors *wcol,
static void widget_menu_radial_itembut(uiBut *but,
uiWidgetColors *wcol,
rcti *rect,
- int UNUSED(state),
+ const uiWidgetStateInfo *UNUSED(state),
int UNUSED(roundboxalign),
const float zoom)
{
@@ -4114,7 +4144,7 @@ static void widget_menu_radial_itembut(uiBut *but,
static void widget_list_itembut(uiWidgetColors *wcol,
rcti *rect,
- int UNUSED(state),
+ const uiWidgetStateInfo *UNUSED(state),
int UNUSED(roundboxalign),
const float zoom)
{
@@ -4131,11 +4161,13 @@ static void widget_list_itembut(uiWidgetColors *wcol,
static void widget_optionbut(uiWidgetColors *wcol,
rcti *rect,
- int state,
+ const uiWidgetStateInfo *state,
int UNUSED(roundboxalign),
const float UNUSED(zoom))
{
- const bool text_before_widget = (state & UI_STATE_TEXT_BEFORE_WIDGET);
+ /* For a right aligned layout (signified by #UI_BUT_TEXT_RIGHT), draw the text on the left of the
+ * checkbox. */
+ const bool text_before_widget = (state->but_drawflag & UI_BUT_TEXT_RIGHT);
rcti recttemp = *rect;
uiWidgetBase wtb;
@@ -4160,7 +4192,7 @@ static void widget_optionbut(uiWidgetColors *wcol,
round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad);
/* decoration */
- if (state & UI_SELECT) {
+ if (state->but_flag & UI_SELECT) {
shape_preset_trias_from_rect_checkmark(&wtb.tria1, &recttemp);
}
@@ -4177,19 +4209,21 @@ static void widget_optionbut(uiWidgetColors *wcol,
}
/* labels use Editor theme colors for text */
-static void widget_state_label(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss)
+static void widget_state_label(uiWidgetType *wt,
+ const uiWidgetStateInfo *state,
+ eUIEmbossType emboss)
{
- if (state & UI_BUT_LIST_ITEM) {
+ if (state->but_flag & UI_BUT_LIST_ITEM) {
/* Override default label theme's colors. */
bTheme *btheme = UI_GetTheme();
wt->wcol_theme = &btheme->tui.wcol_list_item;
/* call this for option button */
- widget_state(wt, state, drawflag, emboss);
+ widget_state(wt, state, emboss);
}
else {
/* call this for option button */
- widget_state(wt, state, drawflag, emboss);
- if (state & UI_SELECT) {
+ widget_state(wt, state, emboss);
+ if (state->but_flag & UI_SELECT) {
UI_GetThemeColor3ubv(TH_TEXT_HI, wt->wcol.text);
}
else {
@@ -4197,14 +4231,17 @@ static void widget_state_label(uiWidgetType *wt, int state, int drawflag, eUIEmb
}
}
- if (state & UI_BUT_REDALERT) {
+ if (state->but_flag & UI_BUT_REDALERT) {
const uchar red[4] = {255, 0, 0};
color_blend_v3_v3(wt->wcol.text, red, 0.4f);
}
}
-static void widget_radiobut(
- uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign, const float zoom)
+static void widget_radiobut(uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *UNUSED(state),
+ int roundboxalign,
+ const float zoom)
{
uiWidgetBase wtb;
widget_init(&wtb);
@@ -4218,7 +4255,7 @@ static void widget_radiobut(
static void widget_box(uiBut *but,
uiWidgetColors *wcol,
rcti *rect,
- int UNUSED(state),
+ const uiWidgetStateInfo *UNUSED(state),
int roundboxalign,
const float zoom)
{
@@ -4244,8 +4281,11 @@ static void widget_box(uiBut *but,
copy_v3_v3_uchar(wcol->inner, old_col);
}
-static void widget_but(
- uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign, const float zoom)
+static void widget_but(uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *UNUSED(state),
+ int roundboxalign,
+ const float zoom)
{
uiWidgetBase wtb;
widget_init(&wtb);
@@ -4271,13 +4311,16 @@ static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
}
#endif
-static void widget_roundbut_exec(
- uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, const float zoom)
+static void widget_roundbut_exec(uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *state,
+ int roundboxalign,
+ const float zoom)
{
uiWidgetBase wtb;
widget_init(&wtb);
- if (state & UI_STATE_HOLD_ACTION) {
+ if (state->has_hold_action) {
/* Show that keeping pressed performs another action (typically a menu). */
shape_preset_init_hold_action(&wtb.tria1, rect, 0.75f, 'r');
}
@@ -4290,11 +4333,14 @@ static void widget_roundbut_exec(
widgetbase_draw(&wtb, wcol);
}
-static void widget_tab(
- uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, const float zoom)
+static void widget_tab(uiWidgetColors *wcol,
+ rcti *rect,
+ const uiWidgetStateInfo *state,
+ int roundboxalign,
+ const float zoom)
{
const float rad = widget_radius_from_zoom(zoom, wcol);
- const bool is_active = (state & UI_SELECT);
+ const bool is_active = (state->but_flag & UI_SELECT);
/* Draw shaded outline - Disabled for now,
* seems incorrect and also looks nicer without it IMHO ;). */
@@ -4442,7 +4488,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
case UI_WTYPE_TOOLTIP:
wt.wcol_theme = &btheme->tui.wcol_tooltip;
- wt.draw = widget_menu_back;
+ wt.draw_block = widget_menu_back;
break;
/* strings */
@@ -4498,7 +4544,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
case UI_WTYPE_MENU_BACK:
wt.wcol_theme = &btheme->tui.wcol_menu_back;
- wt.draw = widget_menu_back;
+ wt.draw_block = widget_menu_back;
break;
/* specials */
@@ -4921,62 +4967,50 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu
const int roundboxalign = widget_roundbox_set(but, rect);
- /* Mask out flags re-used for local state. */
- int state = but->flag & ~UI_STATE_FLAGS_ALL;
- const int drawflag = but->drawflag;
+ uiWidgetStateInfo state = {0};
+ state.but_flag = but->flag;
+ state.but_drawflag = but->drawflag;
- if (state & UI_SELECT_DRAW) {
- state |= UI_SELECT;
+ /* Override selected flag for drawing. */
+ if (but->flag & UI_SELECT_DRAW) {
+ state.but_flag |= UI_SELECT;
}
if ((but->editstr) ||
(UNLIKELY(but->flag & UI_BUT_DRAG_MULTI) && ui_but_drag_multi_edit_get(but))) {
- state |= UI_STATE_TEXT_INPUT;
+ state.is_text_input = true;
}
if (but->hold_func) {
- state |= UI_STATE_HOLD_ACTION;
- }
-
- if (state & UI_ACTIVE) {
- if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
- state |= UI_STATE_ACTIVE_LEFT;
- }
- else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
- state |= UI_STATE_ACTIVE_RIGHT;
- }
+ state.has_hold_action = true;
}
bool use_alpha_blend = false;
if (but->emboss != UI_EMBOSS_PULLDOWN) {
- if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_SEARCH_FILTER_NO_MATCH)) {
+ if (but->flag & (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_SEARCH_FILTER_NO_MATCH)) {
use_alpha_blend = true;
- ui_widget_color_disabled(wt, state);
+ ui_widget_color_disabled(wt, &state);
}
}
- if (drawflag & UI_BUT_TEXT_RIGHT) {
- state |= UI_STATE_TEXT_BEFORE_WIDGET;
- }
-
#ifdef USE_UI_POPOVER_ONCE
if (but->block->flag & UI_BLOCK_POPOVER_ONCE) {
- if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
- state |= UI_BUT_ACTIVE_DEFAULT;
+ if ((but->flag & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
+ state.but_flag |= UI_BUT_ACTIVE_DEFAULT;
}
}
#endif
if (but->block->flag & UI_BLOCK_NO_DRAW_OVERRIDDEN_STATE) {
- state &= ~UI_BUT_OVERRIDDEN;
+ state.but_flag &= ~UI_BUT_OVERRIDDEN;
}
const float zoom = 1.0f / but->block->aspect;
- wt->state(wt, state, drawflag, but->emboss);
+ wt->state(wt, &state, but->emboss);
if (wt->custom) {
- wt->custom(but, &wt->wcol, rect, state, roundboxalign, zoom);
+ wt->custom(but, &wt->wcol, rect, &state, roundboxalign, zoom);
}
else if (wt->draw) {
- wt->draw(&wt->wcol, rect, state, roundboxalign, zoom);
+ wt->draw(&wt->wcol, rect, &state, roundboxalign, zoom);
}
if (wt->text) {
@@ -5017,13 +5051,13 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
{
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
- wt->state(wt, 0, 0, UI_EMBOSS_UNDEFINED);
+ wt->state(wt, &STATE_INFO_NULL, UI_EMBOSS_UNDEFINED);
if (block) {
const float zoom = 1.0f / block->aspect;
- wt->draw(&wt->wcol, rect, block->flag, block->direction, zoom);
+ wt->draw_block(&wt->wcol, rect, block->flag, block->direction, zoom);
}
else {
- wt->draw(&wt->wcol, rect, 0, 0, 1.0f);
+ wt->draw_block(&wt->wcol, rect, 0, 0, 1.0f);
}
ui_draw_clip_tri(block, rect, wt);
@@ -5118,8 +5152,8 @@ void ui_draw_popover_back(struct ARegion *region,
}
else {
const float zoom = 1.0f / block->aspect;
- wt->state(wt, 0, 0, UI_EMBOSS_UNDEFINED);
- wt->draw(&wt->wcol, rect, 0, 0, zoom);
+ wt->state(wt, &STATE_INFO_NULL, UI_EMBOSS_UNDEFINED);
+ wt->draw_block(&wt->wcol, rect, 0, 0, zoom);
}
ui_draw_clip_tri(block, rect, wt);
@@ -5307,11 +5341,20 @@ static void ui_draw_widget_back_color(uiWidgetTypeEnum type,
}
rcti rect_copy = *rect;
- wt->state(wt, 0, 0, UI_EMBOSS_UNDEFINED);
+ wt->state(wt, &STATE_INFO_NULL, UI_EMBOSS_UNDEFINED);
if (color) {
rgba_float_to_uchar(wt->wcol.inner, color);
}
- wt->draw(&wt->wcol, &rect_copy, 0, UI_CNR_ALL, 1.0f);
+
+ if (wt->draw_block) {
+ wt->draw_block(&wt->wcol, &rect_copy, 0, UI_CNR_ALL, 1.0f);
+ }
+ else if (wt->draw) {
+ wt->draw(&wt->wcol, &rect_copy, &STATE_INFO_NULL, UI_CNR_ALL, 1.0f);
+ }
+ else {
+ BLI_assert_unreachable();
+ }
}
void ui_draw_widget_menu_back_color(const rcti *rect, bool use_shadow, const float color[4])
{
@@ -5326,16 +5369,16 @@ void ui_draw_widget_menu_back(const rcti *rect, bool use_shadow)
void ui_draw_tooltip_background(const uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect)
{
uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
- wt->state(wt, 0, 0, UI_EMBOSS_UNDEFINED);
- /* wt->draw ends up using same function to draw the tooltip as menu_back */
- wt->draw(&wt->wcol, rect, 0, 0, 1.0f);
+ wt->state(wt, &STATE_INFO_NULL, UI_EMBOSS_UNDEFINED);
+ /* wt->draw_block ends up using same function to draw the tooltip as menu_back */
+ wt->draw_block(&wt->wcol, rect, 0, 0, 1.0f);
}
void ui_draw_menu_item(const uiFontStyle *fstyle,
rcti *rect,
const char *name,
int iconid,
- int state,
+ int but_flag,
uiMenuItemSeparatorType separator_type,
int *r_xmax)
{
@@ -5346,8 +5389,11 @@ void ui_draw_menu_item(const uiFontStyle *fstyle,
int padding = 0.25f * row_height;
char *cpoin = NULL;
- wt->state(wt, state, 0, UI_EMBOSS_UNDEFINED);
- wt->draw(&wt->wcol, rect, 0, 0, 1.0f);
+ uiWidgetStateInfo state = {0};
+ state.but_flag = but_flag;
+
+ wt->state(wt, &state, UI_EMBOSS_UNDEFINED);
+ wt->draw(&wt->wcol, rect, &STATE_INFO_NULL, 0, 1.0f);
UI_fontstyle_set(fstyle);
@@ -5442,8 +5488,12 @@ void ui_draw_menu_item(const uiFontStyle *fstyle,
/* part text right aligned */
if (separator_type != UI_MENU_ITEM_SEPARATOR_NONE) {
if (cpoin) {
+ /* State info for the hint drawing. */
+ uiWidgetStateInfo hint_state = state;
/* Set inactive state for grayed out text. */
- wt->state(wt, state | UI_BUT_INACTIVE, 0, UI_EMBOSS_UNDEFINED);
+ hint_state.but_flag |= UI_BUT_INACTIVE;
+
+ wt->state(wt, &hint_state, UI_EMBOSS_UNDEFINED);
char hint_drawstr[UI_MAX_DRAW_STR];
{
@@ -5528,14 +5578,17 @@ void ui_draw_preview_item(const uiFontStyle *fstyle,
rcti *rect,
const char *name,
int iconid,
- int state,
+ int but_flag,
eFontStyle_Align text_align)
{
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM_UNPADDED);
+ uiWidgetStateInfo state = {0};
+ state.but_flag = but_flag;
+
/* drawing button background */
- wt->state(wt, state, 0, UI_EMBOSS_UNDEFINED);
- wt->draw(&wt->wcol, rect, 0, 0, 1.0f);
+ wt->state(wt, &state, UI_EMBOSS_UNDEFINED);
+ wt->draw(&wt->wcol, rect, &STATE_INFO_NULL, 0, 1.0f);
ui_draw_preview_item_stateless(fstyle, rect, name, iconid, wt->wcol.text, text_align);
}
diff --git a/source/blender/editors/interface/view2d_gizmo_navigate.cc b/source/blender/editors/interface/view2d_gizmo_navigate.cc
index 01729e35246..fae28833e4f 100644
--- a/source/blender/editors/interface/view2d_gizmo_navigate.cc
+++ b/source/blender/editors/interface/view2d_gizmo_navigate.cc
@@ -130,6 +130,13 @@ static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *UNUSE
}
break;
}
+ case SPACE_IMAGE: {
+ const SpaceImage *sima = static_cast<const SpaceImage *>(area->spacedata.first);
+ if (sima->gizmo_flag & (SI_GIZMO_HIDE | SI_GIZMO_HIDE_NAVIGATE)) {
+ return false;
+ }
+ break;
+ }
}
return true;
}
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index fd454083653..87923d9fdf8 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -282,6 +282,7 @@ void WM_OT_alembic_export(wmOperatorType *ot)
ot->poll = WM_operator_winactive;
ot->ui = wm_alembic_export_draw;
ot->check = wm_alembic_export_check;
+ ot->flag |= OPTYPE_PRESET;
WM_operator_properties_filesel(ot,
FILE_TYPE_FOLDER | FILE_TYPE_ALEMBIC,
@@ -475,7 +476,7 @@ void WM_OT_alembic_export(wmOperatorType *ot)
/* This dummy prop is used to check whether we need to init the start and
* end frame values to that of the scene's, otherwise they are reset at
* every change, draw update. */
- RNA_def_boolean(ot->srna, "init_scene_frame_range", false, "", "");
+ RNA_def_boolean(ot->srna, "init_scene_frame_range", true, "", "");
}
/* ************************************************************************** */
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index 624b85358f5..969049313c9 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -75,17 +75,17 @@ static void open_cancel(bContext *UNUSED(C), wmOperator *op)
static int cachefile_open_exec(bContext *C, wmOperator *op)
{
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
- BKE_report(op->reports, RPT_ERROR, "No filename given");
+ BKE_report(op->reports, RPT_ERROR, "No filepath given");
return OPERATOR_CANCELLED;
}
- char filename[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", filename);
+ char filepath[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filepath);
Main *bmain = CTX_data_main(C);
- CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filename), 0);
- BLI_strncpy(cache_file->filepath, filename, FILE_MAX);
+ CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filepath), 0);
+ BLI_strncpy(cache_file->filepath, filepath, FILE_MAX);
DEG_id_tag_update(&cache_file->id, ID_RECALC_COPY_ON_WRITE);
/* Will be set when running invoke, not exec directly. */
@@ -182,7 +182,7 @@ static int cachefile_layer_open_invoke(bContext *C, wmOperator *op, const wmEven
static int cachefile_layer_add_exec(bContext *C, wmOperator *op)
{
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
- BKE_report(op->reports, RPT_ERROR, "No filename given");
+ BKE_report(op->reports, RPT_ERROR, "No filepath given");
return OPERATOR_CANCELLED;
}
@@ -192,10 +192,10 @@ static int cachefile_layer_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- char filename[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", filename);
+ char filepath[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filepath);
- CacheFileLayer *layer = BKE_cachefile_add_layer(cache_file, filename);
+ CacheFileLayer *layer = BKE_cachefile_add_layer(cache_file, filepath);
if (!layer) {
WM_report(RPT_ERROR, "Could not add a layer to the cache file");
diff --git a/source/blender/editors/io/io_usd.c b/source/blender/editors/io/io_usd.c
index ca9c2de63a4..609230eefea 100644
--- a/source/blender/editors/io/io_usd.c
+++ b/source/blender/editors/io/io_usd.c
@@ -118,7 +118,7 @@ static int wm_usd_export_exec(bContext *C, wmOperator *op)
const bool generate_preview_surface = RNA_boolean_get(op->ptr, "generate_preview_surface");
const bool export_textures = RNA_boolean_get(op->ptr, "export_textures");
const bool overwrite_textures = RNA_boolean_get(op->ptr, "overwrite_textures");
- const bool relative_texture_paths = RNA_boolean_get(op->ptr, "relative_texture_paths");
+ const bool relative_paths = RNA_boolean_get(op->ptr, "relative_paths");
struct USDExportParams params = {
export_animation,
@@ -133,7 +133,7 @@ static int wm_usd_export_exec(bContext *C, wmOperator *op)
generate_preview_surface,
export_textures,
overwrite_textures,
- relative_texture_paths,
+ relative_paths,
};
bool ok = USD_export(C, filename, &params, as_background_job);
@@ -181,9 +181,9 @@ static void wm_usd_export_draw(bContext *UNUSED(C), wmOperator *op)
const bool export_tex = RNA_boolean_get(ptr, "export_textures");
uiLayoutSetActive(row, export_mtl && preview && export_tex);
- row = uiLayoutRow(col, true);
- uiItemR(row, ptr, "relative_texture_paths", 0, NULL, ICON_NONE);
- uiLayoutSetActive(row, export_mtl && preview);
+ box = uiLayoutBox(layout);
+ col = uiLayoutColumnWithHeading(box, true, IFACE_("File References"));
+ uiItemR(col, ptr, "relative_paths", 0, NULL, ICON_NONE);
box = uiLayoutBox(layout);
uiItemL(box, IFACE_("Experimental"), ICON_NONE);
@@ -297,10 +297,11 @@ void WM_OT_usd_export(struct wmOperatorType *ot)
"Allow overwriting existing texture files when exporting textures");
RNA_def_boolean(ot->srna,
- "relative_texture_paths",
+ "relative_paths",
true,
- "Relative Texture Paths",
- "Make texture asset paths relative to the USD file");
+ "Relative Paths",
+ "Use relative paths to reference external files (i.e. textures, volumes) in "
+ "USD, otherwise use absolute paths");
}
/* ====== USD Import ====== */
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index 0b9261eac4f..d10c420e28c 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -230,7 +230,7 @@ static bool add_vertex_subdivide(const bContext *C, Mask *mask, const float co[2
MaskLayer *mask_layer;
MaskSpline *spline;
MaskSplinePoint *point = NULL;
- const float threshold = 9;
+ const float threshold = 12;
float tangent[2];
float u;
@@ -593,7 +593,7 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op)
MaskLayer *mask_layer;
MaskSpline *spline;
MaskSplinePoint *point = NULL;
- const float threshold = 9;
+ const float threshold = 12;
float co[2], u;
RNA_float_get_array(op->ptr, "location", co);
diff --git a/source/blender/editors/mask/mask_query.c b/source/blender/editors/mask/mask_query.c
index afe457a8502..89524a7b9e2 100644
--- a/source/blender/editors/mask/mask_query.c
+++ b/source/blender/editors/mask/mask_query.c
@@ -45,6 +45,8 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
float *r_u,
float *r_score)
{
+ const float threshold_sq = threshold * threshold;
+
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
@@ -139,7 +141,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
}
}
- if (point && dist_best_sq < threshold) {
+ if (point && dist_best_sq < threshold_sq) {
if (r_mask_layer) {
*r_mask_layer = point_mask_layer;
}
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index ed09e5a6334..28ac913a3e3 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -24,7 +24,7 @@ set(INC
)
set(SRC
- editface.c
+ editface.cc
editmesh_add.c
editmesh_add_gizmo.c
editmesh_automerge.c
@@ -51,10 +51,10 @@ set(SRC
editmesh_tools.c
editmesh_undo.c
editmesh_utils.c
- mesh_data.c
+ mesh_data.cc
mesh_mirror.c
mesh_ops.c
- meshtools.c
+ meshtools.cc
mesh_intern.h
)
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.cc
index a5c6adaa43e..cb5d48d1023 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.cc
@@ -36,16 +36,16 @@
/* own include */
-void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
+void paintface_flush_flags(bContext *C, Object *ob, short flag)
{
Mesh *me = BKE_mesh_from_object(ob);
MPoly *polys, *mp_orig;
- const int *index_array = NULL;
+ const int *index_array = nullptr;
int totpoly;
BLI_assert((flag & ~(SELECT | ME_HIDE)) == 0);
- if (me == NULL) {
+ if (me == nullptr) {
return;
}
@@ -60,7 +60,7 @@ void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- if (ob_eval == NULL) {
+ if (ob_eval == nullptr) {
return;
}
@@ -68,7 +68,7 @@ void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
Mesh *me_eval = (Mesh *)ob_eval->runtime.data_eval;
bool updated = false;
- if (me_orig != NULL && me_eval != NULL && me_orig->totpoly == me->totpoly) {
+ if (me_orig != nullptr && me_eval != nullptr && me_orig->totpoly == me->totpoly) {
/* Update the COW copy of the mesh. */
for (int i = 0; i < me->totpoly; i++) {
me_orig->mpoly[i].flag = me->mpoly[i].flag;
@@ -79,7 +79,7 @@ void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
updated = true;
}
/* Mesh polys => Final derived polys */
- else if ((index_array = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
+ else if ((index_array = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
polys = me_eval->mpoly;
totpoly = me_eval->totpoly;
@@ -104,10 +104,10 @@ void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
BKE_mesh_batch_cache_dirty_tag(me_eval, BKE_MESH_BATCH_DIRTY_SELECT_PAINT);
}
- DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
+ DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_SELECT);
}
else {
- DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
}
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
@@ -115,18 +115,13 @@ void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
void paintface_hide(bContext *C, Object *ob, const bool unselected)
{
- Mesh *me;
- MPoly *mpoly;
- int a;
-
- me = BKE_mesh_from_object(ob);
- if (me == NULL || me->totpoly == 0) {
+ Mesh *me = BKE_mesh_from_object(ob);
+ if (me == nullptr || me->totpoly == 0) {
return;
}
- mpoly = me->mpoly;
- a = me->totpoly;
- while (a--) {
+ for (int i = 0; i < me->totpoly; i++) {
+ MPoly *mpoly = &me->mpoly[i];
if ((mpoly->flag & ME_HIDE) == 0) {
if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) {
mpoly->flag |= ME_HIDE;
@@ -136,8 +131,6 @@ void paintface_hide(bContext *C, Object *ob, const bool unselected)
if (mpoly->flag & ME_HIDE) {
mpoly->flag &= ~ME_FACE_SEL;
}
-
- mpoly++;
}
BKE_mesh_flush_hidden_from_polys(me);
@@ -147,23 +140,17 @@ void paintface_hide(bContext *C, Object *ob, const bool unselected)
void paintface_reveal(bContext *C, Object *ob, const bool select)
{
- Mesh *me;
- MPoly *mpoly;
- int a;
-
- me = BKE_mesh_from_object(ob);
- if (me == NULL || me->totpoly == 0) {
+ Mesh *me = BKE_mesh_from_object(ob);
+ if (me == nullptr || me->totpoly == 0) {
return;
}
- mpoly = me->mpoly;
- a = me->totpoly;
- while (a--) {
+ for (int i = 0; i < me->totpoly; i++) {
+ MPoly *mpoly = &me->mpoly[i];
if (mpoly->flag & ME_HIDE) {
SET_FLAG_FROM_TEST(mpoly->flag, select, ME_FACE_SEL);
mpoly->flag &= ~ME_HIDE;
}
- mpoly++;
}
BKE_mesh_flush_hidden_from_polys(me);
@@ -175,9 +162,6 @@ void paintface_reveal(bContext *C, Object *ob, const bool select)
static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bool select)
{
- MPoly *mp;
- MLoop *ml;
- int a, b;
bool do_it = true;
bool mark = false;
@@ -186,20 +170,20 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
if (index != (uint)-1) {
/* only put face under cursor in array */
- mp = &me->mpoly[index];
+ MPoly *mp = &me->mpoly[index];
BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
BLI_BITMAP_ENABLE(poly_tag, index);
}
else {
/* fill array by selection */
- mp = me->mpoly;
- for (a = 0; a < me->totpoly; a++, mp++) {
+ for (int i = 0; i < me->totpoly; i++) {
+ MPoly *mp = &me->mpoly[i];
if (mp->flag & ME_HIDE) {
/* pass */
}
else if (mp->flag & ME_FACE_SEL) {
BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
- BLI_BITMAP_ENABLE(poly_tag, a);
+ BLI_BITMAP_ENABLE(poly_tag, i);
}
}
}
@@ -208,17 +192,17 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
do_it = false;
/* expand selection */
- mp = me->mpoly;
- for (a = 0; a < me->totpoly; a++, mp++) {
+ for (int i = 0; i < me->totpoly; i++) {
+ MPoly *mp = &me->mpoly[i];
if (mp->flag & ME_HIDE) {
continue;
}
- if (!BLI_BITMAP_TEST(poly_tag, a)) {
+ if (!BLI_BITMAP_TEST(poly_tag, i)) {
mark = false;
- ml = me->mloop + mp->loopstart;
- for (b = 0; b < mp->totloop; b++, ml++) {
+ MLoop *ml = me->mloop + mp->loopstart;
+ for (int b = 0; b < mp->totloop; b++, ml++) {
if ((me->medge[ml->e].flag & ME_SEAM) == 0) {
if (BLI_BITMAP_TEST(edge_tag, ml->e)) {
mark = true;
@@ -228,7 +212,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
}
if (mark) {
- BLI_BITMAP_ENABLE(poly_tag, a);
+ BLI_BITMAP_ENABLE(poly_tag, i);
BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
do_it = true;
}
@@ -238,8 +222,9 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
MEM_freeN(edge_tag);
- for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++) {
- if (BLI_BITMAP_TEST(poly_tag, a)) {
+ for (int i = 0; i < me->totpoly; i++) {
+ MPoly *mp = &me->mpoly[i];
+ if (BLI_BITMAP_TEST(poly_tag, i)) {
SET_FLAG_FROM_TEST(mp->flag, select, ME_FACE_SEL);
}
}
@@ -249,11 +234,10 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const bool select)
{
- Mesh *me;
uint index = (uint)-1;
- me = BKE_mesh_from_object(ob);
- if (me == NULL || me->totpoly == 0) {
+ Mesh *me = BKE_mesh_from_object(ob);
+ if (me == nullptr || me->totpoly == 0) {
return;
}
@@ -270,34 +254,27 @@ void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const b
bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags)
{
- Mesh *me;
- MPoly *mpoly;
- int a;
-
- me = BKE_mesh_from_object(ob);
- if (me == NULL) {
+ Mesh *me = BKE_mesh_from_object(ob);
+ if (me == nullptr) {
return false;
}
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
- mpoly = me->mpoly;
- a = me->totpoly;
- while (a--) {
+ for (int i = 0; i < me->totpoly; i++) {
+ MPoly *mpoly = &me->mpoly[i];
if ((mpoly->flag & ME_HIDE) == 0 && mpoly->flag & ME_FACE_SEL) {
action = SEL_DESELECT;
break;
}
- mpoly++;
}
}
bool changed = false;
- mpoly = me->mpoly;
- a = me->totpoly;
- while (a--) {
+ for (int i = 0; i < me->totpoly; i++) {
+ MPoly *mpoly = &me->mpoly[i];
if ((mpoly->flag & ME_HIDE) == 0) {
switch (action) {
case SEL_SELECT:
@@ -318,7 +295,6 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
break;
}
}
- mpoly++;
}
if (changed) {
@@ -331,30 +307,25 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
{
- const Mesh *me;
- const MPoly *mp;
- const MLoop *ml;
- const MVert *mvert;
- int a, b;
bool ok = false;
float vec[3], bmat[3][3];
- me = BKE_mesh_from_object(ob);
+ const Mesh *me = BKE_mesh_from_object(ob);
if (!me || !me->mloopuv) {
return ok;
}
+ const MVert *mvert = me->mvert;
copy_m3_m4(bmat, ob->obmat);
- mvert = me->mvert;
- mp = me->mpoly;
- for (a = me->totpoly; a > 0; a--, mp++) {
+ for (int i = 0; i < me->totpoly; i++) {
+ MPoly *mp = &me->mpoly[i];
if (mp->flag & ME_HIDE || !(mp->flag & ME_FACE_SEL)) {
continue;
}
- ml = me->mloop + mp->loopstart;
- for (b = 0; b < mp->totloop; b++, ml++) {
+ const MLoop *ml = me->mloop + mp->loopstart;
+ for (int b = 0; b < mp->totloop; b++, ml++) {
mul_v3_m3v3(vec, bmat, mvert[ml->v].co);
add_v3_v3v3(vec, vec, ob->obmat[3]);
minmax_v3v3_v3(r_min, r_max, vec);
@@ -366,19 +337,18 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
return ok;
}
-bool paintface_mouse_select(struct bContext *C,
+bool paintface_mouse_select(bContext *C,
const int mval[2],
- const struct SelectPick_Params *params,
+ const SelectPick_Params *params,
Object *ob)
{
- Mesh *me;
- MPoly *mpoly_sel = NULL;
+ MPoly *mpoly_sel = nullptr;
uint index;
bool changed = false;
bool found = false;
/* Get the face under the cursor */
- me = BKE_mesh_from_object(ob);
+ Mesh *me = BKE_mesh_from_object(ob);
if (ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
if (index < me->totpoly) {
@@ -444,11 +414,11 @@ void paintvert_flush_flags(Object *ob)
Mesh *me = BKE_mesh_from_object(ob);
Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
MVert *mvert_eval, *mv;
- const int *index_array = NULL;
+ const int *index_array = nullptr;
int totvert;
int i;
- if (me == NULL) {
+ if (me == nullptr) {
return;
}
@@ -456,11 +426,11 @@ void paintvert_flush_flags(Object *ob)
* since this could become slow for realtime updates (circle-select for eg) */
BKE_mesh_flush_select_from_verts(me);
- if (me_eval == NULL) {
+ if (me_eval == nullptr) {
return;
}
- index_array = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
+ index_array = (const int *)CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
mvert_eval = me_eval->mvert;
totvert = me_eval->totvert;
@@ -485,41 +455,34 @@ void paintvert_flush_flags(Object *ob)
BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_ALL);
}
-void paintvert_tag_select_update(struct bContext *C, struct Object *ob)
+void paintvert_tag_select_update(bContext *C, Object *ob)
{
- DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
}
bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
{
- Mesh *me;
- MVert *mvert;
- int a;
-
- me = BKE_mesh_from_object(ob);
- if (me == NULL) {
+ Mesh *me = BKE_mesh_from_object(ob);
+ if (me == nullptr) {
return false;
}
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
- mvert = me->mvert;
- a = me->totvert;
- while (a--) {
+ for (int i = 0; i < me->totvert; i++) {
+ MVert *mvert = &me->mvert[i];
if ((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) {
action = SEL_DESELECT;
break;
}
- mvert++;
}
}
bool changed = false;
- mvert = me->mvert;
- a = me->totvert;
- while (a--) {
+ for (int i = 0; i < me->totvert; i++) {
+ MVert *mvert = &me->mvert[i];
if ((mvert->flag & ME_HIDE) == 0) {
switch (action) {
case SEL_SELECT:
@@ -540,7 +503,6 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
break;
}
}
- mvert++;
}
if (changed) {
@@ -565,11 +527,8 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
{
Mesh *me = BKE_mesh_from_object(ob);
- MVert *mv;
- MDeformVert *dv;
- int a, tot;
- if (me == NULL || me->dvert == NULL) {
+ if (me == nullptr || me->dvert == nullptr) {
return;
}
@@ -577,12 +536,11 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
}
- dv = me->dvert;
- tot = me->totvert;
-
- for (a = 0, mv = me->mvert; a < tot; a++, mv++, dv++) {
+ for (int i = 0; i < me->totvert; i++) {
+ MVert *mv = &me->mvert[i];
+ MDeformVert *dv = &me->dvert[i];
if ((mv->flag & ME_HIDE) == 0) {
- if (dv->dw == NULL) {
+ if (dv->dw == nullptr) {
/* if null weight then not grouped */
mv->flag |= SELECT;
}
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index b2f33428b21..57e0d04727c 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -113,7 +113,7 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op)
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ ED_mesh_uv_ensure(obedit->data, NULL);
}
if (!EDBM_op_call_and_selectf(
@@ -178,7 +178,7 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op)
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ ED_mesh_uv_ensure(obedit->data, NULL);
}
if (!EDBM_op_call_and_selectf(em,
@@ -252,7 +252,7 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ ED_mesh_uv_ensure(obedit->data, NULL);
}
if (!EDBM_op_call_and_selectf(
@@ -324,7 +324,7 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ ED_mesh_uv_ensure(obedit->data, NULL);
}
if (!EDBM_op_call_and_selectf(em,
@@ -400,7 +400,7 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ ED_mesh_uv_ensure(obedit->data, NULL);
}
if (!EDBM_op_call_and_selectf(em,
@@ -476,7 +476,7 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op)
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ ED_mesh_uv_ensure(obedit->data, NULL);
}
if (!EDBM_op_call_and_selectf(
@@ -553,7 +553,7 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ ED_mesh_uv_ensure(obedit->data, NULL);
}
if (!EDBM_op_call_and_selectf(em,
@@ -614,7 +614,7 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ ED_mesh_uv_ensure(obedit->data, NULL);
}
if (!EDBM_op_call_and_selectf(
@@ -682,7 +682,7 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ ED_mesh_uv_ensure(obedit->data, NULL);
}
if (!EDBM_op_call_and_selectf(
diff --git a/source/blender/editors/mesh/editmesh_add_gizmo.c b/source/blender/editors/mesh/editmesh_add_gizmo.c
index d0f37314661..f5090c0143d 100644
--- a/source/blender/editors/mesh/editmesh_add_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_add_gizmo.c
@@ -328,7 +328,7 @@ static int add_primitive_cube_gizmo_exec(bContext *C, wmOperator *op)
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ ED_mesh_uv_ensure(obedit->data, NULL);
}
if (!EDBM_op_call_and_selectf(em,
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 5d8cf176b87..5de7681a1e6 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -198,7 +198,7 @@ typedef struct KnifeObjectInfo {
* Optionally allocate triangle indices, these are needed for non-interactive knife
* projection as multiple cuts are made without the BVH being updated.
* Using these indices the it's possible to access `cagecos` even if the face has been cut
- * and the loops in `em->looptris` no longer refer to the original triangles, see:
+ * and the loops in `em->looptris` no longer refer to the original triangles, see: T97153.
*/
const int (*tri_indices)[3];
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index c3d5f33705c..c7c7e5cf2f8 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -9,6 +9,7 @@
#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "BLI_alloca.h"
@@ -19,6 +20,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_bvh.h"
#include "BKE_global.h"
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.cc
index d11f0b490c1..67834bf05ce 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.cc
@@ -13,7 +13,7 @@
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
-#include "BLI_alloca.h"
+#include "BLI_array.hh"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -43,10 +43,12 @@
#include "mesh_intern.h" /* own include */
+using blender::Array;
+
static CustomData *mesh_customdata_get_type(Mesh *me, const char htype, int *r_tot)
{
CustomData *data;
- BMesh *bm = (me->edit_mesh) ? me->edit_mesh->bm : NULL;
+ BMesh *bm = (me->edit_mesh) ? me->edit_mesh->bm : nullptr;
int tot;
switch (htype) {
@@ -93,7 +95,7 @@ static CustomData *mesh_customdata_get_type(Mesh *me, const char htype, int *r_t
default:
BLI_assert(0);
tot = 0;
- data = NULL;
+ data = nullptr;
break;
}
@@ -172,7 +174,7 @@ static void mesh_uv_reset_array(float **fuv, const int len)
static void mesh_uv_reset_bmface(BMFace *f, const int cd_loop_uv_offset)
{
- float **fuv = BLI_array_alloca(fuv, f->len);
+ Array<float *, BM_DEFAULT_NGON_STACK_SIZE> fuv(f->len);
BMIter liter;
BMLoop *l;
int i;
@@ -181,21 +183,21 @@ static void mesh_uv_reset_bmface(BMFace *f, const int cd_loop_uv_offset)
fuv[i] = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv;
}
- mesh_uv_reset_array(fuv, f->len);
+ mesh_uv_reset_array(fuv.data(), f->len);
}
static void mesh_uv_reset_mface(MPoly *mp, MLoopUV *mloopuv)
{
- float **fuv = BLI_array_alloca(fuv, mp->totloop);
+ Array<float *, BM_DEFAULT_NGON_STACK_SIZE> fuv(mp->totloop);
for (int i = 0; i < mp->totloop; i++) {
fuv[i] = mloopuv[mp->loopstart + i].uv;
}
- mesh_uv_reset_array(fuv, mp->totloop);
+ mesh_uv_reset_array(fuv.data(), mp->totloop);
}
-void ED_mesh_uv_loop_reset_ex(struct Mesh *me, const int layernum)
+void ED_mesh_uv_loop_reset_ex(Mesh *me, const int layernum)
{
BMEditMesh *em = me->edit_mesh;
@@ -219,7 +221,7 @@ void ED_mesh_uv_loop_reset_ex(struct Mesh *me, const int layernum)
else {
/* Collect Mesh UVs */
BLI_assert(CustomData_has_layer(&me->ldata, CD_MLOOPUV));
- MLoopUV *mloopuv = CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, layernum);
+ MLoopUV *mloopuv = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, layernum);
for (int i = 0; i < me->totpoly; i++) {
mesh_uv_reset_mface(&me->mpoly[i], mloopuv);
@@ -229,7 +231,7 @@ void ED_mesh_uv_loop_reset_ex(struct Mesh *me, const int layernum)
DEG_id_tag_update(&me->id, 0);
}
-void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me)
+void ED_mesh_uv_loop_reset(bContext *C, Mesh *me)
{
/* could be ldata or pdata */
CustomData *ldata = GET_CD_DATA(me, ldata);
@@ -239,7 +241,7 @@ void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me)
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
}
-int ED_mesh_uv_texture_add(
+int ED_mesh_uv_add(
Mesh *me, const char *name, const bool active_set, const bool do_init, ReportList *reports)
{
/* NOTE: keep in sync with #ED_mesh_color_add. */
@@ -284,7 +286,7 @@ int ED_mesh_uv_texture_add(
is_init = true;
}
else {
- CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, name);
+ CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, nullptr, me->totloop, name);
}
if (active_set || layernum_dst == 0) {
@@ -305,7 +307,7 @@ int ED_mesh_uv_texture_add(
return layernum_dst;
}
-void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name)
+void ED_mesh_uv_ensure(Mesh *me, const char *name)
{
BMEditMesh *em;
int layernum_dst;
@@ -315,25 +317,25 @@ void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name)
layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV);
if (layernum_dst == 0) {
- ED_mesh_uv_texture_add(me, name, true, true, NULL);
+ ED_mesh_uv_add(me, name, true, true, nullptr);
}
}
else {
layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
if (layernum_dst == 0) {
- ED_mesh_uv_texture_add(me, name, true, true, NULL);
+ ED_mesh_uv_add(me, name, true, true, nullptr);
}
}
}
-bool ED_mesh_uv_texture_remove_index(Mesh *me, const int n)
+bool ED_mesh_uv_remove_index(Mesh *me, const int n)
{
CustomData *ldata = GET_CD_DATA(me, ldata);
CustomDataLayer *cdlu;
int index;
index = CustomData_get_layer_index_n(ldata, CD_MLOOPUV, n);
- cdlu = (index == -1) ? NULL : &ldata->layers[index];
+ cdlu = (index == -1) ? nullptr : &ldata->layers[index];
if (!cdlu) {
return false;
@@ -346,24 +348,22 @@ bool ED_mesh_uv_texture_remove_index(Mesh *me, const int n)
return true;
}
-bool ED_mesh_uv_texture_remove_active(Mesh *me)
+bool ED_mesh_uv_remove_active(Mesh *me)
{
- /* texpoly/uv are assumed to be in sync */
CustomData *ldata = GET_CD_DATA(me, ldata);
const int n = CustomData_get_active_layer(ldata, CD_MLOOPUV);
if (n != -1) {
- return ED_mesh_uv_texture_remove_index(me, n);
+ return ED_mesh_uv_remove_index(me, n);
}
return false;
}
-bool ED_mesh_uv_texture_remove_named(Mesh *me, const char *name)
+bool ED_mesh_uv_remove_named(Mesh *me, const char *name)
{
- /* texpoly/uv are assumed to be in sync */
CustomData *ldata = GET_CD_DATA(me, ldata);
const int n = CustomData_get_named_layer(ldata, CD_MLOOPUV, name);
if (n != -1) {
- return ED_mesh_uv_texture_remove_index(me, n);
+ return ED_mesh_uv_remove_index(me, n);
}
return false;
}
@@ -371,7 +371,7 @@ bool ED_mesh_uv_texture_remove_named(Mesh *me, const char *name)
int ED_mesh_color_add(
Mesh *me, const char *name, const bool active_set, const bool do_init, ReportList *reports)
{
- /* NOTE: keep in sync with #ED_mesh_uv_texture_add. */
+ /* NOTE: keep in sync with #ED_mesh_uv_add. */
BMEditMesh *em;
int layernum;
@@ -409,7 +409,7 @@ int ED_mesh_color_add(
}
else {
CustomData_add_layer_named(
- &me->ldata, CD_PROP_BYTE_COLOR, CD_DEFAULT, NULL, me->totloop, name);
+ &me->ldata, CD_PROP_BYTE_COLOR, CD_DEFAULT, nullptr, me->totloop, name);
}
if (active_set || layernum == 0) {
@@ -425,14 +425,14 @@ int ED_mesh_color_add(
return layernum;
}
-bool ED_mesh_color_ensure(struct Mesh *me, const char *name)
+bool ED_mesh_color_ensure(Mesh *me, const char *name)
{
- BLI_assert(me->edit_mesh == NULL);
+ BLI_assert(me->edit_mesh == nullptr);
CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me->id);
if (!layer) {
CustomData_add_layer_named(
- &me->ldata, CD_PROP_BYTE_COLOR, CD_DEFAULT, NULL, me->totloop, name);
+ &me->ldata, CD_PROP_BYTE_COLOR, CD_DEFAULT, nullptr, me->totloop, name);
layer = me->ldata.layers + CustomData_get_layer_index(&me->ldata, CD_PROP_BYTE_COLOR);
BKE_id_attributes_active_color_set(&me->id, layer);
@@ -441,7 +441,7 @@ bool ED_mesh_color_ensure(struct Mesh *me, const char *name)
DEG_id_tag_update(&me->id, 0);
- return (layer != NULL);
+ return (layer != nullptr);
}
bool ED_mesh_color_remove_index(Mesh *me, const int n)
@@ -451,7 +451,7 @@ bool ED_mesh_color_remove_index(Mesh *me, const int n)
int index;
index = CustomData_get_layer_index_n(ldata, CD_PROP_BYTE_COLOR, n);
- cdl = (index == -1) ? NULL : &ldata->layers[index];
+ cdl = (index == -1) ? nullptr : &ldata->layers[index];
if (!cdl) {
return false;
@@ -487,7 +487,7 @@ bool ED_mesh_color_remove_named(Mesh *me, const char *name)
static bool layers_poll(bContext *C)
{
Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
+ ID *data = (ob) ? static_cast<ID *>(ob->data) : nullptr;
return (ob && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && ob->type == OB_MESH && data &&
!ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data));
}
@@ -501,7 +501,7 @@ static bool sculpt_vertex_color_remove_poll(bContext *C)
}
Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
CustomData *vdata = GET_CD_DATA(me, vdata);
const int active = CustomData_get_active_layer(vdata, CD_PROP_COLOR);
if (active != -1) {
@@ -514,7 +514,7 @@ static bool sculpt_vertex_color_remove_poll(bContext *C)
int ED_mesh_sculpt_color_add(
Mesh *me, const char *name, const bool active_set, const bool do_init, ReportList *reports)
{
- /* NOTE: keep in sync with #ED_mesh_uv_texture_add. */
+ /* NOTE: keep in sync with #ED_mesh_uv_add. */
BMEditMesh *em;
int layernum;
@@ -549,12 +549,14 @@ int ED_mesh_sculpt_color_add(
}
if (CustomData_has_layer(&me->vdata, CD_PROP_COLOR) && do_init) {
- MPropCol *color_data = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
+ const MPropCol *color_data = (const MPropCol *)CustomData_get_layer(&me->vdata,
+ CD_PROP_COLOR);
CustomData_add_layer_named(
- &me->vdata, CD_PROP_COLOR, CD_DUPLICATE, color_data, me->totvert, name);
+ &me->vdata, CD_PROP_COLOR, CD_DUPLICATE, (MPropCol *)color_data, me->totvert, name);
}
else {
- CustomData_add_layer_named(&me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, me->totvert, name);
+ CustomData_add_layer_named(
+ &me->vdata, CD_PROP_COLOR, CD_DEFAULT, nullptr, me->totvert, name);
}
if (active_set || layernum == 0) {
@@ -570,18 +572,18 @@ int ED_mesh_sculpt_color_add(
return layernum;
}
-bool ED_mesh_sculpt_color_ensure(struct Mesh *me, const char *name)
+bool ED_mesh_sculpt_color_ensure(Mesh *me, const char *name)
{
- BLI_assert(me->edit_mesh == NULL);
+ BLI_assert(me->edit_mesh == nullptr);
if (me->totvert && !CustomData_has_layer(&me->vdata, CD_PROP_COLOR)) {
- CustomData_add_layer_named(&me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, me->totvert, name);
+ CustomData_add_layer_named(&me->vdata, CD_PROP_COLOR, CD_DEFAULT, nullptr, me->totvert, name);
BKE_mesh_update_customdata_pointers(me, true);
}
DEG_id_tag_update(&me->id, 0);
- return (me->mloopcol != NULL);
+ return (me->mloopcol != nullptr);
}
bool ED_mesh_sculpt_color_remove_index(Mesh *me, const int n)
@@ -591,7 +593,7 @@ bool ED_mesh_sculpt_color_remove_index(Mesh *me, const int n)
int index;
index = CustomData_get_layer_index_n(vdata, CD_PROP_COLOR, n);
- cdl = (index == -1) ? NULL : &vdata->layers[index];
+ cdl = (index == -1) ? nullptr : &vdata->layers[index];
if (!cdl) {
return false;
@@ -631,7 +633,7 @@ static bool uv_texture_remove_poll(bContext *C)
}
Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
CustomData *ldata = GET_CD_DATA(me, ldata);
const int active = CustomData_get_active_layer(ldata, CD_MLOOPUV);
if (active != -1) {
@@ -644,16 +646,16 @@ static bool uv_texture_remove_poll(bContext *C)
static int mesh_uv_texture_add_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
- if (ED_mesh_uv_texture_add(me, NULL, true, true, op->reports) == -1) {
+ if (ED_mesh_uv_add(me, nullptr, true, true, op->reports) == -1) {
return OPERATOR_CANCELLED;
}
if (ob->mode & OB_MODE_TEXTURE_PAINT) {
Scene *scene = CTX_data_scene(C);
- ED_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ ED_paint_proj_mesh_data_check(scene, ob, nullptr, nullptr, nullptr, nullptr);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, nullptr);
}
return OPERATOR_FINISHED;
@@ -677,16 +679,16 @@ void MESH_OT_uv_texture_add(wmOperatorType *ot)
static int mesh_uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
- if (!ED_mesh_uv_texture_remove_active(me)) {
+ if (!ED_mesh_uv_remove_active(me)) {
return OPERATOR_CANCELLED;
}
if (ob->mode & OB_MODE_TEXTURE_PAINT) {
Scene *scene = CTX_data_scene(C);
- ED_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ ED_paint_proj_mesh_data_check(scene, ob, nullptr, nullptr, nullptr, nullptr);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, nullptr);
}
return OPERATOR_FINISHED;
@@ -716,7 +718,7 @@ static bool vertex_color_remove_poll(bContext *C)
}
Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
CustomData *ldata = GET_CD_DATA(me, ldata);
const int active = CustomData_get_active_layer(ldata, CD_PROP_BYTE_COLOR);
if (active != -1) {
@@ -729,9 +731,9 @@ static bool vertex_color_remove_poll(bContext *C)
static int mesh_vertex_color_add_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
- if (ED_mesh_color_add(me, NULL, true, true, op->reports) == -1) {
+ if (ED_mesh_color_add(me, nullptr, true, true, op->reports) == -1) {
return OPERATOR_CANCELLED;
}
@@ -756,7 +758,7 @@ void MESH_OT_vertex_color_add(wmOperatorType *ot)
static int mesh_vertex_color_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
if (!ED_mesh_color_remove_active(me)) {
return OPERATOR_CANCELLED;
@@ -785,9 +787,9 @@ void MESH_OT_vertex_color_remove(wmOperatorType *ot)
static int mesh_sculpt_vertex_color_add_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
- if (ED_mesh_sculpt_color_add(me, NULL, true, true, op->reports) == -1) {
+ if (ED_mesh_sculpt_color_add(me, nullptr, true, true, op->reports) == -1) {
return OPERATOR_CANCELLED;
}
@@ -812,7 +814,7 @@ void MESH_OT_sculpt_vertex_color_add(wmOperatorType *ot)
static int mesh_sculpt_vertex_color_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
if (!ED_mesh_sculpt_color_remove_active(me)) {
return OPERATOR_CANCELLED;
@@ -868,7 +870,7 @@ static bool mesh_customdata_mask_clear_poll(bContext *C)
{
Object *ob = ED_object_context(C);
if (ob && ob->type == OB_MESH) {
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
/* special case - can't run this if we're in sculpt mode */
if (ob->mode & OB_MODE_SCULPT) {
@@ -925,7 +927,7 @@ static int mesh_customdata_skin_state(bContext *C)
Object *ob = ED_object_context(C);
if (ob && ob->type == OB_MESH) {
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
if (!ID_IS_LINKED(me) && !ID_IS_OVERRIDE_LIBRARY(me)) {
CustomData *data = GET_CD_DATA(me, vdata);
return CustomData_has_layer(data, CD_MVERT_SKIN);
@@ -942,7 +944,7 @@ static bool mesh_customdata_skin_add_poll(bContext *C)
static int mesh_customdata_skin_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
BKE_mesh_ensure_skin_customdata(me);
@@ -1025,7 +1027,7 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
me->smoothresh);
}
- CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, me->totloop);
+ CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, nullptr, me->totloop);
}
DEG_id_tag_update(&me->id, 0);
@@ -1057,7 +1059,7 @@ static int mesh_customdata_custom_splitnormals_clear_exec(bContext *C, wmOperato
if (BKE_mesh_has_custom_loop_normals(me)) {
BMEditMesh *em = me->edit_mesh;
- if (em != NULL && em->bm->lnor_spacearr != NULL) {
+ if (em != nullptr && em->bm->lnor_spacearr != nullptr) {
BKE_lnor_spacearr_clear(em->bm->lnor_spacearr);
}
return mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_CUSTOMLOOPNORMAL);
@@ -1114,7 +1116,7 @@ static void mesh_add_verts(Mesh *mesh, int len)
CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
if (!CustomData_has_layer(&vdata, CD_MVERT)) {
- CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
+ CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, nullptr, totvert);
}
CustomData_free(&mesh->vdata, mesh->totvert);
@@ -1152,7 +1154,7 @@ static void mesh_add_edges(Mesh *mesh, int len)
CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
if (!CustomData_has_layer(&edata, CD_MEDGE)) {
- CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
+ CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, nullptr, totedge);
}
CustomData_free(&mesh->edata, mesh->totedge);
@@ -1186,7 +1188,7 @@ static void mesh_add_loops(Mesh *mesh, int len)
CustomData_copy_data(&mesh->ldata, &ldata, 0, 0, mesh->totloop);
if (!CustomData_has_layer(&ldata, CD_MLOOP)) {
- CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop);
+ CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, nullptr, totloop);
}
BKE_mesh_runtime_clear_cache(mesh);
@@ -1215,7 +1217,7 @@ static void mesh_add_polys(Mesh *mesh, int len)
CustomData_copy_data(&mesh->pdata, &pdata, 0, 0, mesh->totpoly);
if (!CustomData_has_layer(&pdata, CD_MPOLY)) {
- CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpoly);
+ CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, nullptr, totpoly);
}
CustomData_free(&mesh->pdata, mesh->totpoly);
@@ -1413,21 +1415,21 @@ void ED_mesh_report_mirror(wmOperator *op, int totmirr, int totfail)
ED_mesh_report_mirror_ex(op, totmirr, totfail, SCE_SELECT_VERTEX);
}
-Mesh *ED_mesh_context(struct bContext *C)
+Mesh *ED_mesh_context(bContext *C)
{
- Mesh *mesh = CTX_data_pointer_get_type(C, "mesh", &RNA_Mesh).data;
- if (mesh != NULL) {
+ Mesh *mesh = static_cast<Mesh *>(CTX_data_pointer_get_type(C, "mesh", &RNA_Mesh).data);
+ if (mesh != nullptr) {
return mesh;
}
Object *ob = ED_object_active_context(C);
- if (ob == NULL) {
- return NULL;
+ if (ob == nullptr) {
+ return nullptr;
}
ID *data = (ID *)ob->data;
- if (data == NULL || GS(data->name) != ID_ME) {
- return NULL;
+ if (data == nullptr || GS(data->name) != ID_ME) {
+ return nullptr;
}
return (Mesh *)data;
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index b39a0b90f6d..1ee4be50322 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -9,6 +9,10 @@
#pragma once
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct BMEditMesh;
struct BMElem;
struct BMOperator;
@@ -301,7 +305,7 @@ void MESH_OT_mark_freestyle_edge(struct wmOperatorType *ot);
void MESH_OT_mark_freestyle_face(struct wmOperatorType *ot);
#endif
-/* *** mesh_data.c *** */
+/* *** mesh_data.cc *** */
void MESH_OT_uv_texture_add(struct wmOperatorType *ot);
void MESH_OT_uv_texture_remove(struct wmOperatorType *ot);
@@ -314,3 +318,7 @@ void MESH_OT_customdata_skin_add(struct wmOperatorType *ot);
void MESH_OT_customdata_skin_clear(struct wmOperatorType *ot);
void MESH_OT_customdata_custom_splitnormals_add(struct wmOperatorType *ot);
void MESH_OT_customdata_custom_splitnormals_clear(struct wmOperatorType *ot);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.cc
index 9575fde68f0..fafccf68f03 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.cc
@@ -21,10 +21,8 @@
#include "DNA_view3d_types.h"
#include "DNA_workspace_types.h"
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-
#include "BKE_context.h"
+#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_key.h"
@@ -91,7 +89,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
{
int a, b;
- Mesh *me = ob_src->data;
+ Mesh *me = static_cast<Mesh *>(ob_src->data);
MVert *mvert = *mvert_pp;
MEdge *medge = *medge_pp;
MLoop *mloop = *mloop_pp;
@@ -106,12 +104,13 @@ static void join_mesh_single(Depsgraph *depsgraph,
CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert);
/* vertex groups */
- MDeformVert *dvert = CustomData_get(vdata, *vertofs, CD_MDEFORMVERT);
- MDeformVert *dvert_src = CustomData_get(&me->vdata, 0, CD_MDEFORMVERT);
+ MDeformVert *dvert = (MDeformVert *)CustomData_get(vdata, *vertofs, CD_MDEFORMVERT);
+ const MDeformVert *dvert_src = (const MDeformVert *)CustomData_get(
+ &me->vdata, 0, CD_MDEFORMVERT);
/* Remap to correct new vgroup indices, if needed. */
if (dvert_src) {
- BLI_assert(dvert != NULL);
+ BLI_assert(dvert != nullptr);
/* Build src to merged mapping of vgroup indices. */
int *vgroup_index_map;
@@ -120,7 +119,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
ob_src, ob_dst, &vgroup_index_map_len);
BKE_object_defgroup_index_map_apply(
dvert, me->totvert, vgroup_index_map, vgroup_index_map_len);
- if (vgroup_index_map != NULL) {
+ if (vgroup_index_map != nullptr) {
MEM_freeN(vgroup_index_map);
}
}
@@ -150,11 +149,11 @@ static void join_mesh_single(Depsgraph *depsgraph,
float(*cos)[3] = ((float(*)[3])kb->data) + *vertofs;
/* Check if this mesh has such a shape-key. */
- KeyBlock *okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL;
+ KeyBlock *okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : nullptr;
if (okb) {
/* copy this mesh's shape-key to the destination shape-key
* (need to transform first) */
- float(*ocos)[3] = okb->data;
+ float(*ocos)[3] = static_cast<float(*)[3]>(okb->data);
for (a = 0; a < me->totvert; a++, cos++, ocos++) {
copy_v3_v3(*cos, *ocos);
mul_m4_v3(cmat, *cos);
@@ -180,10 +179,10 @@ static void join_mesh_single(Depsgraph *depsgraph,
float(*cos)[3] = ((float(*)[3])kb->data) + *vertofs;
/* Check if this was one of the original shape-keys. */
- KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL;
+ KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : nullptr;
if (okb) {
/* copy this mesh's shape-key to the destination shape-key */
- float(*ocos)[3] = okb->data;
+ float(*ocos)[3] = static_cast<float(*)[3]>(okb->data);
for (a = 0; a < me->totvert; a++, cos++, ocos++) {
copy_v3_v3(*cos, *ocos);
}
@@ -254,17 +253,17 @@ static void join_mesh_single(Depsgraph *depsgraph,
}
/* Face maps. */
- int *fmap = CustomData_get(pdata, *polyofs, CD_FACEMAP);
- int *fmap_src = CustomData_get(&me->pdata, 0, CD_FACEMAP);
+ int *fmap = (int *)CustomData_get(pdata, *polyofs, CD_FACEMAP);
+ const int *fmap_src = (const int *)CustomData_get(&me->pdata, 0, CD_FACEMAP);
/* Remap to correct new face-map indices, if needed. */
if (fmap_src) {
- BLI_assert(fmap != NULL);
+ BLI_assert(fmap != nullptr);
int *fmap_index_map;
int fmap_index_map_len;
fmap_index_map = BKE_object_facemap_index_map_create(ob_src, ob_dst, &fmap_index_map_len);
BKE_object_facemap_index_map_apply(fmap, me->totpoly, fmap_index_map, fmap_index_map_len);
- if (fmap_index_map != NULL) {
+ if (fmap_index_map != nullptr) {
MEM_freeN(fmap_index_map);
}
}
@@ -290,7 +289,7 @@ static void mesh_join_offset_face_sets_ID(const Mesh *mesh, int *face_set_offset
return;
}
- int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
+ int *face_sets = (int *)CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
if (!face_sets) {
return;
}
@@ -317,20 +316,18 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- Material **matar = NULL, *ma;
+ Material **matar = nullptr, *ma;
Mesh *me;
- MVert *mvert = NULL;
- MEdge *medge = NULL;
- MPoly *mpoly = NULL;
- MLoop *mloop = NULL;
- Key *key, *nkey = NULL;
- KeyBlock *kb, *kbn;
+ MVert *mvert = nullptr;
+ MEdge *medge = nullptr;
+ MPoly *mpoly = nullptr;
+ MLoop *mloop = nullptr;
+ Key *key, *nkey = nullptr;
float imat[4][4];
int a, b, totcol, totmat = 0, totedge = 0, totvert = 0;
- int totloop = 0, totpoly = 0, vertofs, *matmap = NULL;
+ int totloop = 0, totpoly = 0, vertofs, *matmap = nullptr;
int i, haskey = 0, edgeofs, loopofs, polyofs;
bool ok = false, join_parent = false;
- bDeformGroup *dg, *odg;
CustomData vdata, edata, fdata, ldata, pdata;
if (ob->mode & OB_MODE_EDIT) {
@@ -349,7 +346,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
/* count & check */
CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
if (ob_iter->type == OB_MESH) {
- me = ob_iter->data;
+ me = static_cast<Mesh *>(ob_iter->data);
totvert += me->totvert;
totedge += me->totedge;
@@ -361,7 +358,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
ok = true;
}
- if ((ob->parent != NULL) && (ob_iter == ob->parent)) {
+ if ((ob->parent != nullptr) && (ob_iter == ob->parent)) {
join_parent = true;
}
@@ -376,7 +373,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
/* Apply parent transform if the active object's parent was joined to it.
* NOTE: This doesn't apply recursive parenting. */
if (join_parent) {
- ob->parent = NULL;
+ ob->parent = nullptr;
BKE_object_apply_mat4_ex(ob, ob->obmat, ob->parent, ob->parentinv, false);
}
@@ -416,8 +413,8 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
/* new material indices and material array */
if (totmat) {
- matar = MEM_callocN(sizeof(*matar) * totmat, "join_mesh matar");
- matmap = MEM_callocN(sizeof(*matmap) * totmat, "join_mesh matmap");
+ matar = static_cast<Material **>(MEM_callocN(sizeof(*matar) * totmat, __func__));
+ matmap = static_cast<int *>(MEM_callocN(sizeof(*matmap) * totmat, __func__));
}
totcol = ob->totcol;
@@ -438,7 +435,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
nkey = (Key *)BKE_id_copy(bmain, &key->id);
/* for all keys in old block, clear data-arrays */
- for (kb = key->block.first; kb; kb = kb->next) {
+ LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
if (kb->data) {
MEM_freeN(kb->data);
}
@@ -462,13 +459,14 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
/* only act if a mesh, and not the one we're joining to */
if ((ob != ob_iter) && (ob_iter->type == OB_MESH)) {
- me = ob_iter->data;
+ me = static_cast<Mesh *>(ob_iter->data);
/* Join this object's vertex groups to the base one's */
- for (dg = me->vertex_group_names.first; dg; dg = dg->next) {
+ LISTBASE_FOREACH (bDeformGroup *, dg, &me->vertex_group_names) {
/* See if this group exists in the object (if it doesn't, add it to the end) */
if (!BKE_object_defgroup_find_name(ob, dg->name)) {
- odg = MEM_mallocN(sizeof(bDeformGroup), "join deformGroup");
+ bDeformGroup *odg = static_cast<bDeformGroup *>(
+ MEM_mallocN(sizeof(bDeformGroup), __func__));
memcpy(odg, dg, sizeof(bDeformGroup));
BLI_addtail(&mesh_active->vertex_group_names, odg);
}
@@ -481,8 +479,8 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
/* Join this object's face maps to the base one's. */
LISTBASE_FOREACH (bFaceMap *, fmap, &ob_iter->fmaps) {
/* See if this group exists in the object (if it doesn't, add it to the end) */
- if (BKE_object_facemap_find_name(ob, fmap->name) == NULL) {
- bFaceMap *fmap_new = MEM_mallocN(sizeof(bFaceMap), "join faceMap");
+ if (BKE_object_facemap_find_name(ob, fmap->name) == nullptr) {
+ bFaceMap *fmap_new = static_cast<bFaceMap *>(MEM_mallocN(sizeof(bFaceMap), __func__));
memcpy(fmap_new, fmap, sizeof(bFaceMap));
BLI_addtail(&ob->fmaps, fmap_new);
}
@@ -522,13 +520,15 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
* check if destination mesh already has matching entries too. */
if (me->key && key) {
/* for remapping KeyBlock.relative */
- int *index_map = MEM_mallocN(sizeof(int) * me->key->totkey, __func__);
- KeyBlock **kb_map = MEM_mallocN(sizeof(KeyBlock *) * me->key->totkey, __func__);
+ int *index_map = static_cast<int *>(
+ MEM_mallocN(sizeof(int) * me->key->totkey, __func__));
+ KeyBlock **kb_map = static_cast<KeyBlock **>(
+ MEM_mallocN(sizeof(KeyBlock *) * me->key->totkey, __func__));
- for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) {
+ LISTBASE_FOREACH_INDEX (KeyBlock *, kb, &me->key->block, i) {
BLI_assert(i < me->key->totkey);
- kbn = BKE_keyblock_find_name(key, kb->name);
+ KeyBlock *kbn = BKE_keyblock_find_name(key, kb->name);
/* if key doesn't exist in destination mesh, add it */
if (kbn) {
index_map[i] = BLI_findindex(&key->block, kbn);
@@ -549,7 +549,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
}
/* remap relative index values */
- for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) {
+ LISTBASE_FOREACH_INDEX (KeyBlock *, kb, &me->key->block, i) {
/* sanity check, should always be true */
if (LIKELY(kb->relative < me->key->totkey)) {
kb_map[i]->relative = index_map[kb->relative];
@@ -571,10 +571,10 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
CustomData_reset(&ldata);
CustomData_reset(&pdata);
- mvert = CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
- medge = CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
- mloop = CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop);
- mpoly = CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpoly);
+ mvert = (MVert *)CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, nullptr, totvert);
+ medge = (MEdge *)CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, nullptr, totedge);
+ mloop = (MLoop *)CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, nullptr, totloop);
+ mpoly = (MPoly *)CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, nullptr, totpoly);
vertofs = 0;
edgeofs = 0;
@@ -661,7 +661,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* return to mesh we're merging to */
- me = ob->data;
+ me = static_cast<Mesh *>(ob->data);
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
@@ -703,8 +703,8 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
if (totcol) {
me->mat = matar;
- ob->mat = MEM_callocN(sizeof(*ob->mat) * totcol, "join obmatar");
- ob->matbits = MEM_callocN(sizeof(*ob->matbits) * totcol, "join obmatbits");
+ ob->mat = static_cast<Material **>(MEM_callocN(sizeof(*ob->mat) * totcol, __func__));
+ ob->matbits = static_cast<char *>(MEM_callocN(sizeof(*ob->matbits) * totcol, __func__));
MEM_freeN(matmap);
}
@@ -751,8 +751,8 @@ int ED_mesh_shapes_join_objects_exec(bContext *C, wmOperator *op)
Object *ob_active = CTX_data_active_object(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Mesh *me = (Mesh *)ob_active->data;
- Mesh *selme = NULL;
- Mesh *me_deformed = NULL;
+ Mesh *selme = nullptr;
+ Mesh *me_deformed = nullptr;
Key *key = me->key;
KeyBlock *kb;
bool ok = false, nonequal_verts = false;
@@ -769,7 +769,7 @@ int ED_mesh_shapes_join_objects_exec(bContext *C, wmOperator *op)
ok = true;
}
else {
- nonequal_verts = 1;
+ nonequal_verts = true;
}
}
}
@@ -787,12 +787,12 @@ int ED_mesh_shapes_join_objects_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (key == NULL) {
+ if (key == nullptr) {
key = me->key = BKE_key_add(bmain, (ID *)me);
key->type = KEY_RELATIVE;
/* first key added, so it was the basis. initialize it with the existing mesh */
- kb = BKE_keyblock_add(key, NULL);
+ kb = BKE_keyblock_add(key, nullptr);
BKE_keyblock_convert_from_mesh(me, key, kb);
}
@@ -835,21 +835,21 @@ int ED_mesh_shapes_join_objects_exec(bContext *C, wmOperator *op)
/** \name Mesh Topology Mirror API
* \{ */
-static MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1};
+static MirrTopoStore_t mesh_topo_store = {nullptr, -1, -1, false};
BLI_INLINE void mesh_mirror_topo_table_get_meshes(Object *ob,
Mesh *me_eval,
Mesh **r_me_mirror,
BMEditMesh **r_em_mirror)
{
- Mesh *me_mirror = NULL;
- BMEditMesh *em_mirror = NULL;
+ Mesh *me_mirror = nullptr;
+ BMEditMesh *em_mirror = nullptr;
- Mesh *me = ob->data;
- if (me_eval != NULL) {
+ Mesh *me = static_cast<Mesh *>(ob->data);
+ if (me_eval != nullptr) {
me_mirror = me_eval;
}
- else if (me->edit_mesh != NULL) {
+ else if (me->edit_mesh != nullptr) {
em_mirror = me->edit_mesh;
}
else {
@@ -892,7 +892,7 @@ static bool ed_mesh_mirror_topo_table_update(Object *ob, Mesh *me_eval)
static int mesh_get_x_mirror_vert_spatial(Object *ob, Mesh *me_eval, int index)
{
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
MVert *mvert = me_eval ? me_eval->mvert : me->mvert;
float vec[3];
@@ -901,7 +901,7 @@ static int mesh_get_x_mirror_vert_spatial(Object *ob, Mesh *me_eval, int index)
vec[1] = mvert->co[1];
vec[2] = mvert->co[2];
- return ED_mesh_mirror_spatial_table_lookup(ob, NULL, me_eval, vec);
+ return ED_mesh_mirror_spatial_table_lookup(ob, nullptr, me_eval, vec);
}
static int mesh_get_x_mirror_vert_topo(Object *ob, Mesh *mesh, int index)
@@ -928,28 +928,25 @@ static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, c
/* ignore nan verts */
if ((isfinite(co[0]) == false) || (isfinite(co[1]) == false) || (isfinite(co[2]) == false)) {
- return NULL;
+ return nullptr;
}
vec[0] = -co[0];
vec[1] = co[1];
vec[2] = co[2];
- i = ED_mesh_mirror_spatial_table_lookup(ob, em, NULL, vec);
+ i = ED_mesh_mirror_spatial_table_lookup(ob, em, nullptr, vec);
if (i != -1) {
return BM_vert_at_index(em->bm, i);
}
- return NULL;
+ return nullptr;
}
-static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob,
- struct BMEditMesh *em,
- BMVert *eve,
- int index)
+static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob, BMEditMesh *em, BMVert *eve, int index)
{
intptr_t poinval;
- if (!ed_mesh_mirror_topo_table_update(ob, NULL)) {
- return NULL;
+ if (!ed_mesh_mirror_topo_table_update(ob, nullptr)) {
+ return nullptr;
}
if (index == -1) {
@@ -965,7 +962,7 @@ static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob,
}
if (index == em->bm->totvert) {
- return NULL;
+ return nullptr;
}
}
@@ -974,15 +971,11 @@ static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob,
if (poinval != -1) {
return (BMVert *)(poinval);
}
- return NULL;
+ return nullptr;
}
-BMVert *editbmesh_get_x_mirror_vert(Object *ob,
- struct BMEditMesh *em,
- BMVert *eve,
- const float co[3],
- int index,
- const bool use_topology)
+BMVert *editbmesh_get_x_mirror_vert(
+ Object *ob, BMEditMesh *em, BMVert *eve, const float co[3], int index, const bool use_topology)
{
if (use_topology) {
return editbmesh_get_x_mirror_vert_topo(ob, em, eve, index);
@@ -992,7 +985,7 @@ BMVert *editbmesh_get_x_mirror_vert(Object *ob,
int ED_mesh_mirror_get_vert(Object *ob, int index)
{
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
BMEditMesh *em = me->edit_mesh;
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
int index_mirr;
@@ -1004,7 +997,7 @@ int ED_mesh_mirror_get_vert(Object *ob, int index)
index_mirr = eve_mirr ? BM_elem_index_get(eve_mirr) : -1;
}
else {
- index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, use_topology);
+ index_mirr = mesh_get_x_mirror_vert(ob, nullptr, index, use_topology);
}
return index_mirr;
@@ -1021,7 +1014,7 @@ static float *editmesh_get_mirror_uv(
/* ignore nan verts */
if (isnan(uv[0]) || !isfinite(uv[0]) || isnan(uv[1]) || !isfinite(uv[1])) {
- return NULL;
+ return nullptr;
}
if (axis) {
@@ -1061,14 +1054,14 @@ static float *editmesh_get_mirror_uv(
}
}
- return NULL;
+ return nullptr;
}
#endif
static uint mirror_facehash(const void *ptr)
{
- const MFace *mf = ptr;
+ const MFace *mf = static_cast<const MFace *>(ptr);
uint v0, v1;
if (mf->v4) {
@@ -1121,21 +1114,21 @@ static bool mirror_facecmp(const void *a, const void *b)
int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval)
{
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
MVert *mv, *mvert;
MFace mirrormf, *mf, *hashmf, *mface;
GHash *fhash;
int *mirrorverts, *mirrorfaces;
- BLI_assert(em == NULL); /* Does not work otherwise, currently... */
+ BLI_assert(em == nullptr); /* Does not work otherwise, currently... */
const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
const int totvert = me_eval ? me_eval->totvert : me->totvert;
const int totface = me_eval ? me_eval->totface : me->totface;
int a;
- mirrorverts = MEM_callocN(sizeof(int) * totvert, "MirrorVerts");
- mirrorfaces = MEM_callocN(sizeof(int[2]) * totface, "MirrorFaces");
+ mirrorverts = static_cast<int *>(MEM_callocN(sizeof(int) * totvert, "MirrorVerts"));
+ mirrorfaces = static_cast<int *>(MEM_callocN(sizeof(int[2]) * totface, "MirrorFaces"));
mvert = me_eval ? me_eval->mvert : me->mvert;
mface = me_eval ? me_eval->mface : me->mface;
@@ -1165,7 +1158,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval)
SWAP(uint, mirrormf.v2, mirrormf.v4);
}
- hashmf = BLI_ghash_lookup(fhash, &mirrormf);
+ hashmf = static_cast<MFace *>(BLI_ghash_lookup(fhash, &mirrormf));
if (hashmf) {
mirrorfaces[a * 2] = hashmf - mface;
mirrorfaces[a * 2 + 1] = mirror_facerotation(&mirrormf, hashmf);
@@ -1175,7 +1168,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval)
}
}
- BLI_ghash_free(fhash, NULL, NULL);
+ BLI_ghash_free(fhash, nullptr, nullptr);
MEM_freeN(mirrorverts);
return mirrorfaces;
@@ -1186,7 +1179,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval)
bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index)
{
ViewContext vc;
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
BLI_assert(me && GS(me->id.name) == ID_ME);
@@ -1199,8 +1192,8 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px,
ED_view3d_select_id_validate(&vc);
if (dist_px) {
- /* sample rect to increase chances of selecting, so that when clicking
- * on an edge in the backbuf, we can still select a face */
+ /* Sample rect to increase chances of selecting, so that when clicking
+ * on an edge in the back-buffer, we can still select a face. */
*r_index = DRW_select_buffer_find_nearest_to_point(
vc.depsgraph, vc.region, vc.v3d, mval, 1, me->totpoly + 1, &dist_px);
}
@@ -1220,7 +1213,7 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px,
static void ed_mesh_pick_face_vert__mpoly_find(
/* context */
- struct ARegion *region,
+ ARegion *region,
const float mval[2],
/* mesh data (evaluated) */
const MPoly *mp,
@@ -1250,14 +1243,14 @@ bool ED_mesh_pick_face_vert(
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
uint poly_index;
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
BLI_assert(me && GS(me->id.name) == ID_ME);
if (ED_mesh_pick_face(C, ob, mval, dist_px, &poly_index)) {
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- struct ARegion *region = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* derived mesh to find deformed locations */
Mesh *me_eval = mesh_get_eval_final(
@@ -1266,14 +1259,13 @@ bool ED_mesh_pick_face_vert(
int v_idx_best = ORIGINDEX_NONE;
/* find the vert closest to 'mval' */
- const float mval_f[2] = {UNPACK2(mval)};
+ const float mval_f[2] = {(float)mval[0], (float)mval[1]};
float len_best = FLT_MAX;
MPoly *me_eval_mpoly;
MLoop *me_eval_mloop;
MVert *me_eval_mvert;
uint me_eval_mpoly_len;
- const int *index_mp_to_orig;
me_eval_mpoly = me_eval->mpoly;
me_eval_mloop = me_eval->mloop;
@@ -1281,7 +1273,7 @@ bool ED_mesh_pick_face_vert(
me_eval_mpoly_len = me_eval->totpoly;
- index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
+ const int *index_mp_to_orig = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
/* tag all verts using this face */
if (index_mp_to_orig) {
@@ -1313,8 +1305,8 @@ bool ED_mesh_pick_face_vert(
/* map 'dm -> me' r_index if possible */
if (v_idx_best != ORIGINDEX_NONE) {
- const int *index_mv_to_orig;
- index_mv_to_orig = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
+ const int *index_mv_to_orig = (const int *)CustomData_get_layer(&me_eval->vdata,
+ CD_ORIGINDEX);
if (index_mv_to_orig) {
v_idx_best = index_mv_to_orig[v_idx_best];
}
@@ -1335,7 +1327,7 @@ bool ED_mesh_pick_face_vert(
*
* \return boolean true == Found
*/
-typedef struct VertPickData {
+struct VertPickData {
const MVert *mvert;
const float *mval_f; /* [2] */
ARegion *region;
@@ -1343,14 +1335,14 @@ typedef struct VertPickData {
/* runtime */
float len_best;
int v_idx_best;
-} VertPickData;
+};
static void ed_mesh_pick_vert__mapFunc(void *userData,
int index,
const float co[3],
const float UNUSED(no[3]))
{
- VertPickData *data = userData;
+ VertPickData *data = static_cast<VertPickData *>(userData);
if ((data->mvert[index].flag & ME_HIDE) == 0) {
float sco[2];
@@ -1368,7 +1360,7 @@ bool ED_mesh_pick_vert(
bContext *C, Object *ob, const int mval[2], uint dist_px, bool use_zbuf, uint *r_index)
{
ViewContext vc;
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
BLI_assert(me && GS(me->id.name) == ID_ME);
@@ -1382,8 +1374,8 @@ bool ED_mesh_pick_vert(
if (use_zbuf) {
if (dist_px > 0) {
- /* sample rect to increase chances of selecting, so that when clicking
- * on an face in the backbuf, we can still select a vert */
+ /* Sample rectangle to increase chances of selecting, so that when clicking
+ * on an face in the back-buffer, we can still select a vert. */
*r_index = DRW_select_buffer_find_nearest_to_point(
vc.depsgraph, vc.region, vc.v3d, mval, 1, me->totvert + 1, &dist_px);
}
@@ -1405,16 +1397,16 @@ bool ED_mesh_pick_vert(
/* derived mesh to find deformed locations */
Mesh *me_eval = mesh_get_eval_final(vc.depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
ARegion *region = vc.region;
- RegionView3D *rv3d = region->regiondata;
+ RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
/* find the vert closest to 'mval' */
const float mval_f[2] = {(float)mval[0], (float)mval[1]};
- VertPickData data = {NULL};
+ VertPickData data = {nullptr};
ED_view3d_init_mats_rv3d(ob, rv3d);
- if (me_eval == NULL) {
+ if (me_eval == nullptr) {
return false;
}
@@ -1440,7 +1432,7 @@ bool ED_mesh_pick_vert(
MDeformVert *ED_mesh_active_dvert_get_em(Object *ob, BMVert **r_eve)
{
if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH) {
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
if (!BLI_listbase_is_empty(&me->vertex_group_names)) {
BMesh *bm = me->edit_mesh->bm;
const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
@@ -1452,27 +1444,27 @@ MDeformVert *ED_mesh_active_dvert_get_em(Object *ob, BMVert **r_eve)
if (r_eve) {
*r_eve = eve;
}
- return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ return static_cast<MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
}
}
}
}
if (r_eve) {
- *r_eve = NULL;
+ *r_eve = nullptr;
}
- return NULL;
+ return nullptr;
}
MDeformVert *ED_mesh_active_dvert_get_ob(Object *ob, int *r_index)
{
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
int index = BKE_mesh_mselect_active_get(me, ME_VSEL);
if (r_index) {
*r_index = index;
}
- if (index == -1 || me->dvert == NULL) {
- return NULL;
+ if (index == -1 || me->dvert == nullptr) {
+ return nullptr;
}
return me->dvert + index;
}
@@ -1481,14 +1473,14 @@ MDeformVert *ED_mesh_active_dvert_get_only(Object *ob)
{
if (ob->type == OB_MESH) {
if (ob->mode & OB_MODE_EDIT) {
- return ED_mesh_active_dvert_get_em(ob, NULL);
+ return ED_mesh_active_dvert_get_em(ob, nullptr);
}
- return ED_mesh_active_dvert_get_ob(ob, NULL);
+ return ED_mesh_active_dvert_get_ob(ob, nullptr);
}
- return NULL;
+ return nullptr;
}
-void EDBM_mesh_stats_multi(struct Object **objects,
+void EDBM_mesh_stats_multi(Object **objects,
const uint objects_len,
int totelem[3],
int totelem_sel[3])
diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc
index db8860efdd8..ac8ab834cb7 100644
--- a/source/blender/editors/object/object_add.cc
+++ b/source/blender/editors/object/object_add.cc
@@ -1888,7 +1888,7 @@ void OBJECT_OT_collection_external_asset_drop(wmOperatorType *ot)
ED_object_add_generic_props(ot, false);
- /* Important: Instancing option. Intentionally remembered across executions (no #PROP_SKIP_SAVE).
+ /* IMPORTANT: Instancing option. Intentionally remembered across executions (no #PROP_SKIP_SAVE).
*/
RNA_def_boolean(ot->srna,
"use_instance",
@@ -2116,6 +2116,22 @@ static int object_curves_empty_hair_add_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static bool object_curves_empty_hair_add_poll(bContext *C)
+{
+ if (!U.experimental.use_new_curves_type) {
+ return false;
+ }
+ if (!ED_operator_objectmode(C)) {
+ return false;
+ }
+ Object *ob = CTX_data_active_object(C);
+ if (ob == nullptr || ob->type != OB_MESH) {
+ CTX_wm_operator_poll_msg_set(C, "No active mesh object");
+ return false;
+ }
+ return true;
+}
+
void OBJECT_OT_curves_empty_hair_add(wmOperatorType *ot)
{
ot->name = "Add Empty Curves";
@@ -2123,7 +2139,7 @@ void OBJECT_OT_curves_empty_hair_add(wmOperatorType *ot)
ot->idname = "OBJECT_OT_curves_empty_hair_add";
ot->exec = object_curves_empty_hair_add_exec;
- ot->poll = object_curves_add_poll;
+ ot->poll = object_curves_empty_hair_add_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2762,9 +2778,32 @@ static const EnumPropertyItem convert_target_items[] = {
"Point Cloud",
"Point Cloud from Mesh objects"},
#endif
+ {OB_CURVES, "CURVES", ICON_OUTLINER_OB_CURVES, "Curves", "Curves from evaluated curve data"},
{0, nullptr, 0, nullptr, nullptr},
};
+static const EnumPropertyItem *convert_target_items_fn(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ EnumPropertyItem *items = nullptr;
+ int items_num = 0;
+ for (const EnumPropertyItem *item = convert_target_items; item->identifier != nullptr; item++) {
+ if (item->value == OB_CURVES) {
+ if (U.experimental.use_new_curves_type) {
+ RNA_enum_item_add(&items, &items_num, item);
+ }
+ }
+ else {
+ RNA_enum_item_add(&items, &items_num, item);
+ }
+ }
+ RNA_enum_item_end(&items, &items_num);
+ *r_free = true;
+ return items;
+}
+
static void object_data_convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
if (ob->runtime.curve_cache == nullptr) {
@@ -3065,6 +3104,50 @@ static int object_convert_exec(bContext *C, wmOperator *op)
}
ob_gpencil->actcol = actcol;
}
+ else if (target == OB_CURVES) {
+ ob->flag |= OB_DONE;
+
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ GeometrySet geometry;
+ if (ob_eval->runtime.geometry_set_eval != nullptr) {
+ geometry = *ob_eval->runtime.geometry_set_eval;
+ }
+
+ if (geometry.has_curves()) {
+ if (keep_original) {
+ basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
+ newob = basen->object;
+
+ /* Decrement original curve's usage count. */
+ Curve *legacy_curve = static_cast<Curve *>(newob->data);
+ id_us_min(&legacy_curve->id);
+
+ /* Make a copy of the curve. */
+ newob->data = BKE_id_copy(bmain, &legacy_curve->id);
+ }
+ else {
+ newob = ob;
+ }
+
+ const CurveComponent &curve_component = *geometry.get_component_for_read<CurveComponent>();
+ const Curves *curves_eval = curve_component.get_for_read();
+ Curves *new_curves = static_cast<Curves *>(BKE_id_new(bmain, ID_CV, newob->id.name + 2));
+
+ newob->data = new_curves;
+ newob->type = OB_CURVES;
+
+ blender::bke::CurvesGeometry::wrap(
+ new_curves->geometry) = blender::bke::CurvesGeometry::wrap(curves_eval->geometry);
+ BKE_object_material_from_eval_data(bmain, newob, &curves_eval->id);
+
+ BKE_object_free_derived_caches(newob);
+ BKE_object_free_modifiers(newob, 0);
+ }
+ else {
+ BKE_reportf(
+ op->reports, RPT_WARNING, "Object '%s' has no evaluated curves data", ob->id.name + 2);
+ }
+ }
else if (ob->type == OB_MESH && target == OB_POINTCLOUD) {
ob->flag |= OB_DONE;
@@ -3480,6 +3563,7 @@ void OBJECT_OT_convert(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(
ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to");
+ RNA_def_enum_funcs(ot->prop, convert_target_items_fn);
RNA_def_boolean(ot->srna,
"keep_original",
false,
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index a7379d7e492..114b2ce8102 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -446,9 +446,9 @@ static bool bake_object_check(ViewLayer *view_layer,
}
if (target == R_BAKE_TARGET_VERTEX_COLORS) {
- MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
+ const MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
const bool mcol_valid = (mcol != NULL);
- MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR);
+ const MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR);
if (mloopcol == NULL && !mcol_valid) {
BKE_reportf(reports,
RPT_ERROR,
@@ -943,9 +943,9 @@ static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, Re
}
Mesh *me = ob->data;
- MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
+ const MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
const bool mcol_valid = (mcol != NULL);
- MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR);
+ const MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR);
if (mloopcol == NULL && !mcol_valid) {
BKE_report(reports, RPT_ERROR, "No vertex colors layer found to bake to");
return false;
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 2e878770347..d982d86fe77 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -1715,7 +1715,7 @@ static int constraint_copy_to_selected_exec(bContext *C, wmOperator *op)
Object *prev_ob = NULL;
- /* Copy all constraints from active posebone to all selected posebones. */
+ /* Copy all constraints from active pose-bone to all selected pose-bones. */
CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, chan, selected_pose_bones, Object *, ob) {
/* If we're not handling the object we're copying from, copy all constraints over. */
if (pchan == chan) {
@@ -2115,7 +2115,7 @@ static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
Object *prev_ob = NULL;
- /* copy all constraints from active posebone to all selected posebones */
+ /* Copy all constraints from active pose-bone to all selected pose-bones. */
CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, chan, selected_pose_bones, Object *, ob) {
/* if we're not handling the object we're copying from, copy all constraints over */
if (pchan != chan) {
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index ff25859b56b..adac1479c7e 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -17,6 +17,7 @@
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
+#include "BLI_math_rotation.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -86,6 +87,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "RNA_types.h"
#include "UI_interface_icons.h"
@@ -1461,6 +1463,8 @@ void OBJECT_OT_paths_clear(wmOperatorType *ot)
static int shade_smooth_exec(bContext *C, wmOperator *op)
{
const bool use_smooth = STREQ(op->idname, "OBJECT_OT_shade_smooth");
+ const bool use_auto_smooth = RNA_boolean_get(op->ptr, "use_auto_smooth");
+ const float auto_smooth_angle = RNA_float_get(op->ptr, "auto_smooth_angle");
bool changed_multi = false;
bool has_linked_data = false;
@@ -1508,6 +1512,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
bool changed = false;
if (ob->type == OB_MESH) {
BKE_mesh_smooth_flag_set(ob->data, use_smooth);
+ BKE_mesh_auto_smooth_flag_set(ob->data, use_auto_smooth, auto_smooth_angle);
BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
changed = true;
}
@@ -1577,6 +1582,25 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop;
+
+ prop = RNA_def_boolean(
+ ot->srna,
+ "use_auto_smooth",
+ false,
+ "Auto Smooth",
+ "Enable automatic smooth based on smooth/sharp faces/edges and angle between faces");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_property(ot->srna, "auto_smooth_angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(30.0f));
+ RNA_def_property_ui_text(prop,
+ "Angle",
+ "Maximum angle between face normals that will be considered as smooth"
+ "(unused if custom split normals data are available)");
}
/** \} */
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index cc6aa34d39d..fdf2cae026d 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -143,7 +143,12 @@ bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
}
break;
case OB_CURVES:
- if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT_CURVES)) {
+ if (U.experimental.use_new_curves_tools) {
+ if (mode & OB_MODE_EDIT) {
+ return true;
+ }
+ }
+ if (mode & OB_MODE_SCULPT_CURVES) {
return true;
}
break;
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 76dcfbd8d36..6e6dbc6837c 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -2258,49 +2258,6 @@ static bool make_override_library_object_overridable_check(Main *bmain, Object *
return false;
}
-/* Set the object to override. */
-static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *obact = ED_object_active_context(C);
-
- /* Sanity checks. */
- if (!scene || ID_IS_LINKED(scene) || !obact) {
- return OPERATOR_CANCELLED;
- }
-
- if ((!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
- ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection)) ||
- make_override_library_object_overridable_check(bmain, obact)) {
- uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
- uiLayout *layout = UI_popup_menu_layout(pup);
-
- /* Create operator menu item with relevant properties filled in. */
- PointerRNA opptr_dummy;
- uiItemFullO_ptr(
- layout, op->type, op->type->name, ICON_NONE, NULL, WM_OP_EXEC_REGION_WIN, 0, &opptr_dummy);
-
- /* Present the menu and be done... */
- UI_popup_menu_end(C, pup);
-
- /* This invoke just calls another instance of this operator... */
- return OPERATOR_INTERFACE;
- }
-
- if (ID_IS_LINKED(obact)) {
- /* Show menu with list of directly linked collections containing the active object. */
- WM_enum_search_invoke(C, op, event);
- return OPERATOR_CANCELLED;
- }
-
- /* Error.. cannot continue. */
- BKE_report(op->reports,
- RPT_ERROR,
- "Can only make library override for a referenced object or collection");
- return OPERATOR_CANCELLED;
-}
-
static int make_override_library_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -2310,8 +2267,12 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
ID *id_root = NULL;
bool is_override_instancing_object = false;
- GSet *user_overrides_objects_uids = BLI_gset_new(
- BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+ const bool do_fully_editable = RNA_boolean_get(op->ptr, "do_fully_editable");
+
+ GSet *user_overrides_objects_uids = do_fully_editable ? NULL :
+ BLI_gset_new(BLI_ghashutil_inthash_p,
+ BLI_ghashutil_intcmp,
+ __func__);
bool user_overrides_from_selected_objects = false;
if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
@@ -2359,7 +2320,10 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
user_overrides_from_selected_objects = true;
}
- if (user_overrides_from_selected_objects) {
+ if (do_fully_editable) {
+ /* Pass. */
+ }
+ else if (user_overrides_from_selected_objects) {
/* Only selected objects can be 'user overrides'. */
FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
BLI_gset_add(user_overrides_objects_uids, POINTER_FROM_UINT(ob_iter->id.session_uuid));
@@ -2379,25 +2343,34 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
ID *id_root_override;
- const bool success = BKE_lib_override_library_create(
- bmain, scene, view_layer, NULL, id_root, id_root, &obact->id, &id_root_override);
-
- /* Define liboverrides from selected/validated objects as user defined. */
- ID *id_hierarchy_root_override = id_root_override->override_library->hierarchy_root;
- ID *id_iter;
- FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
- if (ID_IS_LINKED(id_iter) || !ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) ||
- id_iter->override_library->hierarchy_root != id_hierarchy_root_override) {
- continue;
- }
- if (BLI_gset_haskey(user_overrides_objects_uids,
- POINTER_FROM_UINT(id_iter->override_library->reference->session_uuid))) {
- id_iter->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
+ const bool success = BKE_lib_override_library_create(bmain,
+ scene,
+ view_layer,
+ NULL,
+ id_root,
+ id_root,
+ &obact->id,
+ &id_root_override,
+ do_fully_editable);
+
+ if (!do_fully_editable) {
+ /* Define liboverrides from selected/validated objects as user defined. */
+ ID *id_hierarchy_root_override = id_root_override->override_library->hierarchy_root;
+ ID *id_iter;
+ FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
+ if (ID_IS_LINKED(id_iter) || !ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) ||
+ id_iter->override_library->hierarchy_root != id_hierarchy_root_override) {
+ continue;
+ }
+ if (BLI_gset_haskey(user_overrides_objects_uids,
+ POINTER_FROM_UINT(id_iter->override_library->reference->session_uuid))) {
+ id_iter->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
+ }
}
- }
- FOREACH_MAIN_ID_END;
+ FOREACH_MAIN_ID_END;
- BLI_gset_free(user_overrides_objects_uids, NULL);
+ BLI_gset_free(user_overrides_objects_uids, NULL);
+ }
/* Remove the instance empty from this scene, the items now have an overridden collection
* instead. */
@@ -2411,6 +2384,37 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
+/* Set the object to override. */
+static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obact = ED_object_active_context(C);
+
+ /* Sanity checks. */
+ if (!scene || ID_IS_LINKED(scene) || !obact) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if ((!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
+ ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection)) ||
+ make_override_library_object_overridable_check(bmain, obact)) {
+ return make_override_library_exec(C, op);
+ }
+
+ if (ID_IS_LINKED(obact)) {
+ /* Show menu with list of directly linked collections containing the active object. */
+ WM_enum_search_invoke(C, op, event);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Error.. cannot continue. */
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Can only make library override for a referenced object or collection");
+ return OPERATOR_CANCELLED;
+}
+
static bool make_override_library_poll(bContext *C)
{
Object *obact = CTX_data_active_object(C);
@@ -2480,6 +2484,13 @@ void OBJECT_OT_make_override_library(wmOperatorType *ot)
RNA_def_enum_funcs(prop, make_override_collections_of_linked_object_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
+
+ prop = RNA_def_boolean(ot->srna,
+ "do_fully_editable",
+ false,
+ "Create Fully Editable",
+ "Make all created override data-blocks fully editable");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc
index a56f513e98f..addcedc4481 100644
--- a/source/blender/editors/render/render_preview.cc
+++ b/source/blender/editors/render/render_preview.cc
@@ -1306,7 +1306,7 @@ static ImBuf *icon_preview_imbuf_from_brush(Brush *brush)
{
static const int flags = IB_rect | IB_multilayer | IB_metadata;
- char path[FILE_MAX];
+ char filepath[FILE_MAX];
const char *folder;
if (!(brush->icon_imbuf)) {
@@ -1315,22 +1315,22 @@ static ImBuf *icon_preview_imbuf_from_brush(Brush *brush)
if (brush->icon_filepath[0]) {
/* First use the path directly to try and load the file. */
- BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath));
- BLI_path_abs(path, ID_BLEND_PATH_FROM_GLOBAL(&brush->id));
+ BLI_strncpy(filepath, brush->icon_filepath, sizeof(brush->icon_filepath));
+ BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&brush->id));
/* Use default color-spaces for brushes. */
- brush->icon_imbuf = IMB_loadiffname(path, flags, nullptr);
+ brush->icon_imbuf = IMB_loadiffname(filepath, flags, nullptr);
/* otherwise lets try to find it in other directories */
if (!(brush->icon_imbuf)) {
folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons");
BLI_make_file_string(
- BKE_main_blendfile_path_from_global(), path, folder, brush->icon_filepath);
+ BKE_main_blendfile_path_from_global(), filepath, folder, brush->icon_filepath);
- if (path[0]) {
+ if (filepath[0]) {
/* Use default color spaces. */
- brush->icon_imbuf = IMB_loadiffname(path, flags, nullptr);
+ brush->icon_imbuf = IMB_loadiffname(filepath, flags, nullptr);
}
}
@@ -1821,13 +1821,13 @@ void PreviewLoadJob::run_fn(void *customdata,
const char *deferred_data = static_cast<char *>(PRV_DEFERRED_DATA(preview));
const ThumbSource source = static_cast<ThumbSource>(deferred_data[0]);
- const char *path = &deferred_data[1];
+ const char *filepath = &deferred_data[1];
- // printf("loading deferred %d×%d preview for %s\n", request->sizex, request->sizey, path);
+ // printf("loading deferred %d×%d preview for %s\n", request->sizex, request->sizey, filepath);
- IMB_thumb_path_lock(path);
- ImBuf *thumb = IMB_thumb_manage(path, THB_LARGE, source);
- IMB_thumb_path_unlock(path);
+ IMB_thumb_path_lock(filepath);
+ ImBuf *thumb = IMB_thumb_manage(filepath, THB_LARGE, source);
+ IMB_thumb_path_unlock(filepath);
if (thumb) {
/* PreviewImage assumes premultiplied alpha... */
diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c
index a13177942a8..57a9e6be917 100644
--- a/source/blender/editors/scene/scene_edit.c
+++ b/source/blender/editors/scene/scene_edit.c
@@ -67,7 +67,10 @@ static Scene *scene_add(Main *bmain, Scene *scene_old, eSceneCopyMethod method)
}
/** Add a new scene in the sequence editor. */
-static Scene *ED_scene_sequencer_add(Main *bmain, bContext *C, eSceneCopyMethod method)
+Scene *ED_scene_sequencer_add(Main *bmain,
+ bContext *C,
+ eSceneCopyMethod method,
+ const bool assign_strip)
{
Sequence *seq = NULL;
Scene *scene_active = CTX_data_scene(C);
@@ -88,6 +91,11 @@ static Scene *ED_scene_sequencer_add(Main *bmain, bContext *C, eSceneCopyMethod
Scene *scene_new = scene_add(bmain, scene_strip, method);
+ /* If don't need assign the scene to the strip, nothing else to do. */
+ if (!assign_strip) {
+ return scene_new;
+ }
+
/* As the scene is created in sequencer, do not set the new scene as active.
* This is useful for story-boarding where we want to keep actual scene active.
* The new scene is linked to the active strip and the viewport updated. */
@@ -291,7 +299,7 @@ static int scene_new_sequencer_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
int type = RNA_enum_get(op->ptr, "type");
- if (ED_scene_sequencer_add(bmain, C, type) == NULL) {
+ if (ED_scene_sequencer_add(bmain, C, type, true) == NULL) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index d5385181055..43c19670a41 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1315,7 +1315,7 @@ void ED_screen_full_restore(bContext *C, ScrArea *area)
else {
ED_screen_state_toggle(C, win, area, state);
}
- /* warning: 'area' may be freed */
+ /* WARNING: 'area' may be freed */
}
/* otherwise just tile the area again */
else {
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 08eed52f440..d3bf28798c4 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -27,8 +27,8 @@ set(INC
)
set(SRC
- curves_sculpt_3d_brush.cc
curves_sculpt_add.cc
+ curves_sculpt_brush.cc
curves_sculpt_comb.cc
curves_sculpt_delete.cc
curves_sculpt_grow_shrink.cc
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc
index 0d399419ad8..d7f4b71d2d0 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc
@@ -18,9 +18,11 @@
#include "BKE_bvhutils.h"
#include "BKE_context.h"
#include "BKE_curves.hh"
+#include "BKE_curves_utils.hh"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_paint.h"
+#include "BKE_report.h"
#include "BKE_spline.hh"
#include "DNA_brush_enums.h"
@@ -35,6 +37,8 @@
#include "ED_screen.h"
#include "ED_view3d.h"
+#include "WM_api.h"
+
/**
* The code below uses a prefix naming convention to indicate the coordinate space:
* cu: Local space of the curves object that is being edited.
@@ -62,7 +66,7 @@ class AddOperation : public CurvesSculptStrokeOperation {
}
}
- void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override;
+ void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override;
};
static void initialize_straight_curve_positions(const float3 &p1,
@@ -81,11 +85,12 @@ static void initialize_straight_curve_positions(const float3 &p1,
*/
struct AddOperationExecutor {
AddOperation *self_ = nullptr;
- Depsgraph *depsgraph_ = nullptr;
- Scene *scene_ = nullptr;
- Object *object_ = nullptr;
+ const Depsgraph *depsgraph_ = nullptr;
+ const Scene *scene_ = nullptr;
ARegion *region_ = nullptr;
- View3D *v3d_ = nullptr;
+ const View3D *v3d_ = nullptr;
+
+ Object *object_ = nullptr;
Curves *curves_id_ = nullptr;
CurvesGeometry *curves_ = nullptr;
@@ -94,9 +99,9 @@ struct AddOperationExecutor {
Span<MLoopTri> surface_looptris_;
Span<float3> corner_normals_su_;
- CurvesSculpt *curves_sculpt_ = nullptr;
- Brush *brush_ = nullptr;
- BrushCurvesSculptSettings *brush_settings_ = nullptr;
+ const CurvesSculpt *curves_sculpt_ = nullptr;
+ const Brush *brush_ = nullptr;
+ const BrushCurvesSculptSettings *brush_settings_ = nullptr;
float brush_radius_re_;
float2 brush_pos_re_;
@@ -104,10 +109,11 @@ struct AddOperationExecutor {
bool use_front_face_;
bool interpolate_length_;
bool interpolate_shape_;
+ bool interpolate_point_count_;
bool use_interpolation_;
float new_curve_length_;
int add_amount_;
- int points_per_curve_ = 8;
+ int constant_points_per_curve_;
/** Various matrices to convert between coordinate spaces. */
float4x4 curves_to_world_mat_;
@@ -128,14 +134,23 @@ struct AddOperationExecutor {
Vector<int> looptri_indices;
};
- void execute(AddOperation &self, bContext *C, const StrokeExtension &stroke_extension)
+ struct NeighborInfo {
+ /* Curve index of the neighbor. */
+ int index;
+ /* The weights of all neighbors of a new curve add up to 1. */
+ float weight;
+ };
+ static constexpr int max_neighbors = 5;
+ using NeighborsVector = Vector<NeighborInfo, max_neighbors>;
+
+ void execute(AddOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
{
self_ = &self;
- depsgraph_ = CTX_data_depsgraph_pointer(C);
- scene_ = CTX_data_scene(C);
- object_ = CTX_data_active_object(C);
- region_ = CTX_wm_region(C);
- v3d_ = CTX_wm_view3d(C);
+ depsgraph_ = CTX_data_depsgraph_pointer(&C);
+ scene_ = CTX_data_scene(&C);
+ object_ = CTX_data_active_object(&C);
+ region_ = CTX_wm_region(&C);
+ v3d_ = CTX_wm_view3d(&C);
curves_id_ = static_cast<Curves *>(object_->data);
curves_ = &CurvesGeometry::wrap(curves_id_->geometry);
@@ -162,18 +177,21 @@ struct AddOperationExecutor {
surface_->totloop};
curves_sculpt_ = scene_->toolsettings->curves_sculpt;
- brush_ = BKE_paint_brush(&curves_sculpt_->paint);
+ brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint);
brush_settings_ = brush_->curves_sculpt_settings;
- brush_radius_re_ = BKE_brush_size_get(scene_, brush_);
+ brush_radius_re_ = brush_radius_get(*scene_, *brush_, stroke_extension);
brush_pos_re_ = stroke_extension.mouse_position;
use_front_face_ = brush_->flag & BRUSH_FRONTFACE;
const eBrushFalloffShape falloff_shape = static_cast<eBrushFalloffShape>(
brush_->falloff_shape);
add_amount_ = std::max(0, brush_settings_->add_amount);
+ constant_points_per_curve_ = std::max(2, brush_settings_->points_per_curve);
interpolate_length_ = brush_settings_->flag & BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_LENGTH;
interpolate_shape_ = brush_settings_->flag & BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_SHAPE;
- use_interpolation_ = interpolate_length_ || interpolate_shape_;
+ interpolate_point_count_ = brush_settings_->flag &
+ BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_POINT_COUNT;
+ use_interpolation_ = interpolate_length_ || interpolate_shape_ || interpolate_point_count_;
new_curve_length_ = brush_settings_->curve_length;
tot_old_curves_ = curves_->curves_num();
@@ -183,7 +201,9 @@ struct AddOperationExecutor {
return;
}
- RandomNumberGenerator rng{(uint32_t)(PIL_check_seconds_timer() * 1000000.0f)};
+ const double time = PIL_check_seconds_timer() * 1000000.0;
+ /* Use a pointer cast to avoid overflow warnings. */
+ RandomNumberGenerator rng{*(uint32_t *)(&time)};
BKE_bvhtree_from_mesh_get(&surface_bvh_, surface_, BVHTREE_FROM_LOOPTRI, 2);
BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_); });
@@ -194,13 +214,13 @@ struct AddOperationExecutor {
/* Sample points on the surface using one of multiple strategies. */
AddedPoints added_points;
if (add_amount_ == 1) {
- this->sample_in_center(added_points);
+ this->sample_in_center_with_symmetry(added_points);
}
else if (falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
- this->sample_projected(rng, added_points);
+ this->sample_projected_with_symmetry(rng, added_points);
}
else if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
- this->sample_spherical(rng, added_points);
+ this->sample_spherical_with_symmetry(rng, added_points);
}
else {
BLI_assert_unreachable();
@@ -211,20 +231,31 @@ struct AddOperationExecutor {
return;
}
+ Array<NeighborsVector> neighbors_per_curve;
if (use_interpolation_) {
this->ensure_curve_roots_kdtree();
+ neighbors_per_curve = this->find_curve_neighbors(added_points);
}
+ /* Resize to add the new curves, building the offsets in the array owned by the curves. */
const int tot_added_curves = added_points.bary_coords.size();
- const int tot_added_points = tot_added_curves * points_per_curve_;
+ curves_->resize(curves_->points_num(), curves_->curves_num() + tot_added_curves);
+ if (interpolate_point_count_) {
+ this->initialize_curve_offsets_with_interpolation(neighbors_per_curve);
+ }
+ else {
+ this->initialize_curve_offsets_without_interpolation(constant_points_per_curve_);
+ }
+
+ /* Resize to add the correct point count calculated as part of building the offsets. */
+ curves_->resize(curves_->offsets().last(), curves_->curves_num());
- curves_->resize(curves_->points_num() + tot_added_points,
- curves_->curves_num() + tot_added_curves);
+ this->initialize_attributes(added_points, neighbors_per_curve);
- threading::parallel_invoke([&]() { this->initialize_curve_offsets(tot_added_curves); },
- [&]() { this->initialize_attributes(added_points); });
+ curves_->update_curve_types();
DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, &curves_id_->id);
ED_region_tag_redraw(region_);
}
@@ -241,13 +272,27 @@ struct AddOperationExecutor {
/**
* Sample a single point exactly at the mouse position.
*/
- void sample_in_center(AddedPoints &r_added_points)
+ void sample_in_center_with_symmetry(AddedPoints &r_added_points)
{
float3 ray_start_wo, ray_end_wo;
ED_view3d_win_to_segment_clipped(
depsgraph_, region_, v3d_, brush_pos_re_, ray_start_wo, ray_end_wo, true);
const float3 ray_start_su = world_to_surface_mat_ * ray_start_wo;
const float3 ray_end_su = world_to_surface_mat_ * ray_end_wo;
+
+ const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms(
+ eCurvesSymmetryType(curves_id_->symmetry));
+
+ for (const float4x4 &brush_transform : symmetry_brush_transforms) {
+ this->sample_in_center(
+ r_added_points, brush_transform * ray_start_su, brush_transform * ray_end_su);
+ }
+ }
+
+ void sample_in_center(AddedPoints &r_added_points,
+ const float3 &ray_start_su,
+ const float3 &ray_end_su)
+ {
const float3 ray_direction_su = math::normalize(ray_end_su - ray_start_su);
BVHTreeRayHit ray_hit;
@@ -280,11 +325,23 @@ struct AddOperationExecutor {
/**
* Sample points by shooting rays within the brush radius in the 3D view.
*/
- void sample_projected(RandomNumberGenerator &rng, AddedPoints &r_added_points)
+ void sample_projected_with_symmetry(RandomNumberGenerator &rng, AddedPoints &r_added_points)
{
+ const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms(
+ eCurvesSymmetryType(curves_id_->symmetry));
+ for (const float4x4 &brush_transform : symmetry_brush_transforms) {
+ this->sample_projected(rng, r_added_points, brush_transform);
+ }
+ }
+
+ void sample_projected(RandomNumberGenerator &rng,
+ AddedPoints &r_added_points,
+ const float4x4 &brush_transform)
+ {
+ const int old_amount = r_added_points.bary_coords.size();
const int max_iterations = std::max(100'000, add_amount_ * 10);
int current_iteration = 0;
- while (r_added_points.bary_coords.size() < add_amount_) {
+ while (r_added_points.bary_coords.size() < old_amount + add_amount_) {
if (current_iteration++ >= max_iterations) {
break;
}
@@ -296,8 +353,8 @@ struct AddOperationExecutor {
float3 ray_start_wo, ray_end_wo;
ED_view3d_win_to_segment_clipped(
depsgraph_, region_, v3d_, pos_re, ray_start_wo, ray_end_wo, true);
- const float3 ray_start_su = world_to_surface_mat_ * ray_start_wo;
- const float3 ray_end_su = world_to_surface_mat_ * ray_end_wo;
+ const float3 ray_start_su = brush_transform * (world_to_surface_mat_ * ray_start_wo);
+ const float3 ray_end_su = brush_transform * (world_to_surface_mat_ * ray_end_wo);
const float3 ray_direction_su = math::normalize(ray_end_su - ray_start_su);
BVHTreeRayHit ray_hit;
@@ -339,7 +396,7 @@ struct AddOperationExecutor {
/**
* Sample points in a 3D sphere around the surface position that the mouse hovers over.
*/
- void sample_spherical(RandomNumberGenerator &rng, AddedPoints &r_added_points)
+ void sample_spherical_with_symmetry(RandomNumberGenerator &rng, AddedPoints &r_added_points)
{
/* Find ray that starts in the center of the brush. */
float3 brush_ray_start_wo, brush_ray_end_wo;
@@ -347,7 +404,6 @@ struct AddOperationExecutor {
depsgraph_, region_, v3d_, brush_pos_re_, brush_ray_start_wo, brush_ray_end_wo, true);
const float3 brush_ray_start_su = world_to_surface_mat_ * brush_ray_start_wo;
const float3 brush_ray_end_su = world_to_surface_mat_ * brush_ray_end_wo;
- const float3 brush_ray_direction_su = math::normalize(brush_ray_end_su - brush_ray_start_su);
/* Find ray that starts on the boundary of the brush. That is used to compute the brush radius
* in 3D. */
@@ -362,6 +418,27 @@ struct AddOperationExecutor {
const float3 brush_radius_ray_start_su = world_to_surface_mat_ * brush_radius_ray_start_wo;
const float3 brush_radius_ray_end_su = world_to_surface_mat_ * brush_radius_ray_end_wo;
+ const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms(
+ eCurvesSymmetryType(curves_id_->symmetry));
+ for (const float4x4 &brush_transform : symmetry_brush_transforms) {
+ this->sample_spherical(rng,
+ r_added_points,
+ brush_transform * brush_ray_start_su,
+ brush_transform * brush_ray_end_su,
+ brush_transform * brush_radius_ray_start_su,
+ brush_transform * brush_radius_ray_end_su);
+ }
+ }
+
+ void sample_spherical(RandomNumberGenerator &rng,
+ AddedPoints &r_added_points,
+ const float3 &brush_ray_start_su,
+ const float3 &brush_ray_end_su,
+ const float3 &brush_radius_ray_start_su,
+ const float3 &brush_radius_ray_end_su)
+ {
+ const float3 brush_ray_direction_su = math::normalize(brush_ray_end_su - brush_ray_start_su);
+
BVHTreeRayHit ray_hit;
ray_hit.dist = FLT_MAX;
ray_hit.index = -1;
@@ -426,7 +503,8 @@ struct AddOperationExecutor {
const int max_iterations = 5;
int current_iteration = 0;
- while (r_added_points.bary_coords.size() < add_amount_) {
+ const int old_amount = r_added_points.bary_coords.size();
+ while (r_added_points.bary_coords.size() < old_amount + add_amount_) {
if (current_iteration++ >= max_iterations) {
break;
}
@@ -506,8 +584,8 @@ struct AddOperationExecutor {
}
/* Remove samples when there are too many. */
- while (r_added_points.bary_coords.size() > add_amount_) {
- const int index_to_remove = rng.get_int32(r_added_points.bary_coords.size());
+ while (r_added_points.bary_coords.size() > old_amount + add_amount_) {
+ const int index_to_remove = rng.get_int32(add_amount_) + old_amount;
r_added_points.bary_coords.remove_and_reorder(index_to_remove);
r_added_points.looptri_indices.remove_and_reorder(index_to_remove);
r_added_points.positions_cu.remove_and_reorder(index_to_remove);
@@ -527,33 +605,42 @@ struct AddOperationExecutor {
}
}
- void initialize_curve_offsets(const int tot_added_curves)
+ void initialize_curve_offsets_with_interpolation(const Span<NeighborsVector> neighbors_per_curve)
{
- MutableSpan<int> offsets = curves_->offsets_for_write();
- threading::parallel_for(IndexRange(tot_added_curves), 1024, [&](const IndexRange range) {
- for (const int i : range) {
- const int curve_i = tot_old_curves_ + i;
- offsets[curve_i + 1] = tot_old_points_ + (i + 1) * points_per_curve_;
+ MutableSpan<int> new_offsets = curves_->offsets_for_write().drop_front(tot_old_curves_);
+
+ attribute_math::DefaultMixer<int> mixer{new_offsets};
+ threading::parallel_for(neighbors_per_curve.index_range(), 1024, [&](IndexRange curves_range) {
+ for (const int i : curves_range) {
+ if (neighbors_per_curve[i].is_empty()) {
+ mixer.mix_in(i, constant_points_per_curve_, 1.0f);
+ }
+ else {
+ for (const NeighborInfo &neighbor : neighbors_per_curve[i]) {
+ const int neighbor_points_num = curves_->points_for_curve(neighbor.index).size();
+ mixer.mix_in(i, neighbor_points_num, neighbor.weight);
+ }
+ }
}
});
- }
+ mixer.finalize();
- struct NeighborInfo {
- /* Curve index of the neighbor. */
- int index;
- /* The weights of all neighbors of a new curve add up to 1. */
- float weight;
- };
- static constexpr int max_neighbors = 5;
- using NeighborsVector = Vector<NeighborInfo, max_neighbors>;
+ bke::curves::accumulate_counts_to_offsets(new_offsets, tot_old_points_);
+ }
- void initialize_attributes(const AddedPoints &added_points)
+ void initialize_curve_offsets_without_interpolation(const int points_per_curve)
{
- Array<NeighborsVector> neighbors_per_curve;
- if (use_interpolation_) {
- neighbors_per_curve = this->find_curve_neighbors(added_points);
+ MutableSpan<int> new_offsets = curves_->offsets_for_write().drop_front(tot_old_curves_);
+ int offset = tot_old_points_;
+ for (const int i : new_offsets.index_range()) {
+ new_offsets[i] = offset;
+ offset += points_per_curve;
}
+ }
+ void initialize_attributes(const AddedPoints &added_points,
+ const Span<NeighborsVector> neighbors_per_curve)
+ {
Array<float> new_lengths_cu(added_points.bary_coords.size());
if (interpolate_length_) {
this->interpolate_lengths(neighbors_per_curve, new_lengths_cu);
@@ -613,10 +700,9 @@ struct AddOperationExecutor {
for (const NeighborInfo &neighbor : neighbors) {
const IndexRange neighbor_points = curves_->points_for_curve(neighbor.index);
float neighbor_length = 0.0f;
- const int tot_segments = neighbor_points.size() - 1;
- for (const int segment_i : IndexRange(tot_segments)) {
- const float3 &p1 = positions_cu[neighbor_points[segment_i]];
- const float3 &p2 = positions_cu[neighbor_points[segment_i] + 1];
+ for (const int segment_i : neighbor_points.drop_back(1)) {
+ const float3 &p1 = positions_cu[segment_i];
+ const float3 &p2 = positions_cu[segment_i + 1];
neighbor_length += math::distance(p1, p2);
}
length_sum += neighbor.weight * neighbor_length;
@@ -682,15 +768,14 @@ struct AddOperationExecutor {
threading::parallel_for(
added_points.bary_coords.index_range(), 256, [&](const IndexRange range) {
for (const int i : range) {
- const int first_point_i = tot_old_points_ + i * points_per_curve_;
+ const IndexRange points = curves_->points_for_curve(tot_old_curves_ + i);
const float3 &root_cu = added_points.positions_cu[i];
const float length = lengths_cu[i];
const float3 &normal_su = normals_su[i];
const float3 normal_cu = math::normalize(surface_to_curves_normal_mat_ * normal_su);
const float3 tip_cu = root_cu + length * normal_cu;
- initialize_straight_curve_positions(
- root_cu, tip_cu, positions_cu.slice(first_point_i, points_per_curve_));
+ initialize_straight_curve_positions(root_cu, tip_cu, positions_cu.slice(points));
}
});
}
@@ -711,23 +796,22 @@ struct AddOperationExecutor {
added_points.bary_coords.index_range(), 256, [&](const IndexRange range) {
for (const int i : range) {
const Span<NeighborInfo> neighbors = neighbors_per_curve[i];
+ const IndexRange points = curves_->points_for_curve(tot_old_curves_ + i);
const float length_cu = new_lengths_cu[i];
const float3 &normal_su = new_normals_su[i];
const float3 normal_cu = math::normalize(surface_to_curves_normal_mat_ * normal_su);
const float3 &root_cu = added_points.positions_cu[i];
- const int first_point_i = tot_old_points_ + i * points_per_curve_;
if (neighbors.is_empty()) {
/* If there are no neighbors, just make a straight line. */
const float3 tip_cu = root_cu + length_cu * normal_cu;
- initialize_straight_curve_positions(
- root_cu, tip_cu, positions_cu.slice(first_point_i, points_per_curve_));
+ initialize_straight_curve_positions(root_cu, tip_cu, positions_cu.slice(points));
continue;
}
- positions_cu.slice(first_point_i, points_per_curve_).fill(root_cu);
+ positions_cu.slice(points).fill(root_cu);
for (const NeighborInfo &neighbor : neighbors) {
const int neighbor_curve_i = neighbor.index;
@@ -761,8 +845,8 @@ struct AddOperationExecutor {
const float neighbor_length_cu = neighbor_spline.length();
const float length_factor = std::min(1.0f, length_cu / neighbor_length_cu);
- const float resample_factor = (1.0f / (points_per_curve_ - 1.0f)) * length_factor;
- for (const int j : IndexRange(points_per_curve_)) {
+ const float resample_factor = (1.0f / (points.size() - 1.0f)) * length_factor;
+ for (const int j : IndexRange(points.size())) {
const Spline::LookupResult lookup = neighbor_spline.lookup_evaluated_factor(
j * resample_factor);
const float index_factor = lookup.evaluated_index + lookup.factor;
@@ -772,7 +856,7 @@ struct AddOperationExecutor {
const float3 relative_coord = p - neighbor_root_cu;
float3 rotated_relative_coord = relative_coord;
mul_m3_v3(normal_rotation_cu, rotated_relative_coord);
- positions_cu[first_point_i + j] += neighbor.weight * rotated_relative_coord;
+ positions_cu[points[j]] += neighbor.weight * rotated_relative_coord;
}
}
}
@@ -780,14 +864,23 @@ struct AddOperationExecutor {
}
};
-void AddOperation::on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension)
+void AddOperation::on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension)
{
AddOperationExecutor executor;
executor.execute(*this, C, stroke_extension);
}
-std::unique_ptr<CurvesSculptStrokeOperation> new_add_operation()
+std::unique_ptr<CurvesSculptStrokeOperation> new_add_operation(const bContext &C,
+ ReportList *reports)
{
+ const Object &ob_active = *CTX_data_active_object(&C);
+ BLI_assert(ob_active.type == OB_CURVES);
+ const Curves &curves_id = *static_cast<Curves *>(ob_active.data);
+ if (curves_id.surface == nullptr || curves_id.surface->type != OB_MESH) {
+ BKE_report(reports, RPT_WARNING, "Can not use Add brush when there is no surface mesh");
+ return {};
+ }
+
return std::make_unique<AddOperation>();
}
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_3d_brush.cc b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc
index 945bb09c0c6..92ce6ba3153 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_3d_brush.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc
@@ -41,9 +41,9 @@ static std::optional<float3> find_curves_brush_position(const CurvesGeometry &cu
const float3 &ray_start_cu,
const float3 &ray_end_cu,
const float brush_radius_re,
- ARegion &region,
- RegionView3D &rv3d,
- Object &object)
+ const ARegion &region,
+ const RegionView3D &rv3d,
+ const Object &object)
{
/* This value might have to be adjusted based on user feedback. */
const float brush_inner_radius_re = std::min<float>(brush_radius_re, (float)UI_UNIT_X / 3.0f);
@@ -94,11 +94,30 @@ static std::optional<float3> find_curves_brush_position(const CurvesGeometry &cu
for (const int curve_i : curves_range) {
const IndexRange points = curves.points_for_curve(curve_i);
- const int tot_segments = points.size() - 1;
- for (const int segment_i : IndexRange(tot_segments)) {
- const float3 &p1_cu = positions[points[segment_i]];
- const float3 &p2_cu = positions[points[segment_i] + 1];
+ if (points.size() == 1) {
+ const float3 &pos_cu = positions[points.first()];
+
+ const float depth_sq_cu = math::distance_squared(ray_start_cu, pos_cu);
+ if (depth_sq_cu > max_depth_sq_cu) {
+ continue;
+ }
+
+ float2 pos_re;
+ ED_view3d_project_float_v2_m4(&region, pos_cu, pos_re, projection.values);
+
+ BrushPositionCandidate candidate;
+ candidate.position_cu = pos_cu;
+ candidate.depth_sq_cu = depth_sq_cu;
+ candidate.distance_sq_re = math::distance_squared(brush_pos_re, pos_re);
+
+ update_if_better(best_candidate, candidate);
+ continue;
+ }
+
+ for (const int segment_i : points.drop_back(1)) {
+ const float3 &p1_cu = positions[segment_i];
+ const float3 &p2_cu = positions[segment_i + 1];
float2 p1_re, p2_re;
ED_view3d_project_float_v2_m4(&region, p1_cu, p1_re, projection.values);
@@ -116,8 +135,11 @@ static std::optional<float3> find_curves_brush_position(const CurvesGeometry &cu
const float distance_sq_re = math::distance_squared(brush_pos_re, closest_re);
+ float3 brush_position_cu;
+ closest_to_line_segment_v3(brush_position_cu, closest_cu, ray_start_cu, ray_end_cu);
+
BrushPositionCandidate candidate;
- candidate.position_cu = closest_cu;
+ candidate.position_cu = brush_position_cu;
candidate.depth_sq_cu = depth_sq_cu;
candidate.distance_sq_re = distance_sq_re;
@@ -138,23 +160,21 @@ static std::optional<float3> find_curves_brush_position(const CurvesGeometry &cu
return best_candidate.position_cu;
}
-std::optional<CurvesBrush3D> sample_curves_3d_brush(bContext &C,
- Object &curves_object,
+std::optional<CurvesBrush3D> sample_curves_3d_brush(const Depsgraph &depsgraph,
+ const ARegion &region,
+ const View3D &v3d,
+ const RegionView3D &rv3d,
+ const Object &curves_object,
const float2 &brush_pos_re,
const float brush_radius_re)
{
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(&C);
- ARegion *region = CTX_wm_region(&C);
- View3D *v3d = CTX_wm_view3d(&C);
- RegionView3D *rv3d = CTX_wm_region_view3d(&C);
-
- Curves &curves_id = *static_cast<Curves *>(curves_object.data);
- CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
- Object *surface_object = curves_id.surface;
+ const Curves &curves_id = *static_cast<Curves *>(curves_object.data);
+ const CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
+ const Object *surface_object = curves_id.surface;
float3 center_ray_start_wo, center_ray_end_wo;
ED_view3d_win_to_segment_clipped(
- depsgraph, region, v3d, brush_pos_re, center_ray_start_wo, center_ray_end_wo, true);
+ &depsgraph, &region, &v3d, brush_pos_re, center_ray_start_wo, center_ray_end_wo, true);
/* Shorten ray when the surface object is hit. */
if (surface_object != nullptr) {
@@ -202,8 +222,8 @@ std::optional<CurvesBrush3D> sample_curves_3d_brush(bContext &C,
center_ray_start_cu,
center_ray_end_cu,
brush_radius_re,
- *region,
- *rv3d,
+ region,
+ rv3d,
curves_object);
if (!brush_position_optional_cu.has_value()) {
/* Nothing found. */
@@ -213,9 +233,9 @@ std::optional<CurvesBrush3D> sample_curves_3d_brush(bContext &C,
/* Determine the 3D brush radius. */
float3 radius_ray_start_wo, radius_ray_end_wo;
- ED_view3d_win_to_segment_clipped(depsgraph,
- region,
- v3d,
+ ED_view3d_win_to_segment_clipped(&depsgraph,
+ &region,
+ &v3d,
brush_pos_re + float2(brush_radius_re, 0.0f),
radius_ray_start_wo,
radius_ray_end_wo,
@@ -229,4 +249,32 @@ std::optional<CurvesBrush3D> sample_curves_3d_brush(bContext &C,
return brush_3d;
}
+Vector<float4x4> get_symmetry_brush_transforms(const eCurvesSymmetryType symmetry)
+{
+ Vector<float4x4> matrices;
+
+ auto symmetry_to_factors = [&](const eCurvesSymmetryType type) -> Span<float> {
+ if (symmetry & type) {
+ static std::array<float, 2> values = {1.0f, -1.0f};
+ return values;
+ }
+ static std::array<float, 1> values = {1.0f};
+ return values;
+ };
+
+ for (const float x : symmetry_to_factors(CURVES_SYMMETRY_X)) {
+ for (const float y : symmetry_to_factors(CURVES_SYMMETRY_Y)) {
+ for (const float z : symmetry_to_factors(CURVES_SYMMETRY_Z)) {
+ float4x4 matrix = float4x4::identity();
+ matrix.values[0][0] = x;
+ matrix.values[1][1] = y;
+ matrix.values[2][2] = z;
+ matrices.append(matrix);
+ }
+ }
+ }
+
+ return matrices;
+}
+
} // namespace blender::ed::sculpt_paint
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc b/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc
index 232d632aa3f..1fcab2290e8 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc
@@ -37,6 +37,8 @@
#include "UI_interface.h"
+#include "WM_api.h"
+
/**
* The code below uses a prefix naming convention to indicate the coordinate space:
* cu: Local space of the curves object that is being edited.
@@ -67,7 +69,7 @@ class CombOperation : public CurvesSculptStrokeOperation {
friend struct CombOperationExecutor;
public:
- void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override;
+ void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override;
};
/**
@@ -76,21 +78,21 @@ class CombOperation : public CurvesSculptStrokeOperation {
*/
struct CombOperationExecutor {
CombOperation *self_ = nullptr;
- bContext *C_ = nullptr;
- Depsgraph *depsgraph_ = nullptr;
- Scene *scene_ = nullptr;
- Object *object_ = nullptr;
+ const Depsgraph *depsgraph_ = nullptr;
+ const Scene *scene_ = nullptr;
ARegion *region_ = nullptr;
- View3D *v3d_ = nullptr;
- RegionView3D *rv3d_ = nullptr;
+ const View3D *v3d_ = nullptr;
+ const RegionView3D *rv3d_ = nullptr;
- CurvesSculpt *curves_sculpt_ = nullptr;
- Brush *brush_ = nullptr;
- float brush_radius_re_;
+ const CurvesSculpt *curves_sculpt_ = nullptr;
+ const Brush *brush_ = nullptr;
+ float brush_radius_base_re_;
+ float brush_radius_factor_;
float brush_strength_;
eBrushFalloffShape falloff_shape_;
+ Object *object_ = nullptr;
Curves *curves_id_ = nullptr;
CurvesGeometry *curves_ = nullptr;
@@ -110,24 +112,24 @@ struct CombOperationExecutor {
BVHTreeFromMesh surface_bvh_;
- void execute(CombOperation &self, bContext *C, const StrokeExtension &stroke_extension)
+ void execute(CombOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
{
self_ = &self;
BLI_SCOPED_DEFER([&]() { self_->brush_pos_last_re_ = stroke_extension.mouse_position; });
- C_ = C;
- depsgraph_ = CTX_data_depsgraph_pointer(C);
- scene_ = CTX_data_scene(C);
- object_ = CTX_data_active_object(C);
- region_ = CTX_wm_region(C);
- v3d_ = CTX_wm_view3d(C);
- rv3d_ = CTX_wm_region_view3d(C);
+ depsgraph_ = CTX_data_depsgraph_pointer(&C);
+ scene_ = CTX_data_scene(&C);
+ object_ = CTX_data_active_object(&C);
+ region_ = CTX_wm_region(&C);
+ v3d_ = CTX_wm_view3d(&C);
+ rv3d_ = CTX_wm_region_view3d(&C);
curves_sculpt_ = scene_->toolsettings->curves_sculpt;
- brush_ = BKE_paint_brush(&curves_sculpt_->paint);
- brush_radius_re_ = BKE_brush_size_get(scene_, brush_);
- brush_strength_ = BKE_brush_alpha_get(scene_, brush_);
+ brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint);
+ brush_radius_base_re_ = BKE_brush_size_get(scene_, brush_);
+ brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
+ brush_strength_ = brush_strength_get(*scene_, *brush_, stroke_extension);
curves_to_world_mat_ = object_->obmat;
world_to_curves_mat_ = curves_to_world_mat_.inverted();
@@ -173,10 +175,10 @@ struct CombOperationExecutor {
EnumerableThreadSpecific<Vector<int>> changed_curves;
if (falloff_shape_ == PAINT_FALLOFF_SHAPE_TUBE) {
- this->comb_projected(changed_curves);
+ this->comb_projected_with_symmetry(changed_curves);
}
else if (falloff_shape_ == PAINT_FALLOFF_SHAPE_SPHERE) {
- this->comb_spherical(changed_curves);
+ this->comb_spherical_with_symmetry(changed_curves);
}
else {
BLI_assert_unreachable();
@@ -186,20 +188,34 @@ struct CombOperationExecutor {
curves_->tag_positions_changed();
DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, &curves_id_->id);
ED_region_tag_redraw(region_);
}
/**
* Do combing in screen space.
*/
- void comb_projected(EnumerableThreadSpecific<Vector<int>> &r_changed_curves)
+ void comb_projected_with_symmetry(EnumerableThreadSpecific<Vector<int>> &r_changed_curves)
{
+ const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms(
+ eCurvesSymmetryType(curves_id_->symmetry));
+ for (const float4x4 &brush_transform : symmetry_brush_transforms) {
+ this->comb_projected(r_changed_curves, brush_transform);
+ }
+ }
+
+ void comb_projected(EnumerableThreadSpecific<Vector<int>> &r_changed_curves,
+ const float4x4 &brush_transform)
+ {
+ const float4x4 brush_transform_inv = brush_transform.inverted();
+
MutableSpan<float3> positions_cu = curves_->positions_for_write();
float4x4 projection;
ED_view3d_ob_project_mat_get(rv3d_, object_, projection.values);
- const float brush_radius_sq_re = pow2f(brush_radius_re_);
+ const float brush_radius_re = brush_radius_base_re_ * brush_radius_factor_;
+ const float brush_radius_sq_re = pow2f(brush_radius_re);
threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) {
Vector<int> &local_changed_curves = r_changed_curves.local();
@@ -207,7 +223,7 @@ struct CombOperationExecutor {
bool curve_changed = false;
const IndexRange points = curves_->points_for_curve(curve_i);
for (const int point_i : points.drop_front(1)) {
- const float3 old_pos_cu = positions_cu[point_i];
+ const float3 old_pos_cu = brush_transform_inv * positions_cu[point_i];
/* Find the position of the point in screen space. */
float2 old_pos_re;
@@ -223,7 +239,7 @@ struct CombOperationExecutor {
const float distance_to_brush_re = std::sqrt(distance_to_brush_sq_re);
/* A falloff that is based on how far away the point is from the stroke. */
const float radius_falloff = BKE_brush_curve_strength(
- brush_, distance_to_brush_re, brush_radius_re_);
+ brush_, distance_to_brush_re, brush_radius_re);
/* Combine the falloff and brush strength. */
const float weight = brush_strength_ * radius_falloff;
@@ -232,7 +248,8 @@ struct CombOperationExecutor {
float3 new_position_wo;
ED_view3d_win_to_3d(
v3d_, region_, curves_to_world_mat_ * old_pos_cu, new_position_re, new_position_wo);
- const float3 new_position_cu = world_to_curves_mat_ * new_position_wo;
+ const float3 new_position_cu = brush_transform *
+ (world_to_curves_mat_ * new_position_wo);
positions_cu[point_i] = new_position_cu;
curve_changed = true;
@@ -247,10 +264,8 @@ struct CombOperationExecutor {
/**
* Do combing in 3D space.
*/
- void comb_spherical(EnumerableThreadSpecific<Vector<int>> &r_changed_curves)
+ void comb_spherical_with_symmetry(EnumerableThreadSpecific<Vector<int>> &r_changed_curves)
{
- MutableSpan<float3> positions_cu = curves_->positions_for_write();
-
float4x4 projection;
ED_view3d_ob_project_mat_get(rv3d_, object_, projection.values);
@@ -268,10 +283,26 @@ struct CombOperationExecutor {
const float3 brush_start_cu = world_to_curves_mat_ * brush_start_wo;
const float3 brush_end_cu = world_to_curves_mat_ * brush_end_wo;
- const float3 brush_diff_cu = brush_end_cu - brush_start_cu;
+ const float brush_radius_cu = self_->brush_3d_.radius_cu * brush_radius_factor_;
+
+ const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms(
+ eCurvesSymmetryType(curves_id_->symmetry));
+ for (const float4x4 &brush_transform : symmetry_brush_transforms) {
+ this->comb_spherical(r_changed_curves,
+ brush_transform * brush_start_cu,
+ brush_transform * brush_end_cu,
+ brush_radius_cu);
+ }
+ }
- const float brush_radius_cu = self_->brush_3d_.radius_cu;
+ void comb_spherical(EnumerableThreadSpecific<Vector<int>> &r_changed_curves,
+ const float3 &brush_start_cu,
+ const float3 &brush_end_cu,
+ const float brush_radius_cu)
+ {
+ MutableSpan<float3> positions_cu = curves_->positions_for_write();
const float brush_radius_sq_cu = pow2f(brush_radius_cu);
+ const float3 brush_diff_cu = brush_end_cu - brush_start_cu;
threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) {
Vector<int> &local_changed_curves = r_changed_curves.local();
@@ -314,7 +345,7 @@ struct CombOperationExecutor {
void initialize_spherical_brush_reference_point()
{
std::optional<CurvesBrush3D> brush_3d = sample_curves_3d_brush(
- *C_, *object_, brush_pos_re_, brush_radius_re_);
+ *depsgraph_, *region_, *v3d_, *rv3d_, *object_, brush_pos_re_, brush_radius_base_re_);
if (brush_3d.has_value()) {
self_->brush_3d_ = *brush_3d;
}
@@ -353,11 +384,11 @@ struct CombOperationExecutor {
threading::parallel_for(changed_curves.index_range(), 256, [&](const IndexRange range) {
for (const int curve_i : changed_curves.as_span().slice(range)) {
const IndexRange points = curves_->points_for_curve(curve_i);
- for (const int segment_i : IndexRange(points.size() - 1)) {
- const float3 &p1_cu = positions_cu[points[segment_i]];
- float3 &p2_cu = positions_cu[points[segment_i] + 1];
+ for (const int segment_i : points.drop_back(1)) {
+ const float3 &p1_cu = positions_cu[segment_i];
+ float3 &p2_cu = positions_cu[segment_i + 1];
const float3 direction = math::normalize(p2_cu - p1_cu);
- const float expected_length_cu = expected_lengths_cu[points[segment_i]];
+ const float expected_length_cu = expected_lengths_cu[segment_i];
p2_cu = p1_cu + direction * expected_length_cu;
}
}
@@ -366,7 +397,7 @@ struct CombOperationExecutor {
}
};
-void CombOperation::on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension)
+void CombOperation::on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension)
{
CombOperationExecutor executor;
executor.execute(*this, C, stroke_extension);
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_delete.cc b/source/blender/editors/sculpt_paint/curves_sculpt_delete.cc
index 2841a19d677..323e99df099 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_delete.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_delete.cc
@@ -35,6 +35,8 @@
#include "ED_screen.h"
#include "ED_view3d.h"
+#include "WM_api.h"
+
/**
* The code below uses a suffix naming convention to indicate the coordinate space:
* cu: Local space of the curves object that is being edited.
@@ -48,62 +50,56 @@ using blender::bke::CurvesGeometry;
class DeleteOperation : public CurvesSculptStrokeOperation {
private:
- float2 brush_pos_prev_re_;
-
CurvesBrush3D brush_3d_;
friend struct DeleteOperationExecutor;
public:
- void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override;
+ void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override;
};
struct DeleteOperationExecutor {
DeleteOperation *self_ = nullptr;
- bContext *C_ = nullptr;
- Depsgraph *depsgraph_ = nullptr;
- Scene *scene_ = nullptr;
- Object *object_ = nullptr;
+ const Depsgraph *depsgraph_ = nullptr;
+ const Scene *scene_ = nullptr;
ARegion *region_ = nullptr;
- View3D *v3d_ = nullptr;
- RegionView3D *rv3d_ = nullptr;
+ const View3D *v3d_ = nullptr;
+ const RegionView3D *rv3d_ = nullptr;
+ Object *object_ = nullptr;
Curves *curves_id_ = nullptr;
CurvesGeometry *curves_ = nullptr;
- CurvesSculpt *curves_sculpt_ = nullptr;
- Brush *brush_ = nullptr;
- float brush_radius_re_;
+ const CurvesSculpt *curves_sculpt_ = nullptr;
+ const Brush *brush_ = nullptr;
+ float brush_radius_base_re_;
+ float brush_radius_factor_;
float2 brush_pos_re_;
- float2 brush_pos_prev_re_;
float4x4 curves_to_world_mat_;
float4x4 world_to_curves_mat_;
- void execute(DeleteOperation &self, bContext *C, const StrokeExtension &stroke_extension)
+ void execute(DeleteOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
{
- BLI_SCOPED_DEFER([&]() { self.brush_pos_prev_re_ = stroke_extension.mouse_position; });
self_ = &self;
- C_ = C;
- depsgraph_ = CTX_data_depsgraph_pointer(C);
- scene_ = CTX_data_scene(C);
- object_ = CTX_data_active_object(C);
- region_ = CTX_wm_region(C);
- v3d_ = CTX_wm_view3d(C);
- rv3d_ = CTX_wm_region_view3d(C);
+ depsgraph_ = CTX_data_depsgraph_pointer(&C);
+ scene_ = CTX_data_scene(&C);
+ object_ = CTX_data_active_object(&C);
+ region_ = CTX_wm_region(&C);
+ v3d_ = CTX_wm_view3d(&C);
+ rv3d_ = CTX_wm_region_view3d(&C);
curves_id_ = static_cast<Curves *>(object_->data);
curves_ = &CurvesGeometry::wrap(curves_id_->geometry);
curves_sculpt_ = scene_->toolsettings->curves_sculpt;
- brush_ = BKE_paint_brush(&curves_sculpt_->paint);
- brush_radius_re_ = BKE_brush_size_get(scene_, brush_);
+ brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint);
+ brush_radius_base_re_ = BKE_brush_size_get(scene_, brush_);
+ brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
brush_pos_re_ = stroke_extension.mouse_position;
- brush_pos_prev_re_ = stroke_extension.is_first ? stroke_extension.mouse_position :
- self.brush_pos_prev_re_;
curves_to_world_mat_ = object_->obmat;
world_to_curves_mat_ = curves_to_world_mat_.inverted();
@@ -117,115 +113,152 @@ struct DeleteOperationExecutor {
}
}
+ Array<bool> curves_to_delete(curves_->curves_num(), false);
if (falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
- this->delete_projected();
+ this->delete_projected_with_symmetry(curves_to_delete);
}
else if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
- this->delete_spherical();
+ this->delete_spherical_with_symmetry(curves_to_delete);
}
else {
BLI_assert_unreachable();
}
+ Vector<int64_t> indices;
+ const IndexMask mask = index_mask_ops::find_indices_based_on_predicate(
+ curves_->curves_range(), 4096, indices, [&](const int curve_i) {
+ return curves_to_delete[curve_i];
+ });
+
+ curves_->remove_curves(mask);
+
DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, &curves_id_->id);
ED_region_tag_redraw(region_);
}
- void delete_projected()
+ void delete_projected_with_symmetry(MutableSpan<bool> curves_to_delete)
{
+ const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms(
+ eCurvesSymmetryType(curves_id_->symmetry));
+ for (const float4x4 &brush_transform : symmetry_brush_transforms) {
+ this->delete_projected(brush_transform, curves_to_delete);
+ }
+ }
+
+ void delete_projected(const float4x4 &brush_transform, MutableSpan<bool> curves_to_delete)
+ {
+ const float4x4 brush_transform_inv = brush_transform.inverted();
+
float4x4 projection;
ED_view3d_ob_project_mat_get(rv3d_, object_, projection.values);
Span<float3> positions_cu = curves_->positions();
- /* Find indices of curves that have to be removed. */
- Vector<int64_t> indices;
- const IndexMask curves_to_remove = index_mask_ops::find_indices_based_on_predicate(
- curves_->curves_range(), 512, indices, [&](const int curve_i) {
- const IndexRange point_range = curves_->points_for_curve(curve_i);
- for (const int segment_i : IndexRange(point_range.size() - 1)) {
- const float3 pos1_cu = positions_cu[point_range[segment_i]];
- const float3 pos2_cu = positions_cu[point_range[segment_i + 1]];
-
- float2 pos1_re, pos2_re;
- ED_view3d_project_float_v2_m4(region_, pos1_cu, pos1_re, projection.values);
- ED_view3d_project_float_v2_m4(region_, pos2_cu, pos2_re, projection.values);
-
- const float dist = dist_seg_seg_v2(
- pos1_re, pos2_re, brush_pos_prev_re_, brush_pos_re_);
- if (dist <= brush_radius_re_) {
- return true;
- }
- }
- return false;
- });
+ const float brush_radius_re = brush_radius_base_re_ * brush_radius_factor_;
+ const float brush_radius_sq_re = pow2f(brush_radius_re);
+
+ threading::parallel_for(curves_->curves_range(), 512, [&](IndexRange curve_range) {
+ for (const int curve_i : curve_range) {
+ const IndexRange points = curves_->points_for_curve(curve_i);
+ if (points.size() == 1) {
+ const float3 pos_cu = brush_transform_inv * positions_cu[points.first()];
+ float2 pos_re;
+ ED_view3d_project_float_v2_m4(region_, pos_cu, pos_re, projection.values);
- curves_->remove_curves(curves_to_remove);
+ if (math::distance_squared(brush_pos_re_, pos_re) <= brush_radius_sq_re) {
+ curves_to_delete[curve_i] = true;
+ }
+ continue;
+ }
+
+ for (const int segment_i : points.drop_back(1)) {
+ const float3 pos1_cu = brush_transform_inv * positions_cu[segment_i];
+ const float3 pos2_cu = brush_transform_inv * positions_cu[segment_i + 1];
+
+ float2 pos1_re, pos2_re;
+ ED_view3d_project_float_v2_m4(region_, pos1_cu, pos1_re, projection.values);
+ ED_view3d_project_float_v2_m4(region_, pos2_cu, pos2_re, projection.values);
+
+ const float dist_sq_re = dist_squared_to_line_segment_v2(
+ brush_pos_re_, pos1_re, pos2_re);
+ if (dist_sq_re <= brush_radius_sq_re) {
+ curves_to_delete[curve_i] = true;
+ break;
+ }
+ }
+ }
+ });
}
- void delete_spherical()
+ void delete_spherical_with_symmetry(MutableSpan<bool> curves_to_delete)
{
- Span<float3> positions_cu = curves_->positions();
-
float4x4 projection;
ED_view3d_ob_project_mat_get(rv3d_, object_, projection.values);
- float3 brush_start_wo, brush_end_wo;
- ED_view3d_win_to_3d(v3d_,
- region_,
- curves_to_world_mat_ * self_->brush_3d_.position_cu,
- brush_pos_prev_re_,
- brush_start_wo);
+ float3 brush_wo;
ED_view3d_win_to_3d(v3d_,
region_,
curves_to_world_mat_ * self_->brush_3d_.position_cu,
brush_pos_re_,
- brush_end_wo);
- const float3 brush_start_cu = world_to_curves_mat_ * brush_start_wo;
- const float3 brush_end_cu = world_to_curves_mat_ * brush_end_wo;
+ brush_wo);
+ const float3 brush_cu = world_to_curves_mat_ * brush_wo;
+
+ const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms(
+ eCurvesSymmetryType(curves_id_->symmetry));
+
+ for (const float4x4 &brush_transform : symmetry_brush_transforms) {
+ this->delete_spherical(brush_transform * brush_cu, curves_to_delete);
+ }
+ }
- const float brush_radius_cu = self_->brush_3d_.radius_cu;
+ void delete_spherical(const float3 &brush_cu, MutableSpan<bool> curves_to_delete)
+ {
+ Span<float3> positions_cu = curves_->positions();
+
+ const float brush_radius_cu = self_->brush_3d_.radius_cu * brush_radius_factor_;
const float brush_radius_sq_cu = pow2f(brush_radius_cu);
- Vector<int64_t> indices;
- const IndexMask curves_to_remove = index_mask_ops::find_indices_based_on_predicate(
- curves_->curves_range(), 512, indices, [&](const int curve_i) {
- const IndexRange points = curves_->points_for_curve(curve_i);
- for (const int segment_i : IndexRange(points.size() - 1)) {
- const float3 pos1_cu = positions_cu[points[segment_i]];
- const float3 pos2_cu = positions_cu[points[segment_i] + 1];
-
- float3 closest_segment_cu, closest_brush_cu;
- isect_seg_seg_v3(pos1_cu,
- pos2_cu,
- brush_start_cu,
- brush_end_cu,
- closest_segment_cu,
- closest_brush_cu);
- const float distance_to_brush_sq_cu = math::distance_squared(closest_segment_cu,
- closest_brush_cu);
- if (distance_to_brush_sq_cu > brush_radius_sq_cu) {
- continue;
- }
- return true;
+ threading::parallel_for(curves_->curves_range(), 512, [&](IndexRange curve_range) {
+ for (const int curve_i : curve_range) {
+ const IndexRange points = curves_->points_for_curve(curve_i);
+
+ if (points.size() == 1) {
+ const float3 &pos_cu = positions_cu[points.first()];
+ const float distance_sq_cu = math::distance_squared(pos_cu, brush_cu);
+ if (distance_sq_cu < brush_radius_sq_cu) {
+ curves_to_delete[curve_i] = true;
}
- return false;
- });
+ continue;
+ }
+
+ for (const int segment_i : points.drop_back(1)) {
+ const float3 &pos1_cu = positions_cu[segment_i];
+ const float3 &pos2_cu = positions_cu[segment_i + 1];
- curves_->remove_curves(curves_to_remove);
+ const float distance_sq_cu = dist_squared_to_line_segment_v3(brush_cu, pos1_cu, pos2_cu);
+ if (distance_sq_cu > brush_radius_sq_cu) {
+ continue;
+ }
+ curves_to_delete[curve_i] = true;
+ break;
+ }
+ }
+ });
}
void initialize_spherical_brush_reference_point()
{
std::optional<CurvesBrush3D> brush_3d = sample_curves_3d_brush(
- *C_, *object_, brush_pos_re_, brush_radius_re_);
+ *depsgraph_, *region_, *v3d_, *rv3d_, *object_, brush_pos_re_, brush_radius_base_re_);
if (brush_3d.has_value()) {
self_->brush_3d_ = *brush_3d;
}
}
};
-void DeleteOperation::on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension)
+void DeleteOperation::on_stroke_extended(const bContext &C,
+ const StrokeExtension &stroke_extension)
{
DeleteOperationExecutor executor;
executor.execute(*this, C, stroke_extension);
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc b/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc
index 6228a643a76..b0a6d6ef29c 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc
@@ -36,6 +36,8 @@
#include "ED_screen.h"
#include "ED_view3d.h"
+#include "WM_api.h"
+
#include "curves_sculpt_intern.hh"
/**
@@ -68,10 +70,10 @@ class CurvesEffect {
*/
class ShrinkCurvesEffect : public CurvesEffect {
private:
- Brush &brush_;
+ const Brush &brush_;
public:
- ShrinkCurvesEffect(Brush &brush) : brush_(brush)
+ ShrinkCurvesEffect(const Brush &brush) : brush_(brush)
{
}
@@ -203,10 +205,10 @@ class ExtrapolateCurvesEffect : public CurvesEffect {
class ScaleCurvesEffect : public CurvesEffect {
private:
bool scale_up_;
- Brush &brush_;
+ const Brush &brush_;
public:
- ScaleCurvesEffect(bool scale_up, Brush &brush) : scale_up_(scale_up), brush_(brush)
+ ScaleCurvesEffect(bool scale_up, const Brush &brush) : scale_up_(scale_up), brush_(brush)
{
}
@@ -261,7 +263,7 @@ class CurvesEffectOperation : public CurvesSculptStrokeOperation {
{
}
- void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override;
+ void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override;
};
/**
@@ -270,20 +272,21 @@ class CurvesEffectOperation : public CurvesSculptStrokeOperation {
*/
struct CurvesEffectOperationExecutor {
CurvesEffectOperation *self_ = nullptr;
- Depsgraph *depsgraph_ = nullptr;
- Scene *scene_ = nullptr;
- Object *object_ = nullptr;
+ const Depsgraph *depsgraph_ = nullptr;
+ const Scene *scene_ = nullptr;
ARegion *region_ = nullptr;
- View3D *v3d_ = nullptr;
- RegionView3D *rv3d_ = nullptr;
+ const View3D *v3d_ = nullptr;
+ const RegionView3D *rv3d_ = nullptr;
+ Object *object_ = nullptr;
Curves *curves_id_ = nullptr;
CurvesGeometry *curves_ = nullptr;
- Brush *brush_ = nullptr;
- float brush_radius_re_;
- float brush_radius_sq_re_;
+ const Brush *brush_ = nullptr;
+ float brush_radius_base_re_;
+ float brush_radius_factor_;
float brush_strength_;
+
eBrushFalloffShape falloff_shape_;
float4x4 curves_to_world_mat_;
@@ -297,17 +300,19 @@ struct CurvesEffectOperationExecutor {
Vector<float> move_distances_cu;
};
- void execute(CurvesEffectOperation &self, bContext *C, const StrokeExtension &stroke_extension)
+ void execute(CurvesEffectOperation &self,
+ const bContext &C,
+ const StrokeExtension &stroke_extension)
{
BLI_SCOPED_DEFER([&]() { self.last_mouse_position_ = stroke_extension.mouse_position; });
self_ = &self;
- depsgraph_ = CTX_data_depsgraph_pointer(C);
- scene_ = CTX_data_scene(C);
- object_ = CTX_data_active_object(C);
- region_ = CTX_wm_region(C);
- v3d_ = CTX_wm_view3d(C);
- rv3d_ = CTX_wm_region_view3d(C);
+ depsgraph_ = CTX_data_depsgraph_pointer(&C);
+ scene_ = CTX_data_scene(&C);
+ object_ = CTX_data_active_object(&C);
+ region_ = CTX_wm_region(&C);
+ v3d_ = CTX_wm_view3d(&C);
+ rv3d_ = CTX_wm_region_view3d(&C);
curves_id_ = static_cast<Curves *>(object_->data);
curves_ = &CurvesGeometry::wrap(curves_id_->geometry);
@@ -315,11 +320,14 @@ struct CurvesEffectOperationExecutor {
return;
}
- CurvesSculpt &curves_sculpt = *scene_->toolsettings->curves_sculpt;
- brush_ = BKE_paint_brush(&curves_sculpt.paint);
- brush_radius_re_ = BKE_brush_size_get(scene_, brush_);
- brush_strength_ = BKE_brush_alpha_get(scene_, brush_);
- brush_radius_sq_re_ = pow2f(brush_radius_re_);
+ const CurvesSculpt &curves_sculpt = *scene_->toolsettings->curves_sculpt;
+ brush_ = BKE_paint_brush_for_read(&curves_sculpt.paint);
+ brush_strength_ = brush_strength_get(*scene_, *brush_, stroke_extension);
+
+ brush_radius_base_re_ = BKE_brush_size_get(scene_, brush_);
+ brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
+ brush_strength_ = brush_strength_get(*scene_, *brush_, stroke_extension);
+
falloff_shape_ = eBrushFalloffShape(brush_->falloff_shape);
curves_to_world_mat_ = object_->obmat;
@@ -331,7 +339,13 @@ struct CurvesEffectOperationExecutor {
if (stroke_extension.is_first) {
if (falloff_shape_ == PAINT_FALLOFF_SHAPE_SPHERE) {
if (std::optional<CurvesBrush3D> brush_3d = sample_curves_3d_brush(
- *C, *object_, stroke_extension.mouse_position, brush_radius_re_)) {
+ *depsgraph_,
+ *region_,
+ *v3d_,
+ *rv3d_,
+ *object_,
+ stroke_extension.mouse_position,
+ brush_radius_base_re_)) {
self.brush_3d_ = *brush_3d;
}
}
@@ -356,6 +370,7 @@ struct CurvesEffectOperationExecutor {
curves_->tag_positions_changed();
DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, &curves_id_->id);
ED_region_tag_redraw(region_);
}
@@ -367,62 +382,75 @@ struct CurvesEffectOperationExecutor {
float4x4 projection;
ED_view3d_ob_project_mat_get(rv3d_, object_, projection.values);
+ const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms(
+ eCurvesSymmetryType(curves_id_->symmetry));
+ Vector<float4x4> symmetry_brush_transforms_inv;
+ for (const float4x4 brush_transform : symmetry_brush_transforms) {
+ symmetry_brush_transforms_inv.append(brush_transform.inverted());
+ }
+
+ const float brush_radius_re = brush_radius_base_re_ * brush_radius_factor_;
+ const float brush_radius_sq_re = pow2f(brush_radius_re);
+
threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) {
Influences &local_influences = influences_for_thread.local();
for (const int curve_i : curves_range) {
const IndexRange points = curves_->points_for_curve(curve_i);
- const int tot_segments = points.size() - 1;
+
float max_move_distance_cu = 0.0f;
- for (const int segment_i : IndexRange(tot_segments)) {
- const float3 &p1_cu = positions_cu[points[segment_i]];
- const float3 &p2_cu = positions_cu[points[segment_i] + 1];
-
- float2 p1_re, p2_re;
- ED_view3d_project_float_v2_m4(region_, p1_cu, p1_re, projection.values);
- ED_view3d_project_float_v2_m4(region_, p2_cu, p2_re, projection.values);
-
- float2 closest_on_brush_re;
- float2 closest_on_segment_re;
- float lambda_on_brush;
- float lambda_on_segment;
- const float dist_to_brush_sq_re = closest_seg_seg_v2(closest_on_brush_re,
- closest_on_segment_re,
- &lambda_on_brush,
- &lambda_on_segment,
- brush_pos_start_re_,
- brush_pos_end_re_,
- p1_re,
- p2_re);
-
- if (dist_to_brush_sq_re > brush_radius_sq_re_) {
- continue;
+ for (const float4x4 &brush_transform_inv : symmetry_brush_transforms_inv) {
+ for (const int segment_i : points.drop_back(1)) {
+ const float3 p1_cu = brush_transform_inv * positions_cu[segment_i];
+ const float3 p2_cu = brush_transform_inv * positions_cu[segment_i + 1];
+
+ float2 p1_re, p2_re;
+ ED_view3d_project_float_v2_m4(region_, p1_cu, p1_re, projection.values);
+ ED_view3d_project_float_v2_m4(region_, p2_cu, p2_re, projection.values);
+
+ float2 closest_on_brush_re;
+ float2 closest_on_segment_re;
+ float lambda_on_brush;
+ float lambda_on_segment;
+ const float dist_to_brush_sq_re = closest_seg_seg_v2(closest_on_brush_re,
+ closest_on_segment_re,
+ &lambda_on_brush,
+ &lambda_on_segment,
+ brush_pos_start_re_,
+ brush_pos_end_re_,
+ p1_re,
+ p2_re);
+
+ if (dist_to_brush_sq_re > brush_radius_sq_re) {
+ continue;
+ }
+
+ const float dist_to_brush_re = std::sqrt(dist_to_brush_sq_re);
+ const float radius_falloff = BKE_brush_curve_strength(
+ brush_, dist_to_brush_re, brush_radius_re);
+ const float weight = brush_strength_ * radius_falloff;
+
+ const float3 closest_on_segment_cu = math::interpolate(
+ p1_cu, p2_cu, lambda_on_segment);
+
+ float3 brush_start_pos_wo, brush_end_pos_wo;
+ ED_view3d_win_to_3d(v3d_,
+ region_,
+ curves_to_world_mat_ * closest_on_segment_cu,
+ brush_pos_start_re_,
+ brush_start_pos_wo);
+ ED_view3d_win_to_3d(v3d_,
+ region_,
+ curves_to_world_mat_ * closest_on_segment_cu,
+ brush_pos_end_re_,
+ brush_end_pos_wo);
+ const float3 brush_start_pos_cu = world_to_curves_mat_ * brush_start_pos_wo;
+ const float3 brush_end_pos_cu = world_to_curves_mat_ * brush_end_pos_wo;
+
+ const float move_distance_cu = weight *
+ math::distance(brush_start_pos_cu, brush_end_pos_cu);
+ max_move_distance_cu = std::max(max_move_distance_cu, move_distance_cu);
}
-
- const float dist_to_brush_re = std::sqrt(dist_to_brush_sq_re);
- const float radius_falloff = BKE_brush_curve_strength(
- brush_, dist_to_brush_re, brush_radius_re_);
- const float weight = brush_strength_ * radius_falloff;
-
- const float3 closest_on_segment_cu = math::interpolate(p1_cu, p2_cu, lambda_on_segment);
-
- float3 brush_start_pos_wo, brush_end_pos_wo;
- ED_view3d_win_to_3d(v3d_,
- region_,
- curves_to_world_mat_ * closest_on_segment_cu,
- brush_pos_start_re_,
- brush_start_pos_wo);
- ED_view3d_win_to_3d(v3d_,
- region_,
- curves_to_world_mat_ * closest_on_segment_cu,
- brush_pos_end_re_,
- brush_end_pos_wo);
- const float3 brush_start_pos_cu = world_to_curves_mat_ * brush_start_pos_wo;
- const float3 brush_end_pos_cu = world_to_curves_mat_ * brush_end_pos_wo;
-
- const float move_distance_cu = weight *
- math::distance(brush_start_pos_cu, brush_end_pos_cu);
- max_move_distance_cu = std::max(max_move_distance_cu, move_distance_cu);
}
if (max_move_distance_cu > 0.0f) {
local_influences.curve_indices.append(curve_i);
@@ -452,41 +480,50 @@ struct CurvesEffectOperationExecutor {
const float3 brush_pos_end_cu = world_to_curves_mat_ * brush_pos_end_wo;
const float3 brush_pos_diff_cu = brush_pos_end_cu - brush_pos_start_cu;
const float brush_pos_diff_length_cu = math::length(brush_pos_diff_cu);
- const float brush_radius_cu = self_->brush_3d_.radius_cu;
+ const float brush_radius_cu = self_->brush_3d_.radius_cu * brush_radius_factor_;
const float brush_radius_sq_cu = pow2f(brush_radius_cu);
+
+ const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms(
+ eCurvesSymmetryType(curves_id_->symmetry));
+
threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) {
Influences &local_influences = influences_for_thread.local();
for (const int curve_i : curves_range) {
const IndexRange points = curves_->points_for_curve(curve_i);
- const int tot_segments = points.size() - 1;
+
float max_move_distance_cu = 0.0f;
- for (const int segment_i : IndexRange(tot_segments)) {
- const float3 &p1_cu = positions_cu[points[segment_i]];
- const float3 &p2_cu = positions_cu[points[segment_i] + 1];
-
- float3 closest_on_segment_cu;
- float3 closest_on_brush_cu;
- isect_seg_seg_v3(p1_cu,
- p2_cu,
- brush_pos_start_cu,
- brush_pos_end_cu,
- closest_on_segment_cu,
- closest_on_brush_cu);
-
- const float dist_to_brush_sq_cu = math::distance_squared(closest_on_segment_cu,
- closest_on_brush_cu);
- if (dist_to_brush_sq_cu > brush_radius_sq_cu) {
- continue;
+ for (const float4x4 &brush_transform : symmetry_brush_transforms) {
+ const float3 brush_pos_start_transformed_cu = brush_transform * brush_pos_start_cu;
+ const float3 brush_pos_end_transformed_cu = brush_transform * brush_pos_end_cu;
+
+ for (const int segment_i : points.drop_back(1)) {
+ const float3 &p1_cu = positions_cu[segment_i];
+ const float3 &p2_cu = positions_cu[segment_i + 1];
+
+ float3 closest_on_segment_cu;
+ float3 closest_on_brush_cu;
+ isect_seg_seg_v3(p1_cu,
+ p2_cu,
+ brush_pos_start_transformed_cu,
+ brush_pos_end_transformed_cu,
+ closest_on_segment_cu,
+ closest_on_brush_cu);
+
+ const float dist_to_brush_sq_cu = math::distance_squared(closest_on_segment_cu,
+ closest_on_brush_cu);
+ if (dist_to_brush_sq_cu > brush_radius_sq_cu) {
+ continue;
+ }
+
+ const float dist_to_brush_cu = std::sqrt(dist_to_brush_sq_cu);
+ const float radius_falloff = BKE_brush_curve_strength(
+ brush_, dist_to_brush_cu, brush_radius_cu);
+ const float weight = brush_strength_ * radius_falloff;
+
+ const float move_distance_cu = weight * brush_pos_diff_length_cu;
+ max_move_distance_cu = std::max(max_move_distance_cu, move_distance_cu);
}
-
- const float dist_to_brush_cu = std::sqrt(dist_to_brush_sq_cu);
- const float radius_falloff = BKE_brush_curve_strength(
- brush_, dist_to_brush_cu, brush_radius_cu);
- const float weight = brush_strength_ * radius_falloff;
-
- const float move_distance_cu = weight * brush_pos_diff_length_cu;
- max_move_distance_cu = std::max(max_move_distance_cu, move_distance_cu);
}
if (max_move_distance_cu > 0.0f) {
local_influences.curve_indices.append(curve_i);
@@ -497,7 +534,7 @@ struct CurvesEffectOperationExecutor {
}
};
-void CurvesEffectOperation::on_stroke_extended(bContext *C,
+void CurvesEffectOperation::on_stroke_extended(const bContext &C,
const StrokeExtension &stroke_extension)
{
CurvesEffectOperationExecutor executor;
@@ -505,10 +542,10 @@ void CurvesEffectOperation::on_stroke_extended(bContext *C,
}
std::unique_ptr<CurvesSculptStrokeOperation> new_grow_shrink_operation(
- const BrushStrokeMode brush_mode, bContext *C)
+ const BrushStrokeMode brush_mode, const bContext &C)
{
- Scene &scene = *CTX_data_scene(C);
- Brush &brush = *BKE_paint_brush(&scene.toolsettings->curves_sculpt->paint);
+ const Scene &scene = *CTX_data_scene(&C);
+ const Brush &brush = *BKE_paint_brush_for_read(&scene.toolsettings->curves_sculpt->paint);
const bool use_scale_uniform = brush.curves_sculpt_settings->flag &
BRUSH_CURVES_SCULPT_FLAG_SCALE_UNIFORM;
const bool use_grow = (brush_mode == BRUSH_STROKE_INVERT) == ((brush.flag & BRUSH_DIR_IN) != 0);
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh
index 03413221907..842de234761 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh
@@ -13,7 +13,11 @@
struct ARegion;
struct RegionView3D;
+struct Depsgraph;
+struct View3D;
struct Object;
+struct Brush;
+struct Scene;
namespace blender::ed::sculpt_paint {
@@ -22,23 +26,35 @@ using bke::CurvesGeometry;
struct StrokeExtension {
bool is_first;
float2 mouse_position;
+ float pressure;
};
+float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension);
+float brush_radius_get(const Scene &scene,
+ const Brush &brush,
+ const StrokeExtension &stroke_extension);
+
+float brush_strength_factor(const Brush &brush, const StrokeExtension &stroke_extension);
+float brush_strength_get(const Scene &scene,
+ const Brush &brush,
+ const StrokeExtension &stroke_extension);
+
/**
* Base class for stroke based operations in curves sculpt mode.
*/
class CurvesSculptStrokeOperation {
public:
virtual ~CurvesSculptStrokeOperation() = default;
- virtual void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) = 0;
+ virtual void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) = 0;
};
-std::unique_ptr<CurvesSculptStrokeOperation> new_add_operation();
+std::unique_ptr<CurvesSculptStrokeOperation> new_add_operation(const bContext &C,
+ ReportList *reports);
std::unique_ptr<CurvesSculptStrokeOperation> new_comb_operation();
std::unique_ptr<CurvesSculptStrokeOperation> new_delete_operation();
std::unique_ptr<CurvesSculptStrokeOperation> new_snake_hook_operation();
std::unique_ptr<CurvesSculptStrokeOperation> new_grow_shrink_operation(
- const BrushStrokeMode brush_mode, bContext *C);
+ const BrushStrokeMode brush_mode, const bContext &C);
struct CurvesBrush3D {
float3 position_cu;
@@ -48,9 +64,14 @@ struct CurvesBrush3D {
/**
* Find 3d brush position based on cursor position for curves sculpting.
*/
-std::optional<CurvesBrush3D> sample_curves_3d_brush(bContext &C,
- Object &curves_object,
+std::optional<CurvesBrush3D> sample_curves_3d_brush(const Depsgraph &depsgraph,
+ const ARegion &region,
+ const View3D &v3d,
+ const RegionView3D &rv3d,
+ const Object &curves_object,
const float2 &brush_pos_re,
- float brush_radius_re);
+ const float brush_radius_re);
+
+Vector<float4x4> get_symmetry_brush_transforms(eCurvesSymmetryType symmetry);
} // namespace blender::ed::sculpt_paint
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
index 992ac77803a..15d0f73592d 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
@@ -74,12 +74,42 @@ using blender::bke::CurvesGeometry;
/** \name * SCULPT_CURVES_OT_brush_stroke
* \{ */
-static std::unique_ptr<CurvesSculptStrokeOperation> start_brush_operation(bContext *C,
- wmOperator *op)
+float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension)
{
- const BrushStrokeMode mode = static_cast<BrushStrokeMode>(RNA_enum_get(op->ptr, "mode"));
+ if (BKE_brush_use_size_pressure(&brush)) {
+ return stroke_extension.pressure;
+ }
+ return 1.0f;
+}
+
+float brush_radius_get(const Scene &scene,
+ const Brush &brush,
+ const StrokeExtension &stroke_extension)
+{
+ return BKE_brush_size_get(&scene, &brush) * brush_radius_factor(brush, stroke_extension);
+}
+
+float brush_strength_factor(const Brush &brush, const StrokeExtension &stroke_extension)
+{
+ if (BKE_brush_use_alpha_pressure(&brush)) {
+ return stroke_extension.pressure;
+ }
+ return 1.0f;
+}
+
+float brush_strength_get(const Scene &scene,
+ const Brush &brush,
+ const StrokeExtension &stroke_extension)
+{
+ return BKE_brush_alpha_get(&scene, &brush) * brush_strength_factor(brush, stroke_extension);
+}
- Scene &scene = *CTX_data_scene(C);
+static std::unique_ptr<CurvesSculptStrokeOperation> start_brush_operation(bContext &C,
+ wmOperator &op)
+{
+ const BrushStrokeMode mode = static_cast<BrushStrokeMode>(RNA_enum_get(op.ptr, "mode"));
+
+ Scene &scene = *CTX_data_scene(&C);
CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt;
Brush &brush = *BKE_paint_brush(&curves_sculpt.paint);
switch (brush.curves_sculpt_tool) {
@@ -90,7 +120,7 @@ static std::unique_ptr<CurvesSculptStrokeOperation> start_brush_operation(bConte
case CURVES_SCULPT_TOOL_SNAKE_HOOK:
return new_snake_hook_operation();
case CURVES_SCULPT_TOOL_ADD:
- return new_add_operation();
+ return new_add_operation(C, op.reports);
case CURVES_SCULPT_TOOL_GROW_SHRINK:
return new_grow_shrink_operation(mode, C);
}
@@ -128,17 +158,18 @@ static void stroke_update_step(bContext *C,
StrokeExtension stroke_extension;
RNA_float_get_array(stroke_element, "mouse", stroke_extension.mouse_position);
+ stroke_extension.pressure = RNA_float_get(stroke_element, "pressure");
if (!op_data->operation) {
stroke_extension.is_first = true;
- op_data->operation = start_brush_operation(C, op);
+ op_data->operation = start_brush_operation(*C, *op);
}
else {
stroke_extension.is_first = false;
}
if (op_data->operation) {
- op_data->operation->on_stroke_extended(C, stroke_extension);
+ op_data->operation->on_stroke_extended(*C, stroke_extension);
}
}
@@ -149,6 +180,12 @@ static void stroke_done(const bContext *C, PaintStroke *stroke)
static int sculpt_curves_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *brush = BKE_paint_brush(paint);
+ if (brush == nullptr) {
+ return OPERATOR_CANCELLED;
+ }
+
SculptCurvesBrushStrokeData *op_data = MEM_new<SculptCurvesBrushStrokeData>(__func__);
op_data->stroke = paint_stroke_new(C,
op,
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc
index 6d930d35f04..bcdeaaeabf2 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc
@@ -37,6 +37,8 @@
#include "ED_screen.h"
#include "ED_view3d.h"
+#include "WM_api.h"
+
/**
* The code below uses a prefix naming convention to indicate the coordinate space:
* - `cu`: Local space of the curves object that is being edited.
@@ -61,7 +63,7 @@ class SnakeHookOperation : public CurvesSculptStrokeOperation {
friend struct SnakeHookOperatorExecutor;
public:
- void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override;
+ void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override;
};
/**
@@ -70,19 +72,21 @@ class SnakeHookOperation : public CurvesSculptStrokeOperation {
*/
struct SnakeHookOperatorExecutor {
SnakeHookOperation *self_ = nullptr;
- bContext *C_ = nullptr;
- Scene *scene_ = nullptr;
- Object *object_ = nullptr;
+ const Depsgraph *depsgraph_ = nullptr;
+ const Scene *scene_ = nullptr;
ARegion *region_ = nullptr;
- View3D *v3d_ = nullptr;
- RegionView3D *rv3d_ = nullptr;
+ const View3D *v3d_ = nullptr;
+ const RegionView3D *rv3d_ = nullptr;
- CurvesSculpt *curves_sculpt_ = nullptr;
- Brush *brush_ = nullptr;
- float brush_radius_re_;
+ const CurvesSculpt *curves_sculpt_ = nullptr;
+ const Brush *brush_ = nullptr;
+ float brush_radius_base_re_;
+ float brush_radius_factor_;
float brush_strength_;
+
eBrushFalloffShape falloff_shape_;
+ Object *object_ = nullptr;
Curves *curves_id_ = nullptr;
CurvesGeometry *curves_ = nullptr;
@@ -93,22 +97,28 @@ struct SnakeHookOperatorExecutor {
float2 brush_pos_re_;
float2 brush_pos_diff_re_;
- void execute(SnakeHookOperation &self, bContext *C, const StrokeExtension &stroke_extension)
+ void execute(SnakeHookOperation &self,
+ const bContext &C,
+ const StrokeExtension &stroke_extension)
{
BLI_SCOPED_DEFER([&]() { self.last_mouse_position_re_ = stroke_extension.mouse_position; });
self_ = &self;
- C_ = C;
- scene_ = CTX_data_scene(C);
- object_ = CTX_data_active_object(C);
- region_ = CTX_wm_region(C);
- v3d_ = CTX_wm_view3d(C);
- rv3d_ = CTX_wm_region_view3d(C);
+ depsgraph_ = CTX_data_depsgraph_pointer(&C);
+ scene_ = CTX_data_scene(&C);
+ scene_ = CTX_data_scene(&C);
+ object_ = CTX_data_active_object(&C);
+ region_ = CTX_wm_region(&C);
+ v3d_ = CTX_wm_view3d(&C);
+ rv3d_ = CTX_wm_region_view3d(&C);
curves_sculpt_ = scene_->toolsettings->curves_sculpt;
- brush_ = BKE_paint_brush(&curves_sculpt_->paint);
- brush_radius_re_ = BKE_brush_size_get(scene_, brush_);
- brush_strength_ = BKE_brush_alpha_get(scene_, brush_);
+ brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint);
+
+ brush_radius_base_re_ = BKE_brush_size_get(scene_, brush_);
+ brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
+ brush_strength_ = brush_strength_get(*scene_, *brush_, stroke_extension);
+
falloff_shape_ = static_cast<eBrushFalloffShape>(brush_->falloff_shape);
curves_to_world_mat_ = object_->obmat;
@@ -127,7 +137,7 @@ struct SnakeHookOperatorExecutor {
if (stroke_extension.is_first) {
if (falloff_shape_ == PAINT_FALLOFF_SHAPE_SPHERE) {
std::optional<CurvesBrush3D> brush_3d = sample_curves_3d_brush(
- *C_, *object_, brush_pos_re_, brush_radius_re_);
+ *depsgraph_, *region_, *v3d_, *rv3d_, *object_, brush_pos_re_, brush_radius_base_re_);
if (brush_3d.has_value()) {
self_->brush_3d_ = *brush_3d;
}
@@ -136,10 +146,10 @@ struct SnakeHookOperatorExecutor {
}
if (falloff_shape_ == PAINT_FALLOFF_SHAPE_SPHERE) {
- this->spherical_snake_hook();
+ this->spherical_snake_hook_with_symmetry();
}
else if (falloff_shape_ == PAINT_FALLOFF_SHAPE_TUBE) {
- this->projected_snake_hook();
+ this->projected_snake_hook_with_symmetry();
}
else {
BLI_assert_unreachable();
@@ -147,49 +157,63 @@ struct SnakeHookOperatorExecutor {
curves_->tag_positions_changed();
DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, &curves_id_->id);
ED_region_tag_redraw(region_);
}
- void projected_snake_hook()
+ void projected_snake_hook_with_symmetry()
{
+ const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms(
+ eCurvesSymmetryType(curves_id_->symmetry));
+ for (const float4x4 &brush_transform : symmetry_brush_transforms) {
+ this->projected_snake_hook(brush_transform);
+ }
+ }
+
+ void projected_snake_hook(const float4x4 &brush_transform)
+ {
+ const float4x4 brush_transform_inv = brush_transform.inverted();
+
MutableSpan<float3> positions_cu = curves_->positions_for_write();
float4x4 projection;
ED_view3d_ob_project_mat_get(rv3d_, object_, projection.values);
+ const float brush_radius_re = brush_radius_base_re_ * brush_radius_factor_;
+ const float brush_radius_sq_re = pow2f(brush_radius_re);
+
threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) {
for (const int curve_i : curves_range) {
const IndexRange points = curves_->points_for_curve(curve_i);
const int last_point_i = points.last();
- const float3 old_pos_cu = positions_cu[last_point_i];
+ const float3 old_pos_cu = brush_transform_inv * positions_cu[last_point_i];
float2 old_pos_re;
ED_view3d_project_float_v2_m4(region_, old_pos_cu, old_pos_re, projection.values);
- const float distance_to_brush_re = math::distance(old_pos_re, brush_pos_prev_re_);
- if (distance_to_brush_re > brush_radius_re_) {
+ const float distance_to_brush_sq_re = math::distance_squared(old_pos_re,
+ brush_pos_prev_re_);
+ if (distance_to_brush_sq_re > brush_radius_sq_re) {
continue;
}
const float radius_falloff = BKE_brush_curve_strength(
- brush_, distance_to_brush_re, brush_radius_re_);
+ brush_, std::sqrt(distance_to_brush_sq_re), brush_radius_re);
const float weight = brush_strength_ * radius_falloff;
const float2 new_position_re = old_pos_re + brush_pos_diff_re_ * weight;
float3 new_position_wo;
ED_view3d_win_to_3d(
v3d_, region_, curves_to_world_mat_ * old_pos_cu, new_position_re, new_position_wo);
- const float3 new_position_cu = world_to_curves_mat_ * new_position_wo;
+ const float3 new_position_cu = brush_transform * (world_to_curves_mat_ * new_position_wo);
this->move_last_point_and_resample(positions_cu.slice(points), new_position_cu);
}
});
}
- void spherical_snake_hook()
+ void spherical_snake_hook_with_symmetry()
{
- MutableSpan<float3> positions_cu = curves_->positions_for_write();
-
float4x4 projection;
ED_view3d_ob_project_mat_get(rv3d_, object_, projection.values);
@@ -206,9 +230,23 @@ struct SnakeHookOperatorExecutor {
brush_end_wo);
const float3 brush_start_cu = world_to_curves_mat_ * brush_start_wo;
const float3 brush_end_cu = world_to_curves_mat_ * brush_end_wo;
- const float3 brush_diff_cu = brush_end_cu - brush_start_cu;
- const float brush_radius_cu = self_->brush_3d_.radius_cu;
+ const float brush_radius_cu = self_->brush_3d_.radius_cu * brush_radius_factor_;
+
+ const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms(
+ eCurvesSymmetryType(curves_id_->symmetry));
+ for (const float4x4 &brush_transform : symmetry_brush_transforms) {
+ this->spherical_snake_hook(
+ brush_transform * brush_start_cu, brush_transform * brush_end_cu, brush_radius_cu);
+ }
+ }
+
+ void spherical_snake_hook(const float3 &brush_start_cu,
+ const float3 &brush_end_cu,
+ const float brush_radius_cu)
+ {
+ MutableSpan<float3> positions_cu = curves_->positions_for_write();
+ const float3 brush_diff_cu = brush_end_cu - brush_start_cu;
const float brush_radius_sq_cu = pow2f(brush_radius_cu);
threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) {
@@ -269,7 +307,8 @@ struct SnakeHookOperatorExecutor {
}
};
-void SnakeHookOperation::on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension)
+void SnakeHookOperation::on_stroke_extended(const bContext &C,
+ const StrokeExtension &stroke_extension)
{
SnakeHookOperatorExecutor executor;
executor.execute(*this, C, stroke_extension);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index e442cd53639..95a7c1d8dee 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -7,6 +7,7 @@
*/
#include <float.h>
+#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
@@ -35,12 +36,17 @@
#include "IMB_imbuf_types.h"
#include "DNA_brush_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_defs.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_node_types.h"
+#include "DNA_object_enums.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "BKE_attribute.h"
#include "BKE_brush.h"
#include "BKE_camera.h"
#include "BKE_colorband.h"
@@ -61,6 +67,8 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -76,12 +84,18 @@
#include "GPU_capabilities.h"
#include "GPU_init_exit.h"
+#include "NOD_shader.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
#include "WM_api.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "RNA_types.h"
#include "NOD_shader.h"
@@ -4070,7 +4084,7 @@ typedef struct {
static void proj_paint_layer_clone_init(ProjPaintState *ps, ProjPaintLayerClone *layer_clone)
{
- MLoopUV *mloopuv_clone_base = NULL;
+ const MLoopUV *mloopuv_clone_base = NULL;
/* use clone mtface? */
if (ps->do_layer_clone) {
@@ -6472,6 +6486,38 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain, bool is_data)
return ima;
}
+static CustomDataLayer *proj_paint_color_attribute_create(wmOperator *op, Object *ob)
+{
+ char name[MAX_NAME] = "";
+ float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ AttributeDomain domain = ATTR_DOMAIN_POINT;
+ CustomDataType type = CD_PROP_COLOR;
+
+ if (op) {
+ RNA_string_get(op->ptr, "name", name);
+ RNA_float_get_array(op->ptr, "color", color);
+ domain = (AttributeDomain)RNA_enum_get(op->ptr, "domain");
+ type = (CustomDataType)RNA_enum_get(op->ptr, "data_type");
+ }
+
+ ID *id = (ID *)ob->data;
+ CustomDataLayer *layer = BKE_id_attribute_new(id, name, type, domain, op->reports);
+
+ if (!layer) {
+ return NULL;
+ }
+
+ BKE_id_attributes_active_color_set(id, layer);
+
+ if (!BKE_id_attributes_render_color_get(id)) {
+ BKE_id_attributes_render_color_set(id, layer);
+ }
+
+ BKE_object_attributes_active_color_fill(ob, color, false);
+
+ return layer;
+}
+
/**
* Get a default color for the paint slot layer from a material's Principled BSDF.
*
@@ -6539,6 +6585,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Material *ma;
Image *ima = NULL;
+ CustomDataLayer *layer = NULL;
if (!ob) {
return false;
@@ -6551,7 +6598,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
int type = RNA_enum_get(op->ptr, "type");
bool is_data = (type > LAYER_BASE_COLOR);
- bNode *imanode;
+ bNode *new_node;
bNodeTree *ntree = ma->nodetree;
if (!ntree) {
@@ -6561,17 +6608,36 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
ma->use_nodes = true;
- /* try to add an image node */
- imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
-
- ima = proj_paint_image_create(op, bmain, is_data);
- imanode->id = &ima->id;
-
- nodeSetActive(ntree, imanode);
+ const ePaintCanvasSource slot_type = ob->mode == OB_MODE_SCULPT ?
+ (ePaintCanvasSource)RNA_enum_get(op->ptr,
+ "slot_type") :
+ PAINT_CANVAS_SOURCE_IMAGE;
+
+ /* Create a new node. */
+ switch (slot_type) {
+ case PAINT_CANVAS_SOURCE_IMAGE: {
+ new_node = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
+ ima = proj_paint_image_create(op, bmain, is_data);
+ new_node->id = &ima->id;
+ break;
+ }
+ case PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE: {
+ new_node = nodeAddStaticNode(C, ntree, SH_NODE_ATTRIBUTE);
+ if ((layer = proj_paint_color_attribute_create(op, ob))) {
+ BLI_strncpy_utf8(
+ ((NodeShaderAttribute *)new_node->storage)->name, layer->name, MAX_NAME);
+ }
+ break;
+ }
+ case PAINT_CANVAS_SOURCE_MATERIAL:
+ BLI_assert_unreachable();
+ return false;
+ }
+ nodeSetActive(ntree, new_node);
/* Connect to first available principled BSDF node. */
bNode *in_node = ntreeFindType(ntree, SH_NODE_BSDF_PRINCIPLED);
- bNode *out_node = imanode;
+ bNode *out_node = new_node;
if (in_node != NULL) {
bNodeSocket *out_sock = nodeFindSocket(out_node, SOCK_OUT, "Color");
@@ -6634,6 +6700,11 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
}
+ if (layer) {
+ BKE_texpaint_slot_refresh_cache(scene, ma, ob);
+ DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, ob->data);
+ }
DEG_id_tag_update(&ntree->id, 0);
DEG_id_tag_update(&ma->id, ID_RECALC_SHADING);
@@ -6695,6 +6766,44 @@ static int texture_paint_add_texture_paint_slot_invoke(bContext *C,
return WM_operator_props_dialog_popup(C, op, 300);
}
+static void texture_paint_add_texture_paint_slot_ui(bContext *C, wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+ Object *ob = ED_object_active_context(C);
+ ePaintCanvasSource slot_type = PAINT_CANVAS_SOURCE_IMAGE;
+
+ if (ob->mode == OB_MODE_SCULPT) {
+ slot_type = (ePaintCanvasSource)RNA_enum_get(op->ptr, "slot_type");
+ uiItemR(layout, op->ptr, "slot_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ }
+
+ uiItemR(layout, op->ptr, "name", 0, NULL, ICON_NONE);
+
+ switch (slot_type) {
+ case PAINT_CANVAS_SOURCE_IMAGE: {
+ uiLayout *col = uiLayoutColumn(layout, true);
+ uiItemR(col, op->ptr, "width", 0, NULL, ICON_NONE);
+ uiItemR(col, op->ptr, "height", 0, NULL, ICON_NONE);
+
+ uiItemR(layout, op->ptr, "alpha", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "generated_type", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "float", 0, NULL, ICON_NONE);
+ break;
+ }
+ case PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE:
+ uiItemR(layout, op->ptr, "domain", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "data_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ break;
+ case PAINT_CANVAS_SOURCE_MATERIAL:
+ BLI_assert_unreachable();
+ break;
+ }
+
+ uiItemR(layout, op->ptr, "color", 0, NULL, ICON_NONE);
+}
+
#define IMA_DEF_NAME N_("Untitled")
void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
@@ -6702,40 +6811,92 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
PropertyRNA *prop;
static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ static const EnumPropertyItem slot_type_items[3] = {
+ {PAINT_CANVAS_SOURCE_IMAGE, "IMAGE", 0, "Image", ""},
+ {PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE, "COLOR_ATTRIBUTE", 0, "Color Attribute", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem domain_items[3] = {
+ {ATTR_DOMAIN_POINT, "POINT", 0, "Vertex", ""},
+ {ATTR_DOMAIN_CORNER, "CORNER", 0, "Face Corner", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem attribute_type_items[3] = {
+ {CD_PROP_COLOR, "COLOR", 0, "Color", ""},
+ {CD_PROP_BYTE_COLOR, "BYTE_COLOR", 0, "Byte Color", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
/* identifiers */
- ot->name = "Add Texture Paint Slot";
- ot->description = "Add a texture paint slot";
+ ot->name = "Add Paint Slot";
+ ot->description = "Add a paint slot";
ot->idname = "PAINT_OT_add_texture_paint_slot";
/* api callbacks */
ot->invoke = texture_paint_add_texture_paint_slot_invoke;
ot->exec = texture_paint_add_texture_paint_slot_exec;
ot->poll = ED_operator_object_active_editable_mesh;
+ ot->ui = texture_paint_add_texture_paint_slot_ui;
/* flags */
ot->flag = OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "type", layer_type_items, 0, "Type", "Merge method to use");
+ /* Shared Properties */
+ prop = RNA_def_enum(ot->srna,
+ "type",
+ layer_type_items,
+ 0,
+ "Material Layer Type",
+ "Material layer type of new paint slot");
RNA_def_property_flag(prop, PROP_HIDDEN);
- RNA_def_string(ot->srna, "name", IMA_DEF_NAME, MAX_ID_NAME - 2, "Name", "Image data-block name");
- prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
- RNA_def_property_subtype(prop, PROP_PIXEL);
- prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
- RNA_def_property_subtype(prop, PROP_PIXEL);
+
+ prop = RNA_def_enum(
+ ot->srna, "slot_type", slot_type_items, 0, "Slot Type", "Type of new paint slot");
+
+ prop = RNA_def_string(
+ ot->srna, "name", IMA_DEF_NAME, MAX_NAME, "Name", "Name for new paint slot source");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
prop = RNA_def_float_color(
ot->srna, "color", 4, NULL, 0.0f, FLT_MAX, "Color", "Default fill color", 0.0f, 1.0f);
RNA_def_property_subtype(prop, PROP_COLOR_GAMMA);
RNA_def_property_float_array_default(prop, default_color);
+
+ /* Image Properties */
+ prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+
+ prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+
RNA_def_boolean(ot->srna, "alpha", true, "Alpha", "Create an image with an alpha channel");
+
RNA_def_enum(ot->srna,
"generated_type",
rna_enum_image_generated_type_items,
IMA_GENTYPE_BLANK,
"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");
+
+ /* Color Attribute Properties */
+ RNA_def_enum(ot->srna,
+ "domain",
+ domain_items,
+ ATTR_DOMAIN_POINT,
+ "Domain",
+ "Type of element that attribute is stored on");
+
+ RNA_def_enum(ot->srna,
+ "data_type",
+ attribute_type_items,
+ CD_PROP_COLOR,
+ "Data Type",
+ "Type of data stored in attribute");
}
static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc
index f13c34e2030..fb1c8ceaa1a 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.cc
+++ b/source/blender/editors/sculpt_paint/paint_vertex.cc
@@ -4144,13 +4144,7 @@ static bool vertex_color_set(Object *ob, ColorPaint4f paintcol_in, Color *color_
}
/**
- * Fills the object's active color atribute layer with the fill color.
- *
- * \param[in] ob: The object.
- * \param[in] fill_color: The fill color.
- * \param[in] only_selected: Limit the fill to selected faces or vertices.
- *
- * \return #true if successful.
+ * See doc-string for #BKE_object_attributes_active_color_fill.
*/
static bool paint_object_attributes_active_color_fill_ex(Object *ob,
ColorPaint4f fill_color,
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 85ea5d5bfc6..5bb4eb7cebf 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -3248,8 +3248,8 @@ static void do_brush_action(Sculpt *sd,
}
nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale, &totnode);
}
-
- if (sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob)) {
+ const bool use_pixels = sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob);
+ if (use_pixels) {
sculpt_pbvh_update_pixels(paint_mode_settings, ss, ob);
}
@@ -3302,16 +3302,18 @@ static void do_brush_action(Sculpt *sd,
}
float location[3];
- SculptThreadedTaskData task_data = {
- .sd = sd,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- };
+ if (!use_pixels) {
+ SculptThreadedTaskData task_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, &task_data, do_brush_action_task_cb, &settings);
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+ BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
+ }
if (sculpt_brush_needs_normal(ss, brush)) {
update_sculpt_normal(sd, ob, nodes, totnode);
@@ -5276,6 +5278,7 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
SculptSession *ss = ob->sculpt;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
+ ToolSettings *tool_settings = CTX_data_tool_settings(C);
/* NOTE: This should be removed when paint mode is available. Paint mode can force based on the
* canvas it is painting on. (ref. use_sculpt_texture_paint). */
@@ -5293,7 +5296,15 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
SculptCursorGeometryInfo sgi;
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
- SCULPT_undo_push_begin(ob, sculpt_tool_name(sd));
+ /* Setup the correct undo system. Image painting and sculpting are mutual exclusive.
+ * Color attributes are part of the sculpting undo system. */
+ if (brush && brush->sculpt_tool == SCULPT_TOOL_PAINT &&
+ SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) {
+ ED_image_undo_push_begin(op->type->name, PAINT_MODE_SCULPT);
+ }
+ else {
+ SCULPT_undo_push_begin(ob, sculpt_tool_name(sd));
+ }
return true;
}
@@ -5420,7 +5431,13 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
SCULPT_cache_free(ss->cache);
ss->cache = NULL;
- SCULPT_undo_push_end(ob);
+ if (brush && brush->sculpt_tool == SCULPT_TOOL_PAINT &&
+ SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) {
+ ED_image_undo_push_end();
+ }
+ else {
+ SCULPT_undo_push_end(ob);
+ }
if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c
index 7171c241534..d03c5ecab4d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.c
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c
@@ -60,7 +60,7 @@
int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh)
{
- int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
+ const int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
if (!face_sets) {
return SCULPT_FACE_SET_NONE;
}
@@ -150,25 +150,22 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
}
}
}
-
else if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- {
- 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.index,
- thread_id);
-
- if (fade > 0.05f) {
- SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set);
- }
+ 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.index,
+ thread_id);
+
+ if (fade > 0.05f) {
+ SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set);
}
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index f9633c91087..5fa115ed629 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -1652,11 +1652,11 @@ void SCULPT_do_paint_brush(struct PaintModeSettings *paint_mode_settings,
int totnode) ATTR_NONNULL();
/**
- * @brief Get the image canvas for painting on the given object.
+ * \brief Get the image canvas for painting on the given object.
*
- * @return #true if an image is found. The #r_image and #r_image_user fields are filled with the
+ * \return #true if an image is found. The #r_image and #r_image_user fields are filled with the
* image and image user. Returns false when the image isn't found. In the later case the r_image
- * and r_image_user are set to nullptr/NULL.
+ * and r_image_user are set to NULL.
*/
bool SCULPT_paint_image_canvas_get(struct PaintModeSettings *paint_mode_settings,
struct Object *ob,
diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.c b/source/blender/editors/sculpt_paint/sculpt_ops.c
index 8df1cc458d3..dc620f0ee93 100644
--- a/source/blender/editors/sculpt_paint/sculpt_ops.c
+++ b/source/blender/editors/sculpt_paint/sculpt_ops.c
@@ -637,16 +637,16 @@ static int vertex_to_loop_colors_exec(bContext *C, wmOperator *UNUSED(op))
if (MPropCol_layer_n == -1) {
return OPERATOR_CANCELLED;
}
- MPropCol *vertcols = CustomData_get_layer_n(&mesh->vdata, CD_PROP_COLOR, MPropCol_layer_n);
+ const MPropCol *vertcols = CustomData_get_layer_n(&mesh->vdata, CD_PROP_COLOR, MPropCol_layer_n);
- MLoop *loops = CustomData_get_layer(&mesh->ldata, CD_MLOOP);
- MPoly *polys = CustomData_get_layer(&mesh->pdata, CD_MPOLY);
+ const MLoop *loops = CustomData_get_layer(&mesh->ldata, CD_MLOOP);
+ const MPoly *polys = CustomData_get_layer(&mesh->pdata, CD_MPOLY);
for (int i = 0; i < mesh->totpoly; i++) {
- MPoly *c_poly = &polys[i];
+ const MPoly *c_poly = &polys[i];
for (int j = 0; j < c_poly->totloop; j++) {
int loop_index = c_poly->loopstart + j;
- MLoop *c_loop = &loops[c_poly->loopstart + j];
+ const MLoop *c_loop = &loops[c_poly->loopstart + j];
float srgb_color[4];
linearrgb_to_srgb_v4(srgb_color, vertcols[c_loop->v].color);
loopcols[loop_index].r = (char)(srgb_color[0] * 255);
@@ -711,7 +711,8 @@ static int loop_to_vertex_colors_exec(bContext *C, wmOperator *UNUSED(op))
if (mloopcol_layer_n == -1) {
return OPERATOR_CANCELLED;
}
- MLoopCol *loopcols = CustomData_get_layer_n(&mesh->ldata, CD_PROP_BYTE_COLOR, mloopcol_layer_n);
+ const MLoopCol *loopcols = CustomData_get_layer_n(
+ &mesh->ldata, CD_PROP_BYTE_COLOR, mloopcol_layer_n);
const int MPropCol_layer_n = CustomData_get_active_layer(&mesh->vdata, CD_PROP_COLOR);
if (MPropCol_layer_n == -1) {
@@ -719,14 +720,14 @@ static int loop_to_vertex_colors_exec(bContext *C, wmOperator *UNUSED(op))
}
MPropCol *vertcols = CustomData_get_layer_n(&mesh->vdata, CD_PROP_COLOR, MPropCol_layer_n);
- MLoop *loops = CustomData_get_layer(&mesh->ldata, CD_MLOOP);
- MPoly *polys = CustomData_get_layer(&mesh->pdata, CD_MPOLY);
+ const MLoop *loops = CustomData_get_layer(&mesh->ldata, CD_MLOOP);
+ const MPoly *polys = CustomData_get_layer(&mesh->pdata, CD_MPOLY);
for (int i = 0; i < mesh->totpoly; i++) {
- MPoly *c_poly = &polys[i];
+ const MPoly *c_poly = &polys[i];
for (int j = 0; j < c_poly->totloop; j++) {
int loop_index = c_poly->loopstart + j;
- MLoop *c_loop = &loops[c_poly->loopstart + j];
+ const MLoop *c_loop = &loops[c_poly->loopstart + j];
vertcols[c_loop->v].color[0] = (loopcols[loop_index].r / 255.0f);
vertcols[c_loop->v].color[1] = (loopcols[loop_index].g / 255.0f);
vertcols[c_loop->v].color[2] = (loopcols[loop_index].b / 255.0f);
diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_image.cc b/source/blender/editors/sculpt_paint/sculpt_paint_image.cc
index df1ccc0fbe9..975a8f21aaf 100644
--- a/source/blender/editors/sculpt_paint/sculpt_paint_image.cc
+++ b/source/blender/editors/sculpt_paint/sculpt_paint_image.cc
@@ -360,6 +360,86 @@ static void do_paint_pixels(void *__restrict userdata,
node_data.flags.dirty |= pixels_updated;
}
+static void undo_region_tiles(
+ ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th)
+{
+ int srcx = 0, srcy = 0;
+ IMB_rectclip(ibuf, nullptr, &x, &y, &srcx, &srcy, &w, &h);
+ *tw = ((x + w - 1) >> ED_IMAGE_UNDO_TILE_BITS);
+ *th = ((y + h - 1) >> ED_IMAGE_UNDO_TILE_BITS);
+ *tx = (x >> ED_IMAGE_UNDO_TILE_BITS);
+ *ty = (y >> ED_IMAGE_UNDO_TILE_BITS);
+}
+
+static void push_undo(const NodeData &node_data,
+ Image &image,
+ ImageUser &image_user,
+ const image::ImageTileWrapper &image_tile,
+ ImBuf &image_buffer,
+ ImBuf **tmpibuf)
+{
+ for (const UDIMTileUndo &tile_undo : node_data.undo_regions) {
+ if (tile_undo.tile_number != image_tile.get_tile_number()) {
+ continue;
+ }
+ int tilex, tiley, tilew, tileh;
+ ListBase *undo_tiles = ED_image_paint_tile_list_get();
+ undo_region_tiles(&image_buffer,
+ tile_undo.region.xmin,
+ tile_undo.region.ymin,
+ BLI_rcti_size_x(&tile_undo.region),
+ BLI_rcti_size_y(&tile_undo.region),
+ &tilex,
+ &tiley,
+ &tilew,
+ &tileh);
+ for (int ty = tiley; ty <= tileh; ty++) {
+ for (int tx = tilex; tx <= tilew; tx++) {
+ ED_image_paint_tile_push(undo_tiles,
+ &image,
+ &image_buffer,
+ tmpibuf,
+ &image_user,
+ tx,
+ ty,
+ nullptr,
+ nullptr,
+ true,
+ true);
+ }
+ }
+ }
+}
+
+static void do_push_undo_tile(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ TexturePaintingUserData *data = static_cast<TexturePaintingUserData *>(userdata);
+ PBVHNode *node = data->nodes[n];
+
+ NodeData &node_data = BKE_pbvh_pixels_node_data_get(*node);
+ Image *image = data->image_data.image;
+ ImageUser *image_user = data->image_data.image_user;
+
+ ImBuf *tmpibuf = nullptr;
+ ImageUser local_image_user = *image_user;
+ LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
+ image::ImageTileWrapper image_tile(tile);
+ local_image_user.tile = image_tile.get_tile_number();
+ ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &local_image_user, nullptr);
+ if (image_buffer == nullptr) {
+ continue;
+ }
+
+ push_undo(node_data, *image, *image_user, image_tile, *image_buffer, &tmpibuf);
+ BKE_image_release_ibuf(image, image_buffer, nullptr);
+ }
+ if (tmpibuf) {
+ IMB_freeImBuf(tmpibuf);
+ }
+}
+
static void do_mark_dirty_regions(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict UNUSED(tls))
@@ -380,8 +460,9 @@ bool SCULPT_paint_image_canvas_get(PaintModeSettings *paint_mode_settings,
Image **r_image,
ImageUser **r_image_user)
{
- BLI_assert(r_image);
- BLI_assert(r_image_user);
+ *r_image = nullptr;
+ *r_image_user = nullptr;
+
ImageData image_data;
if (!ImageData::init_active_image(ob, &image_data, paint_mode_settings)) {
return false;
@@ -421,6 +502,7 @@ void SCULPT_do_paint_brush_image(
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+ BLI_task_parallel_range(0, totnode, &data, do_push_undo_tile, &settings);
BLI_task_parallel_range(0, totnode, &data, do_paint_pixels, &settings);
TaskParallelSettings settings_flush;
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 5867dc558de..1fee20444e7 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -1265,7 +1265,7 @@ static SculptUndoNode *sculpt_undo_face_sets_push(Object *ob, SculptUndoType typ
unode->face_sets = MEM_callocN(me->totpoly * sizeof(int), "sculpt face sets");
- int *face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
+ const int *face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
for (int i = 0; i < me->totpoly; i++) {
unode->face_sets[i] = face_sets[i];
}
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index e24d461019b..72df2b74b11 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -303,7 +303,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
cb->marker->pattern_corners[a][1] *= scale_y;
}
- BKE_tracking_marker_clamp(cb->marker, CLAMP_PAT_DIM);
+ BKE_tracking_marker_clamp_search_size(cb->marker);
ok = true;
}
@@ -319,7 +319,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
sub_v2_v2v2(cb->marker->search_min, delta, side);
add_v2_v2v2(cb->marker->search_max, delta, side);
- BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_POS);
+ BKE_tracking_marker_clamp_search_position(cb->marker);
ok = true;
}
@@ -340,7 +340,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
cb->marker->search_max[0] += dim[0];
cb->marker->search_max[1] += dim[1];
- BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_DIM);
+ BKE_tracking_marker_clamp_search_size(cb->marker);
ok = true;
}
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index dd01c095479..7f9cf61b748 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -187,8 +187,10 @@ void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene);
/* tracking_ops.c */
-struct MovieTrackingTrack *tracking_marker_check_slide(
- struct bContext *C, const struct wmEvent *event, int *r_area, int *r_action, int *r_corner);
+/* Find track which can be slid in a proximity of the given event.
+ * Uses the same distance tolerance rule as the "Slide Marker" operator. */
+struct MovieTrackingTrack *tracking_find_slidable_track_in_proximity(struct bContext *C,
+ const float co[2]);
void CLIP_OT_add_marker(struct wmOperatorType *ot);
void CLIP_OT_add_marker_at_click(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 91fef23019c..5f52e1a3071 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -619,6 +619,44 @@ static void clip_dropboxes(void)
WM_dropbox_add(lb, "CLIP_OT_open", clip_drop_poll, clip_drop_copy, NULL, NULL);
}
+static bool clip_set_region_visible(const bContext *C,
+ ARegion *region,
+ const bool is_visible,
+ const short alignment,
+ const bool view_all_on_show)
+{
+ bool view_changed = false;
+
+ if (is_visible) {
+ if (region && (region->flag & RGN_FLAG_HIDDEN)) {
+ region->flag &= ~RGN_FLAG_HIDDEN;
+ region->v2d.flag &= ~V2D_IS_INIT;
+ if (view_all_on_show) {
+ region->v2d.cur = region->v2d.tot;
+ }
+ view_changed = true;
+ }
+ if (region && region->alignment != alignment) {
+ region->alignment = alignment;
+ view_changed = true;
+ }
+ }
+ else {
+ if (region && !(region->flag & RGN_FLAG_HIDDEN)) {
+ region->flag |= RGN_FLAG_HIDDEN;
+ region->v2d.flag &= ~V2D_IS_INIT;
+ WM_event_remove_handlers((bContext *)C, &region->handlers);
+ view_changed = true;
+ }
+ if (region && region->alignment != RGN_ALIGN_NONE) {
+ region->alignment = RGN_ALIGN_NONE;
+ view_changed = true;
+ }
+ }
+
+ return view_changed;
+}
+
static void clip_refresh(const bContext *C, ScrArea *area)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -662,127 +700,14 @@ static void clip_refresh(const bContext *C, ScrArea *area)
break;
}
- if (main_visible) {
- if (region_main && (region_main->flag & RGN_FLAG_HIDDEN)) {
- region_main->flag &= ~RGN_FLAG_HIDDEN;
- region_main->v2d.flag &= ~V2D_IS_INIT;
- view_changed = true;
- }
-
- if (region_main && region_main->alignment != RGN_ALIGN_NONE) {
- region_main->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- }
- else {
- if (region_main && !(region_main->flag & RGN_FLAG_HIDDEN)) {
- region_main->flag |= RGN_FLAG_HIDDEN;
- region_main->v2d.flag &= ~V2D_IS_INIT;
- WM_event_remove_handlers((bContext *)C, &region_main->handlers);
- view_changed = true;
- }
- if (region_main && region_main->alignment != RGN_ALIGN_NONE) {
- region_main->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- }
-
- if (properties_visible) {
- if (region_properties && (region_properties->flag & RGN_FLAG_HIDDEN)) {
- region_properties->flag &= ~RGN_FLAG_HIDDEN;
- region_properties->v2d.flag &= ~V2D_IS_INIT;
- view_changed = true;
- }
- if (region_properties && region_properties->alignment != RGN_ALIGN_RIGHT) {
- region_properties->alignment = RGN_ALIGN_RIGHT;
- view_changed = true;
- }
- }
- else {
- if (region_properties && !(region_properties->flag & RGN_FLAG_HIDDEN)) {
- region_properties->flag |= RGN_FLAG_HIDDEN;
- region_properties->v2d.flag &= ~V2D_IS_INIT;
- WM_event_remove_handlers((bContext *)C, &region_properties->handlers);
- view_changed = true;
- }
- if (region_properties && region_properties->alignment != RGN_ALIGN_NONE) {
- region_properties->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- }
-
- if (tools_visible) {
- if (region_tools && (region_tools->flag & RGN_FLAG_HIDDEN)) {
- region_tools->flag &= ~RGN_FLAG_HIDDEN;
- region_tools->v2d.flag &= ~V2D_IS_INIT;
- view_changed = true;
- }
- if (region_tools && region_tools->alignment != RGN_ALIGN_LEFT) {
- region_tools->alignment = RGN_ALIGN_LEFT;
- view_changed = true;
- }
- }
- else {
- if (region_tools && !(region_tools->flag & RGN_FLAG_HIDDEN)) {
- region_tools->flag |= RGN_FLAG_HIDDEN;
- region_tools->v2d.flag &= ~V2D_IS_INIT;
- WM_event_remove_handlers((bContext *)C, &region_tools->handlers);
- view_changed = true;
- }
- if (region_tools && region_tools->alignment != RGN_ALIGN_NONE) {
- region_tools->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- }
-
- if (preview_visible) {
- if (region_preview && (region_preview->flag & RGN_FLAG_HIDDEN)) {
- region_preview->flag &= ~RGN_FLAG_HIDDEN;
- region_preview->v2d.flag &= ~V2D_IS_INIT;
- region_preview->v2d.cur = region_preview->v2d.tot;
- view_changed = true;
- }
- if (region_preview && region_preview->alignment != RGN_ALIGN_NONE) {
- region_preview->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- }
- else {
- if (region_preview && !(region_preview->flag & RGN_FLAG_HIDDEN)) {
- region_preview->flag |= RGN_FLAG_HIDDEN;
- region_preview->v2d.flag &= ~V2D_IS_INIT;
- WM_event_remove_handlers((bContext *)C, &region_preview->handlers);
- view_changed = true;
- }
- if (region_preview && region_preview->alignment != RGN_ALIGN_NONE) {
- region_preview->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- }
-
- if (channels_visible) {
- if (region_channels && (region_channels->flag & RGN_FLAG_HIDDEN)) {
- region_channels->flag &= ~RGN_FLAG_HIDDEN;
- region_channels->v2d.flag &= ~V2D_IS_INIT;
- view_changed = true;
- }
- if (region_channels && region_channels->alignment != RGN_ALIGN_LEFT) {
- region_channels->alignment = RGN_ALIGN_LEFT;
- view_changed = true;
- }
- }
- else {
- if (region_channels && !(region_channels->flag & RGN_FLAG_HIDDEN)) {
- region_channels->flag |= RGN_FLAG_HIDDEN;
- region_channels->v2d.flag &= ~V2D_IS_INIT;
- WM_event_remove_handlers((bContext *)C, &region_channels->handlers);
- view_changed = true;
- }
- if (region_channels && region_channels->alignment != RGN_ALIGN_NONE) {
- region_channels->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- }
+ view_changed |= clip_set_region_visible(C, region_main, main_visible, RGN_ALIGN_NONE, false);
+ view_changed |= clip_set_region_visible(
+ C, region_properties, properties_visible, RGN_ALIGN_RIGHT, false);
+ view_changed |= clip_set_region_visible(C, region_tools, tools_visible, RGN_ALIGN_LEFT, false);
+ view_changed |= clip_set_region_visible(
+ C, region_preview, preview_visible, RGN_ALIGN_NONE, true);
+ view_changed |= clip_set_region_visible(
+ C, region_channels, channels_visible, RGN_ALIGN_LEFT, false);
if (view_changed) {
ED_area_init(wm, window, area);
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index e7bdbfe7c68..ca224b04da5 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -336,35 +336,44 @@ void CLIP_OT_delete_marker(wmOperatorType *ot)
/** \name Slide Marker Operator
* \{ */
-enum {
- SLIDE_ACTION_POS = 0,
+typedef enum eSlideAction {
+ SLIDE_ACTION_NONE,
+
+ SLIDE_ACTION_POS,
SLIDE_ACTION_SIZE,
SLIDE_ACTION_OFFSET,
SLIDE_ACTION_TILT_SIZE,
-};
+} eSlideAction;
typedef struct {
- short area, action;
+ short area;
+ eSlideAction action;
MovieTrackingTrack *track;
MovieTrackingMarker *marker;
int mval[2];
int width, height;
- float *min, *max, *pos, *offset, (*corners)[2];
- float spos[2];
+ float *min, *max, *pos, (*corners)[2];
bool lock, accurate;
/* Data to restore on cancel. */
- float old_search_min[2], old_search_max[2], old_pos[2], old_offset[2];
+ float old_search_min[2], old_search_max[2], old_pos[2];
float old_corners[4][2];
float (*old_markers)[2];
} SlideMarkerData;
-static void slide_marker_tilt_slider(const MovieTrackingMarker *marker, float r_slider[2])
+static void slide_marker_tilt_slider_relative(const float pattern_corners[4][2], float r_slider[2])
+{
+ add_v2_v2v2(r_slider, pattern_corners[1], pattern_corners[2]);
+}
+
+static void slide_marker_tilt_slider(const float marker_pos[2],
+ const float pattern_corners[4][2],
+ float r_slider[2])
{
- add_v2_v2v2(r_slider, marker->pattern_corners[1], marker->pattern_corners[2]);
- add_v2_v2(r_slider, marker->pos);
+ slide_marker_tilt_slider_relative(pattern_corners, r_slider);
+ add_v2_v2(r_slider, marker_pos);
}
static SlideMarkerData *create_slide_marker_data(SpaceClip *sc,
@@ -373,7 +382,7 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc,
const wmEvent *event,
int area,
int corner,
- int action,
+ eSlideAction action,
int width,
int height)
{
@@ -389,29 +398,14 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc,
if (area == TRACK_AREA_POINT) {
data->pos = marker->pos;
- data->offset = track->offset;
}
else if (area == TRACK_AREA_PAT) {
- if (action == SLIDE_ACTION_SIZE) {
- data->corners = marker->pattern_corners;
- }
- else if (action == SLIDE_ACTION_OFFSET) {
- data->pos = marker->pos;
- data->offset = track->offset;
- data->old_markers = MEM_callocN(sizeof(*data->old_markers) * track->markersnr,
- "slide markers");
- for (int a = 0; a < track->markersnr; a++) {
- copy_v2_v2(data->old_markers[a], track->markers[a].pos);
- }
- }
- else if (action == SLIDE_ACTION_POS) {
+ if (action == SLIDE_ACTION_POS) {
data->corners = marker->pattern_corners;
data->pos = marker->pattern_corners[corner];
- copy_v2_v2(data->spos, data->pos);
}
else if (action == SLIDE_ACTION_TILT_SIZE) {
data->corners = marker->pattern_corners;
- slide_marker_tilt_slider(marker, data->spos);
}
}
else if (area == TRACK_AREA_SEARCH) {
@@ -434,7 +428,6 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc,
copy_v2_v2(data->old_search_min, marker->search_min);
copy_v2_v2(data->old_search_max, marker->search_max);
copy_v2_v2(data->old_pos, marker->pos);
- copy_v2_v2(data->old_offset, track->offset);
return data;
}
@@ -497,7 +490,7 @@ static int mouse_to_tilt_distance_squared(const MovieTrackingMarker *marker,
int height)
{
float slider[2];
- slide_marker_tilt_slider(marker, slider);
+ slide_marker_tilt_slider(marker->pos, marker->pattern_corners, slider);
return mouse_to_slide_zone_distance_squared(co, slider, width, height);
}
@@ -534,117 +527,96 @@ static bool slide_check_corners(float (*corners)[2])
return true;
}
-MovieTrackingTrack *tracking_marker_check_slide(
- bContext *C, const wmEvent *event, int *r_area, int *r_action, int *r_corner)
+static MovieTrackingTrack *tracking_marker_check_slide(
+ bContext *C, const float co[2], int *r_area, eSlideAction *r_action, int *r_corner)
{
const float distance_clip_squared = 12.0f * 12.0f;
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *region = CTX_wm_region(C);
-
MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTrackingTrack *track;
- int width, height;
- float co[2];
ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- int framenr = ED_space_clip_get_clip_frame_number(sc);
+ const int framenr = ED_space_clip_get_clip_frame_number(sc);
float global_min_distance_squared = FLT_MAX;
- /* Sliding zone designator which is the closest to the mouse
- * across all the tracks.
- */
- int min_action = -1, min_area = 0, min_corner = -1;
+ /* Sliding zone designator which is the closest to the mouse across all the tracks. */
+ eSlideAction min_action;
+ int min_area = 0, min_corner = -1;
MovieTrackingTrack *min_track = NULL;
+ int width, height;
ED_space_clip_get_size(sc, &width, &height);
-
if (width == 0 || height == 0) {
return NULL;
}
- ED_clip_mouse_pos(sc, region, event->mval, co);
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
+ if (!TRACK_VIEW_SELECTED(sc, track) || (track->flag & TRACK_LOCKED)) {
+ continue;
+ }
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- /* Sliding zone designator which is the closest to the mouse for
- * the current tracks.
- */
- float min_distance_squared = FLT_MAX;
- int action = -1, area = 0, corner = -1;
-
- if ((marker->flag & MARKER_DISABLED) == 0) {
- float distance_squared;
-
- /* We start checking with whether the mouse is close enough
- * to the pattern offset area.
- */
- distance_squared = mouse_to_offset_distance_squared(track, marker, co, width, height);
- area = TRACK_AREA_POINT;
- action = SLIDE_ACTION_POS;
+ const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ if (marker->flag & MARKER_DISABLED) {
+ continue;
+ }
- /* NOTE: All checks here are assuming there's no maximum distance
- * limit, so checks are quite simple here.
- * Actual distance clipping happens later once all the sliding
- * zones are checked.
- */
+ /* We start checking with whether the mouse is close enough to the pattern offset area. */
+ float distance_squared = mouse_to_offset_distance_squared(track, marker, co, width, height);
+
+ /* Sliding zone designator which is the closest to the mouse for the current tracks.
+ *
+ * NOTE: All checks here are assuming there's no maximum distance limit, so checks are quite
+ * simple here. Actual distance clipping happens later once all the sliding zones are checked.
+ */
+ float min_distance_squared = distance_squared;
+ int area = TRACK_AREA_POINT;
+ int action = SLIDE_ACTION_POS;
+ int corner = -1;
+
+ /* If search area is visible, check how close to its sliding zones mouse is. */
+ if (sc->flag & SC_SHOW_MARKER_SEARCH) {
+ distance_squared = mouse_to_search_corner_distance_squared(marker, co, 1, width, height);
+ if (distance_squared < min_distance_squared) {
+ area = TRACK_AREA_SEARCH;
+ action = SLIDE_ACTION_OFFSET;
min_distance_squared = distance_squared;
+ }
- /* If search area is visible, check how close to its sliding
- * zones mouse is.
- */
- if (sc->flag & SC_SHOW_MARKER_SEARCH) {
- distance_squared = mouse_to_search_corner_distance_squared(marker, co, 1, width, height);
- if (distance_squared < min_distance_squared) {
- area = TRACK_AREA_SEARCH;
- action = SLIDE_ACTION_OFFSET;
- min_distance_squared = distance_squared;
- }
-
- distance_squared = mouse_to_search_corner_distance_squared(marker, co, 0, width, height);
- if (distance_squared < min_distance_squared) {
- area = TRACK_AREA_SEARCH;
- action = SLIDE_ACTION_SIZE;
- min_distance_squared = distance_squared;
- }
- }
-
- /* If pattern area is visible, check which corner is closest to
- * the mouse.
- */
- if (sc->flag & SC_SHOW_MARKER_PATTERN) {
- int current_corner = -1;
- distance_squared = mouse_to_closest_pattern_corner_distance_squared(
- marker, co, width, height, &current_corner);
- if (distance_squared < min_distance_squared) {
- area = TRACK_AREA_PAT;
- action = SLIDE_ACTION_POS;
- corner = current_corner;
- min_distance_squared = distance_squared;
- }
+ distance_squared = mouse_to_search_corner_distance_squared(marker, co, 0, width, height);
+ if (distance_squared < min_distance_squared) {
+ area = TRACK_AREA_SEARCH;
+ action = SLIDE_ACTION_SIZE;
+ min_distance_squared = distance_squared;
+ }
+ }
- /* Here we also check whether the mouse is actually closer to
- * the widget which controls scale and tilt.
- */
- distance_squared = mouse_to_tilt_distance_squared(marker, co, width, height);
- if (distance_squared < min_distance_squared) {
- area = TRACK_AREA_PAT;
- action = SLIDE_ACTION_TILT_SIZE;
- min_distance_squared = distance_squared;
- }
- }
+ /* If pattern area is visible, check which corner is closest to the mouse. */
+ if (sc->flag & SC_SHOW_MARKER_PATTERN) {
+ int current_corner = -1;
+ distance_squared = mouse_to_closest_pattern_corner_distance_squared(
+ marker, co, width, height, &current_corner);
+ if (distance_squared < min_distance_squared) {
+ area = TRACK_AREA_PAT;
+ action = SLIDE_ACTION_POS;
+ corner = current_corner;
+ min_distance_squared = distance_squared;
+ }
- if (min_distance_squared < global_min_distance_squared) {
- min_area = area;
- min_action = action;
- min_corner = corner;
- min_track = track;
- global_min_distance_squared = min_distance_squared;
- }
+ /* Here we also check whether the mouse is actually closer to the widget which controls scale
+ * and tilt. */
+ distance_squared = mouse_to_tilt_distance_squared(marker, co, width, height);
+ if (distance_squared < min_distance_squared) {
+ area = TRACK_AREA_PAT;
+ action = SLIDE_ACTION_TILT_SIZE;
+ min_distance_squared = distance_squared;
}
}
- track = track->next;
+ if (min_distance_squared < global_min_distance_squared) {
+ min_area = area;
+ min_action = action;
+ min_corner = corner;
+ min_track = track;
+ global_min_distance_squared = min_distance_squared;
+ }
}
if (global_min_distance_squared < distance_clip_squared / sc->zoom) {
@@ -659,9 +631,16 @@ MovieTrackingTrack *tracking_marker_check_slide(
}
return min_track;
}
+
return NULL;
}
+struct MovieTrackingTrack *tracking_find_slidable_track_in_proximity(struct bContext *C,
+ const float co[2])
+{
+ return tracking_marker_check_slide(C, co, NULL, NULL, NULL);
+}
+
static void *slide_marker_customdata(bContext *C, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
@@ -672,7 +651,8 @@ static void *slide_marker_customdata(bContext *C, const wmEvent *event)
float co[2];
void *customdata = NULL;
int framenr = ED_space_clip_get_clip_frame_number(sc);
- int area, action, corner;
+ eSlideAction action;
+ int area, corner;
ED_space_clip_get_size(sc, &width, &height);
@@ -682,7 +662,7 @@ static void *slide_marker_customdata(bContext *C, const wmEvent *event)
ED_clip_mouse_pos(sc, region, event->mval, co);
- track = tracking_marker_check_slide(C, event, &area, &action, &corner);
+ track = tracking_marker_check_slide(C, co, &area, &action, &corner);
if (track != NULL) {
MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
customdata = create_slide_marker_data(
@@ -718,14 +698,12 @@ static int slide_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event
static void cancel_mouse_slide(SlideMarkerData *data)
{
- MovieTrackingTrack *track = data->track;
MovieTrackingMarker *marker = data->marker;
memcpy(marker->pattern_corners, data->old_corners, sizeof(marker->pattern_corners));
copy_v2_v2(marker->search_min, data->old_search_min);
copy_v2_v2(marker->search_max, data->old_search_max);
copy_v2_v2(marker->pos, data->old_pos);
- copy_v2_v2(track->offset, data->old_offset);
if (data->old_markers != NULL) {
for (int a = 0; a < data->track->markersnr; a++) {
@@ -765,7 +743,6 @@ static void free_slide_data(SlideMarkerData *data)
static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *region = CTX_wm_region(C);
SlideMarkerData *data = (SlideMarkerData *)op->customdata;
float dx, dy, mdelta[2];
@@ -804,110 +781,66 @@ static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (data->area == TRACK_AREA_POINT) {
- if (data->action == SLIDE_ACTION_OFFSET) {
- data->offset[0] = data->old_offset[0] + dx;
- data->offset[1] = data->old_offset[1] + dy;
- }
- else {
- data->pos[0] = data->old_pos[0] + dx;
- data->pos[1] = data->old_pos[1] + dy;
- }
+ data->pos[0] += dx;
+ data->pos[1] += dy;
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
DEG_id_tag_update(&sc->clip->id, 0);
}
else if (data->area == TRACK_AREA_PAT) {
- if (data->action == SLIDE_ACTION_SIZE) {
- float start[2], end[2];
- float scale;
-
- ED_clip_point_stable_pos(sc, region, data->mval[0], data->mval[1], &start[0], &start[1]);
-
- sub_v2_v2(start, data->old_pos);
-
- if (len_squared_v2(start) != 0.0f) {
- float mval[2];
-
- if (data->accurate) {
- mval[0] = data->mval[0] + (event->mval[0] - data->mval[0]) / 5.0f;
- mval[1] = data->mval[1] + (event->mval[1] - data->mval[1]) / 5.0f;
- }
- else {
- mval[0] = event->mval[0];
- mval[1] = event->mval[1];
- }
+ if (data->action == SLIDE_ACTION_POS) {
+ float prev_pos[2];
+ copy_v2_v2(prev_pos, data->pos);
- ED_clip_point_stable_pos(sc, region, mval[0], mval[1], &end[0], &end[1]);
-
- sub_v2_v2(end, data->old_pos);
- scale = len_v2(end) / len_v2(start);
-
- if (scale > 0.0f) {
- for (int a = 0; a < 4; a++) {
- mul_v2_v2fl(data->corners[a], data->old_corners[a], scale);
- }
- }
- }
-
- BKE_tracking_marker_clamp(data->marker, CLAMP_PAT_DIM);
- }
- else if (data->action == SLIDE_ACTION_OFFSET) {
- const float d[2] = {dx, dy};
- for (int a = 0; a < data->track->markersnr; a++) {
- add_v2_v2v2(data->track->markers[a].pos, data->old_markers[a], d);
- }
- sub_v2_v2v2(data->offset, data->old_offset, d);
- }
- else if (data->action == SLIDE_ACTION_POS) {
- float spos[2];
-
- copy_v2_v2(spos, data->pos);
-
- data->pos[0] = data->spos[0] + dx;
- data->pos[1] = data->spos[1] + dy;
+ data->pos[0] += dx;
+ data->pos[1] += dy;
if (!slide_check_corners(data->corners)) {
- copy_v2_v2(data->pos, spos);
+ copy_v2_v2(data->pos, prev_pos);
}
- /* Currently only patterns are allowed to have such
- * combination of event and data.
- */
- BKE_tracking_marker_clamp(data->marker, CLAMP_PAT_DIM);
+ /* Allow pattern to be arbitrary size and resize search area if needed. */
+ BKE_tracking_marker_clamp_search_size(data->marker);
}
else if (data->action == SLIDE_ACTION_TILT_SIZE) {
- const float mouse_delta[2] = {dx, dy};
-
- /* Vector which connects marker position with tilt/scale sliding area before sliding
- * began. */
- float start[2];
- sub_v2_v2v2(start, data->spos, data->old_pos);
- start[0] *= data->width;
- start[1] *= data->height;
-
- /* Vector which connects marker position with tilt/scale sliding area with the sliding
- * delta applied. */
- float end[2];
- add_v2_v2v2(end, data->spos, mouse_delta);
- sub_v2_v2(end, data->old_pos);
- end[0] *= data->width;
- end[1] *= data->height;
+ const float delta[2] = {dx, dy};
+
+ /* Slider position relative to the marker position using current state of pattern
+ * corners. */
+ float slider[2];
+ slide_marker_tilt_slider_relative(data->corners, slider);
+
+ /* Vector which connects marker position with the slider state at the current corners
+ * state.
+ * The coordinate is in the pixel space. */
+ float start_px[2];
+ copy_v2_v2(start_px, slider);
+ start_px[0] *= data->width;
+ start_px[1] *= data->height;
+
+ /* Vector which connects marker position with the slider state with the new mouse delta
+ * taken into account.
+ * The coordinate is in the pixel space. */
+ float end_px[2];
+ add_v2_v2v2(end_px, slider, delta);
+ end_px[0] *= data->width;
+ end_px[1] *= data->height;
float scale = 1.0f;
- if (len_squared_v2(start) != 0.0f) {
- scale = len_v2(end) / len_v2(start);
+ if (len_squared_v2(start_px) != 0.0f) {
+ scale = len_v2(end_px) / len_v2(start_px);
if (scale < 0.0f) {
scale = 0.0;
}
}
- const float angle = -angle_signed_v2v2(start, end);
+ const float angle = -angle_signed_v2v2(start_px, end_px);
for (int a = 0; a < 4; a++) {
float vec[2];
- mul_v2_v2fl(data->corners[a], data->old_corners[a], scale);
+ mul_v2_fl(data->corners[a], scale);
copy_v2_v2(vec, data->corners[a]);
vec[0] *= data->width;
@@ -917,30 +850,32 @@ static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
data->corners[a][1] = (vec[1] * cosf(angle) + vec[0] * sinf(angle)) / data->height;
}
- BKE_tracking_marker_clamp(data->marker, CLAMP_PAT_DIM);
+ BKE_tracking_marker_clamp_search_size(data->marker);
}
}
else if (data->area == TRACK_AREA_SEARCH) {
if (data->action == SLIDE_ACTION_SIZE) {
- data->min[0] = data->old_search_min[0] - dx;
- data->max[0] = data->old_search_max[0] + dx;
+ data->min[0] -= dx;
+ data->min[1] += dy;
- data->min[1] = data->old_search_min[1] + dy;
- data->max[1] = data->old_search_max[1] - dy;
+ data->max[0] += dx;
+ data->max[1] -= dy;
- BKE_tracking_marker_clamp(data->marker, CLAMP_SEARCH_DIM);
- }
- else if (data->area == TRACK_AREA_SEARCH) {
- const float d[2] = {dx, dy};
- add_v2_v2v2(data->min, data->old_search_min, d);
- add_v2_v2v2(data->max, data->old_search_max, d);
+ BKE_tracking_marker_clamp_search_size(data->marker);
}
+ else if (data->action == SLIDE_ACTION_OFFSET) {
+ const float delta[2] = {dx, dy};
+ add_v2_v2(data->min, delta);
+ add_v2_v2(data->max, delta);
- BKE_tracking_marker_clamp(data->marker, CLAMP_SEARCH_POS);
+ BKE_tracking_marker_clamp_search_position(data->marker);
+ }
}
data->marker->flag &= ~MARKER_TRACKED;
+ copy_v2_v2_int(data->mval, event->mval);
+
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
break;
@@ -1012,9 +947,9 @@ static int clear_track_path_exec(bContext *C, wmOperator *op)
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- int action = RNA_enum_get(op->ptr, "action");
+ const eTrackClearAction action = RNA_enum_get(op->ptr, "action");
const bool clear_active = RNA_boolean_get(op->ptr, "clear_active");
- int framenr = ED_space_clip_get_clip_frame_number(sc);
+ const int framenr = ED_space_clip_get_clip_frame_number(sc);
if (clear_active) {
MovieTrackingTrack *track = BKE_tracking_track_get_active(tracking);
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index ad604fe59bc..bbfbbd2cc58 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -273,7 +273,18 @@ void ed_tracking_deselect_all_plane_tracks(ListBase *plane_tracks_base)
}
}
-static int mouse_select(bContext *C, const float co[2], const bool extend, const bool deselect_all)
+static bool select_poll(bContext *C)
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+
+ if (sc) {
+ return sc->clip && sc->view == SC_VIEW_CLIP;
+ }
+
+ return false;
+}
+
+static int select_exec(bContext *C, wmOperator *op)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -281,12 +292,35 @@ static int mouse_select(bContext *C, const float co[2], const bool extend, const
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- MovieTrackingTrack *track;
- MovieTrackingPlaneTrack *plane_track;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
+
+ float co[2];
+ RNA_float_get_array(op->ptr, "location", co);
+
+ /* Special code which allows to slide a marker which belongs to currently selected but not yet
+ * active track. If such track is found activate it and return pass-though so that marker slide
+ * operator can be used immediately after.
+ * This logic makes it convenient to slide markers when left mouse selection is used. */
+ if (!extend) {
+ MovieTrackingTrack *track = tracking_find_slidable_track_in_proximity(C, co);
+ if (track != NULL) {
+ MovieClip *clip_iter = ED_space_clip_get_clip(sc);
+
+ clip_iter->tracking.act_track = track;
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ DEG_id_tag_update(&clip_iter->id, ID_RECALC_SELECT);
+
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+
float distance_to_track, distance_to_plane_track;
- track = find_nearest_track(sc, tracksbase, co, &distance_to_track);
- plane_track = find_nearest_plane_track(sc, plane_tracks_base, co, &distance_to_plane_track);
+ MovieTrackingTrack *track = find_nearest_track(sc, tracksbase, co, &distance_to_track);
+ MovieTrackingPlaneTrack *plane_track = find_nearest_plane_track(
+ sc, plane_tracks_base, co, &distance_to_plane_track);
ClipViewLockState lock_state;
ED_clip_view_lock_state_store(C, &lock_state);
@@ -375,51 +409,12 @@ static int mouse_select(bContext *C, const float co[2], const bool extend, const
return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
-static bool select_poll(bContext *C)
-{
- SpaceClip *sc = CTX_wm_space_clip(C);
-
- if (sc) {
- return sc->clip && sc->view == SC_VIEW_CLIP;
- }
-
- return false;
-}
-
-static int select_exec(bContext *C, wmOperator *op)
-{
- float co[2];
-
- RNA_float_get_array(op->ptr, "location", co);
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
-
- return mouse_select(C, co, extend, deselect_all);
-}
-
static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ARegion *region = CTX_wm_region(C);
float co[2];
- const bool extend = RNA_boolean_get(op->ptr, "extend");
-
- if (!extend) {
- MovieTrackingTrack *track = tracking_marker_check_slide(C, event, NULL, NULL, NULL);
-
- if (track) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- clip->tracking.act_track = track;
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
- DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
-
- return OPERATOR_PASS_THROUGH;
- }
- }
-
ED_clip_mouse_pos(sc, region, event->mval, co);
RNA_float_set_array(op->ptr, "location", co);
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 59ecef7d4c6..cfbbc1a1b45 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -336,7 +336,7 @@ enum {
};
typedef struct FileListEntryPreview {
- char path[FILE_MAX];
+ char filepath[FILE_MAX];
uint flags;
int index;
int attributes; /* from FileDirEntry. */
@@ -1636,13 +1636,13 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat
source = THB_SOURCE_FONT;
}
- IMB_thumb_path_lock(preview->path);
+ IMB_thumb_path_lock(preview->filepath);
/* 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. Do not create preview when file is offline. */
ImBuf *imbuf = (preview->attributes & FILE_ATTR_OFFLINE) ?
- IMB_thumb_read(preview->path, THB_LARGE) :
- IMB_thumb_manage(preview->path, THB_LARGE, source);
- IMB_thumb_path_unlock(preview->path);
+ IMB_thumb_read(preview->filepath, THB_LARGE) :
+ IMB_thumb_manage(preview->filepath, THB_LARGE, source);
+ IMB_thumb_path_unlock(preview->filepath);
if (imbuf) {
preview->icon_id = BKE_icon_imbuf_create(imbuf);
}
@@ -1753,7 +1753,7 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
if (preview_in_memory) {
/* TODO(mano-wii): No need to use the thread API here. */
BLI_assert(BKE_previewimg_is_finished(preview_in_memory, ICON_SIZE_PREVIEW));
- preview->path[0] = '\0';
+ preview->filepath[0] = '\0';
ImBuf *imbuf = BKE_previewimg_to_imbuf(preview_in_memory, ICON_SIZE_PREVIEW);
if (imbuf) {
preview->icon_id = BKE_icon_imbuf_create(imbuf);
@@ -1762,13 +1762,13 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
}
else {
if (entry->redirection_path) {
- BLI_strncpy(preview->path, entry->redirection_path, FILE_MAXDIR);
+ BLI_strncpy(preview->filepath, entry->redirection_path, FILE_MAXDIR);
}
else {
BLI_join_dirfile(
- preview->path, sizeof(preview->path), filelist->filelist.root, entry->relpath);
+ preview->filepath, sizeof(preview->filepath), filelist->filelist.root, entry->relpath);
}
- // printf("%s: %d - %s\n", __func__, preview->index, preview->path);
+ // printf("%s: %d - %s\n", __func__, preview->index, preview->filepath);
FileListEntryPreviewTaskData *preview_taskdata = MEM_mallocN(sizeof(*preview_taskdata),
__func__);
@@ -2667,7 +2667,7 @@ bool filelist_cache_previews_update(FileList *filelist)
* we do not want to cache it again here. */
entry = filelist_file_ex(filelist, preview->index, false);
- // printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+ // printf("%s: %d - %s - %p\n", __func__, preview->index, preview->filepath, preview->img);
if (entry) {
if (preview->icon_id) {
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 011506368ee..ce36e3e4e4f 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -1364,3 +1364,21 @@ ScrArea *ED_fileselect_handler_area_find(const wmWindow *win, const wmOperator *
return NULL;
}
+
+ScrArea *ED_fileselect_handler_area_find_any_with_op(const wmWindow *win)
+{
+ const bScreen *screen = WM_window_get_active_screen(win);
+
+ ED_screen_areas_iter (win, screen, area) {
+ if (area->spacetype != SPACE_FILE) {
+ continue;
+ }
+
+ const SpaceFile *sfile = area->spacedata.first;
+ if (sfile->op) {
+ return area;
+ }
+ }
+
+ return NULL;
+}
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index 65354591034..10cde239987 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -519,13 +519,13 @@ void fsmenu_remove_entry(struct FSMenu *fsmenu, FSMenuCategory category, int idx
}
}
-void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename)
+void fsmenu_write_file(struct FSMenu *fsmenu, const char *filepath)
{
FSMenuEntry *fsm_iter = NULL;
char fsm_name[FILE_MAX];
int nwritten = 0;
- FILE *fp = BLI_fopen(filename, "w");
+ FILE *fp = BLI_fopen(filepath, "w");
if (!fp) {
return;
}
@@ -556,14 +556,14 @@ void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename)
fclose(fp);
}
-void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename)
+void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filepath)
{
char line[FILE_MAXDIR];
char name[FILE_MAXFILE];
FSMenuCategory category = FS_CATEGORY_BOOKMARKS;
FILE *fp;
- fp = BLI_fopen(filename, "r");
+ fp = BLI_fopen(filepath, "r");
if (!fp) {
return;
}
diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h
index 861c37ecaa1..6e980a326fc 100644
--- a/source/blender/editors/space_file/fsmenu.h
+++ b/source/blender/editors/space_file/fsmenu.h
@@ -38,10 +38,10 @@ short fsmenu_can_save(struct FSMenu *fsmenu, enum FSMenuCategory category, int i
void fsmenu_remove_entry(struct FSMenu *fsmenu, enum FSMenuCategory category, int idx);
/** saves the 'bookmarks' to the specified file */
-void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename);
+void fsmenu_write_file(struct FSMenu *fsmenu, const char *filepath);
/** reads the 'bookmarks' from the specified file */
-void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename);
+void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filepath);
/** adds system specific directories */
void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index aa77aab2283..336331e44e7 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1680,184 +1680,28 @@ void IMAGE_OT_replace(wmOperatorType *ot)
typedef struct ImageSaveData {
ImageUser *iuser;
Image *image;
- ImageFormatData im_format;
+ ImageSaveOptions opts;
} ImageSaveData;
-static char imtype_best_depth(ImBuf *ibuf, const char imtype)
+static void image_save_options_from_op(Main *bmain, ImageSaveOptions *opts, wmOperator *op)
{
- const char depth_ok = BKE_imtype_valid_depths(imtype);
-
- if (ibuf->rect_float) {
- if (depth_ok & R_IMF_CHAN_DEPTH_32) {
- return R_IMF_CHAN_DEPTH_32;
- }
- if (depth_ok & R_IMF_CHAN_DEPTH_24) {
- return R_IMF_CHAN_DEPTH_24;
- }
- if (depth_ok & R_IMF_CHAN_DEPTH_16) {
- return R_IMF_CHAN_DEPTH_16;
- }
- if (depth_ok & R_IMF_CHAN_DEPTH_12) {
- return R_IMF_CHAN_DEPTH_12;
- }
- return R_IMF_CHAN_DEPTH_8;
- }
-
- if (depth_ok & R_IMF_CHAN_DEPTH_8) {
- return R_IMF_CHAN_DEPTH_8;
- }
- if (depth_ok & R_IMF_CHAN_DEPTH_12) {
- return R_IMF_CHAN_DEPTH_12;
- }
- if (depth_ok & R_IMF_CHAN_DEPTH_16) {
- return R_IMF_CHAN_DEPTH_16;
- }
- if (depth_ok & R_IMF_CHAN_DEPTH_24) {
- return R_IMF_CHAN_DEPTH_24;
- }
- if (depth_ok & R_IMF_CHAN_DEPTH_32) {
- return R_IMF_CHAN_DEPTH_32;
- }
- return R_IMF_CHAN_DEPTH_8; /* fallback, should not get here */
-}
-
-static int image_save_options_init(Main *bmain,
- ImageSaveOptions *opts,
- Image *ima,
- ImageUser *iuser,
- const bool guess_path,
- const bool save_as_render)
-{
- void *lock;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
-
- if (ibuf) {
- Scene *scene = opts->scene;
- bool is_depth_set = false;
-
- if (ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE)) {
- /* imtype */
- BKE_image_format_init_for_write(&opts->im_format, scene, NULL);
- is_depth_set = true;
- if (!BKE_image_is_multiview(ima)) {
- /* In case multiview is disabled,
- * render settings would be invalid for render result in this area. */
- opts->im_format.stereo3d_format = *ima->stereo3d_format;
- opts->im_format.views_format = ima->views_format;
- }
- }
- else {
- if (ima->source == IMA_SRC_GENERATED) {
- opts->im_format.imtype = R_IMF_IMTYPE_PNG;
- opts->im_format.compress = ibuf->foptions.quality;
- opts->im_format.planes = ibuf->planes;
- }
- else {
- BKE_image_format_from_imbuf(&opts->im_format, ibuf);
- }
-
- /* use the multiview image settings as the default */
- opts->im_format.stereo3d_format = *ima->stereo3d_format;
- opts->im_format.views_format = ima->views_format;
-
- BKE_image_format_color_management_copy_from_scene(&opts->im_format, scene);
- }
-
- opts->im_format.color_management = R_IMF_COLOR_MANAGEMENT_FOLLOW_SCENE;
-
- if (ima->source == IMA_SRC_TILED) {
- BLI_strncpy(opts->filepath, ima->filepath, sizeof(opts->filepath));
- BLI_path_abs(opts->filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
- }
- else {
- BLI_strncpy(opts->filepath, ibuf->name, sizeof(opts->filepath));
- }
-
- /* sanitize all settings */
-
- /* unlikely but just in case */
- if (ELEM(opts->im_format.planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB, R_IMF_PLANES_RGBA) == 0) {
- opts->im_format.planes = R_IMF_PLANES_RGBA;
- }
-
- /* depth, account for float buffer and format support */
- if (is_depth_set == false) {
- opts->im_format.depth = imtype_best_depth(ibuf, opts->im_format.imtype);
- }
-
- /* some formats don't use quality so fallback to scenes quality */
- if (opts->im_format.quality == 0) {
- opts->im_format.quality = scene->r.im_format.quality;
- }
-
- /* check for empty path */
- if (guess_path && opts->filepath[0] == 0) {
- const bool is_prev_save = !STREQ(G.ima, "//");
- if (save_as_render) {
- if (is_prev_save) {
- BLI_strncpy(opts->filepath, G.ima, sizeof(opts->filepath));
- }
- else {
- BLI_strncpy(opts->filepath, "//untitled", sizeof(opts->filepath));
- BLI_path_abs(opts->filepath, BKE_main_blendfile_path(bmain));
- }
- }
- else {
- BLI_snprintf(opts->filepath, sizeof(opts->filepath), "//%s", ima->id.name + 2);
- BLI_path_make_safe(opts->filepath);
- BLI_path_abs(opts->filepath, is_prev_save ? G.ima : BKE_main_blendfile_path(bmain));
- }
-
- /* append UDIM marker if not present */
- if (ima->source == IMA_SRC_TILED && strstr(opts->filepath, "<UDIM>") == NULL) {
- int len = strlen(opts->filepath);
- STR_CONCAT(opts->filepath, len, ".<UDIM>");
- }
- }
- }
-
- BKE_image_release_ibuf(ima, ibuf, lock);
-
- return (ibuf != NULL);
-}
-
-static void image_save_options_from_op(Main *bmain,
- ImageSaveOptions *opts,
- wmOperator *op,
- ImageFormatData *imf)
-{
- if (imf) {
- BKE_image_format_free(&opts->im_format);
- BKE_image_format_copy(&opts->im_format, imf);
- }
-
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
RNA_string_get(op->ptr, "filepath", opts->filepath);
BLI_path_abs(opts->filepath, BKE_main_blendfile_path(bmain));
}
-}
-
-static void image_save_options_to_op(ImageSaveOptions *opts, wmOperator *op)
-{
- if (op->customdata) {
- ImageSaveData *isd = op->customdata;
- BKE_image_format_free(&isd->im_format);
- BKE_image_format_copy(&isd->im_format, &opts->im_format);
- }
-
- RNA_string_set(op->ptr, "filepath", opts->filepath);
-}
-static bool save_image_op(
- Main *bmain, Image *ima, ImageUser *iuser, wmOperator *op, ImageSaveOptions *opts)
-{
opts->relative = (RNA_struct_find_property(op->ptr, "relative_path") &&
RNA_boolean_get(op->ptr, "relative_path"));
opts->save_copy = (RNA_struct_find_property(op->ptr, "copy") &&
RNA_boolean_get(op->ptr, "copy"));
opts->save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") &&
RNA_boolean_get(op->ptr, "save_as_render"));
+ opts->do_newpath = true;
+}
+static bool save_image_op(
+ Main *bmain, Image *ima, ImageUser *iuser, wmOperator *op, ImageSaveOptions *opts)
+{
WM_cursor_wait(true);
bool ok = BKE_image_save(op->reports, bmain, ima, iuser, opts);
@@ -1872,11 +1716,54 @@ static bool save_image_op(
return ok;
}
+static ImageSaveData *image_save_as_init(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Image *image = image_from_context(C);
+ ImageUser *iuser = image_user_from_context(C);
+ Scene *scene = CTX_data_scene(C);
+
+ ImageSaveData *isd = MEM_callocN(sizeof(*isd), __func__);
+ isd->image = image;
+ isd->iuser = iuser;
+
+ if (!BKE_image_save_options_init(&isd->opts, bmain, scene, image, iuser, true)) {
+ BKE_image_save_options_free(&isd->opts);
+ MEM_freeN(isd);
+ return NULL;
+ }
+
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ RNA_string_set(op->ptr, "filepath", isd->opts.filepath);
+ }
+
+ /* Enable save_copy by default for render results. */
+ if (ELEM(image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE) &&
+ !RNA_struct_property_is_set(op->ptr, "copy")) {
+ RNA_boolean_set(op->ptr, "copy", true);
+ }
+
+ if (!RNA_struct_property_is_set(op->ptr, "save_as_render")) {
+ RNA_boolean_set(op->ptr, "save_as_render", isd->opts.save_as_render);
+ }
+
+ /* Show multiview save options only if image has multiviews. */
+ PropertyRNA *prop;
+ prop = RNA_struct_find_property(op->ptr, "show_multiview");
+ RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(image));
+ prop = RNA_struct_find_property(op->ptr, "use_multiview");
+ RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(image));
+
+ op->customdata = isd;
+
+ return isd;
+}
+
static void image_save_as_free(wmOperator *op)
{
if (op->customdata) {
ImageSaveData *isd = op->customdata;
- BKE_image_format_free(&isd->im_format);
+ BKE_image_save_options_free(&isd->opts);
MEM_freeN(op->customdata);
op->customdata = NULL;
@@ -1886,96 +1773,55 @@ static void image_save_as_free(wmOperator *op)
static int image_save_as_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ImageSaveOptions opts;
+ ImageSaveData *isd;
- Image *image = NULL;
- ImageUser *iuser = NULL;
- ImageFormatData *imf = NULL;
if (op->customdata) {
- ImageSaveData *isd = op->customdata;
- image = isd->image;
- iuser = isd->iuser;
- imf = &isd->im_format;
+ isd = op->customdata;
}
else {
- image = image_from_context(C);
- iuser = image_user_from_context(C);
+ isd = image_save_as_init(C, op);
+ if (isd == NULL) {
+ return OPERATOR_CANCELLED;
+ }
}
- BKE_image_save_options_init(&opts, bmain, scene);
-
- /* just in case to initialize values,
- * these should be set on invoke or by the caller. */
- image_save_options_init(bmain, &opts, image, iuser, false, false);
+ image_save_options_from_op(bmain, &isd->opts, op);
+ BKE_image_save_options_update(&isd->opts, isd->image);
- image_save_options_from_op(bmain, &opts, op, imf);
- opts.do_newpath = true;
+ save_image_op(bmain, isd->image, isd->iuser, op, &isd->opts);
- save_image_op(bmain, image, iuser, op, &opts);
-
- if (opts.save_copy == false) {
- BKE_image_free_packedfiles(image);
+ if (isd->opts.save_copy == false) {
+ BKE_image_free_packedfiles(isd->image);
}
- BKE_image_save_options_free(&opts);
-
image_save_as_free(op);
return OPERATOR_FINISHED;
}
-static bool image_save_as_check(bContext *UNUSED(C), wmOperator *op)
+static bool image_save_as_check(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
ImageSaveData *isd = op->customdata;
- return WM_operator_filesel_ensure_ext_imtype(op, &isd->im_format);
+
+ image_save_options_from_op(bmain, &isd->opts, op);
+ BKE_image_save_options_update(&isd->opts, isd->image);
+
+ return WM_operator_filesel_ensure_ext_imtype(op, &isd->opts.im_format);
}
static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Main *bmain = CTX_data_main(C);
- Image *ima = image_from_context(C);
- ImageUser *iuser = image_user_from_context(C);
- Scene *scene = CTX_data_scene(C);
- ImageSaveOptions opts;
- PropertyRNA *prop;
- const bool save_as_render = (ima->source == IMA_SRC_VIEWER);
-
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
return image_save_as_exec(C, op);
}
- BKE_image_save_options_init(&opts, bmain, scene);
-
- if (image_save_options_init(bmain, &opts, ima, iuser, true, save_as_render) == 0) {
- BKE_image_save_options_free(&opts);
+ ImageSaveData *isd = image_save_as_init(C, op);
+ if (isd == NULL) {
return OPERATOR_CANCELLED;
}
- image_save_options_to_op(&opts, op);
- /* enable save_copy by default for render results */
- if (ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE) &&
- !RNA_struct_property_is_set(op->ptr, "copy")) {
- RNA_boolean_set(op->ptr, "copy", true);
- }
-
- RNA_boolean_set(op->ptr, "save_as_render", save_as_render);
-
- ImageSaveData *isd = MEM_callocN(sizeof(*isd), __func__);
- isd->image = ima;
- isd->iuser = iuser;
-
- BKE_image_format_copy(&isd->im_format, &opts.im_format);
- op->customdata = isd;
-
- /* show multiview save options only if image has multiviews */
- prop = RNA_struct_find_property(op->ptr, "show_multiview");
- RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(ima));
- prop = RNA_struct_find_property(op->ptr, "use_multiview");
- RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(ima));
-
- image_filesel(C, op, opts.filepath);
- BKE_image_save_options_free(&opts);
+ image_filesel(C, op, isd->opts.filepath);
return OPERATOR_RUNNING_MODAL;
}
@@ -2003,7 +1849,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
ImageSaveData *isd = op->customdata;
PointerRNA imf_ptr;
const bool is_multiview = RNA_boolean_get(op->ptr, "show_multiview");
- const bool use_color_management = RNA_boolean_get(op->ptr, "save_as_render");
+ const bool save_as_render = RNA_boolean_get(op->ptr, "save_as_render");
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
@@ -2015,8 +1861,15 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
uiItemS(layout);
/* image template */
- RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &isd->im_format, &imf_ptr);
- uiTemplateImageSettings(layout, &imf_ptr, use_color_management);
+ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &isd->opts.im_format, &imf_ptr);
+ uiTemplateImageSettings(layout, &imf_ptr, save_as_render);
+
+ if (!save_as_render) {
+ PointerRNA linear_settings_ptr = RNA_pointer_get(&imf_ptr, "linear_colorspace_settings");
+ uiLayout *col = uiLayoutColumn(layout, true);
+ uiItemS(col);
+ uiItemR(col, &linear_settings_ptr, "name", 0, IFACE_("Color Space"), ICON_NONE);
+ }
/* multiview template */
if (is_multiview) {
@@ -2062,16 +1915,19 @@ void IMAGE_OT_save_as(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_boolean(ot->srna,
- "save_as_render",
- 0,
- "Save As Render",
- "Apply render part of display transform when saving byte image");
- RNA_def_boolean(ot->srna,
- "copy",
- 0,
- "Copy",
- "Create a new image file without modifying the current image in blender");
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(ot->srna,
+ "save_as_render",
+ 0,
+ "Save As Render",
+ "Apply render part of display transform when saving byte image");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna,
+ "copy",
+ 0,
+ "Copy",
+ "Create a new image file without modifying the current image in blender");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
image_operator_prop_allow_tokens(ot);
WM_operator_properties_filesel(ot,
@@ -2138,12 +1994,11 @@ static int image_save_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
- BKE_image_save_options_init(&opts, bmain, scene);
- if (image_save_options_init(bmain, &opts, image, iuser, false, false) == 0) {
+ if (!BKE_image_save_options_init(&opts, bmain, scene, image, iuser, false)) {
BKE_image_save_options_free(&opts);
return OPERATOR_CANCELLED;
}
- image_save_options_from_op(bmain, &opts, op, NULL);
+ image_save_options_from_op(bmain, &opts, op);
/* Check if file write permission is ok. */
if (BLI_exists(opts.filepath) && !BLI_file_is_writable(opts.filepath)) {
@@ -2316,6 +2171,14 @@ static bool image_has_valid_path(Image *ima)
return strchr(ima->filepath, '\\') || strchr(ima->filepath, '/');
}
+static bool image_should_pack_during_save_all(const Image *ima)
+{
+ /* Images without a filepath (implied with IMA_SRC_GENERATED) should
+ * be packed during a save_all operation. */
+ return (ima->source == IMA_SRC_GENERATED) ||
+ (ima->source == IMA_SRC_TILED && !BKE_image_has_filepath(ima));
+}
+
bool ED_image_should_save_modified(const Main *bmain)
{
ReportList reports;
@@ -2339,7 +2202,7 @@ int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports)
bool is_format_writable;
if (image_should_be_saved(ima, &is_format_writable)) {
- if (BKE_image_has_packedfile(ima) || (ima->source == IMA_SRC_GENERATED)) {
+ if (BKE_image_has_packedfile(ima) || image_should_pack_during_save_all(ima)) {
if (!ID_IS_LINKED(ima)) {
num_saveable_images++;
}
@@ -2396,15 +2259,14 @@ bool ED_image_save_all_modified(const bContext *C, ReportList *reports)
bool is_format_writable;
if (image_should_be_saved(ima, &is_format_writable)) {
- if (BKE_image_has_packedfile(ima) || (ima->source == IMA_SRC_GENERATED)) {
+ if (BKE_image_has_packedfile(ima) || image_should_pack_during_save_all(ima)) {
BKE_image_memorypack(ima);
}
else if (is_format_writable) {
if (image_has_valid_path(ima)) {
ImageSaveOptions opts;
Scene *scene = CTX_data_scene(C);
- BKE_image_save_options_init(&opts, bmain, scene);
- if (image_save_options_init(bmain, &opts, ima, NULL, false, false)) {
+ if (!BKE_image_save_options_init(&opts, bmain, scene, ima, NULL, false)) {
bool saved_successfully = BKE_image_save(reports, bmain, ima, NULL, &opts);
ok = ok && saved_successfully;
}
@@ -3040,9 +2902,8 @@ static bool image_pack_test(bContext *C, wmOperator *op)
return false;
}
- if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
- BKE_report(
- op->reports, RPT_ERROR, "Packing movies, image sequences or tiled images not supported");
+ if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
+ BKE_report(op->reports, RPT_ERROR, "Packing movies or image sequences not supported");
return false;
}
@@ -3110,9 +2971,8 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
- BKE_report(
- op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported");
+ if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
+ BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
return OPERATOR_CANCELLED;
}
@@ -3144,9 +3004,8 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
return OPERATOR_CANCELLED;
}
- if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
- BKE_report(
- op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported");
+ if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
+ BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c
index c3a48abcae1..1fd9fde084b 100644
--- a/source/blender/editors/space_image/image_undo.c
+++ b/source/blender/editors/space_image/image_undo.c
@@ -1040,7 +1040,7 @@ static ImageUndoStep *image_undo_push_begin(const char *name, int paint_mode)
bContext *C = NULL; /* special case, we never read from this. */
UndoStep *us_p = BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_IMAGE);
ImageUndoStep *us = (ImageUndoStep *)us_p;
- BLI_assert(ELEM(paint_mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D));
+ BLI_assert(ELEM(paint_mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D, PAINT_MODE_SCULPT));
us->paint_mode = paint_mode;
return us;
}
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 5e4389279eb..f89bfd2a36a 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -107,6 +107,7 @@ bool nla_panel_context(const bContext *C,
found = 1;
break;
}
+ case ANIMTYPE_NLAACTION:
case ANIMTYPE_SCENE: /* Top-Level Widgets doubling up as datablocks */
case ANIMTYPE_OBJECT:
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 8b059b33a9a..40082b08806 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -58,14 +58,12 @@
* --> Most channels are now selection only.
*/
-static int mouse_nla_channels(
- bContext *C, bAnimContext *ac, float x, int channel_index, short selectmode)
+static int mouse_nla_channels(bContext *C, bAnimContext *ac, int channel_index, short selectmode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
- View2D *v2d = &ac->region->v2d;
int notifierFlags = 0;
/* get the channel that was clicked on */
@@ -203,47 +201,8 @@ static int mouse_nla_channels(
}
case ANIMTYPE_NLATRACK: {
NlaTrack *nlt = (NlaTrack *)ale->data;
- AnimData *adt = ale->adt;
- short offset;
-
- /* offset for start of channel (on LHS of channel-list) */
- if (ale->id) {
- /* special exception for materials and particles */
- if (ELEM(GS(ale->id->name), ID_MA, ID_PA)) {
- offset = 21 + NLACHANNEL_BUTTON_WIDTH;
- }
- else {
- offset = 14;
- }
- }
- else {
- offset = 0;
- }
- if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) {
- /* toggle protection (only if there's a toggle there) */
- nlt->flag ^= NLATRACK_PROTECTED;
-
- /* notifier flags - channel was edited */
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
- }
- else if (x >= (v2d->cur.xmax - 2 * NLACHANNEL_BUTTON_WIDTH)) {
- /* toggle mute */
- nlt->flag ^= NLATRACK_MUTED;
-
- /* notifier flags - channel was edited */
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else if (x <= ((NLACHANNEL_BUTTON_WIDTH * 2) + offset)) {
- /* toggle 'solo' */
- BKE_nlatrack_solo_toggle(adt, nlt);
-
- /* notifier flags - channel was edited */
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else if (nlaedit_is_tweakmode_on(ac) == 0) {
+ if (nlaedit_is_tweakmode_on(ac) == 0) {
/* set selection */
if (selectmode == SELECT_INVERT) {
/* inverse selection status of this F-Curve only */
@@ -269,61 +228,40 @@ static int mouse_nla_channels(
case ANIMTYPE_NLAACTION: {
AnimData *adt = BKE_animdata_from_id(ale->id);
- /* button region... */
- if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) {
- if (nlaedit_is_tweakmode_on(ac) == 0) {
- /* 'push-down' action - only usable when not in tweak-mode */
- /* 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, ID_IS_OVERRIDE_LIBRARY(ale->id));
- }
- else {
- /* When in tweak-mode, this button becomes the toggle for mapped editing. */
- adt->flag ^= ADT_NLA_EDIT_NOMAP;
- }
+ /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block
+ * - this is useful when there's no clear divider, and makes more sense in
+ * the case of users trying to use this to change actions
+ * - in tweak-mode, clicking here gets us out of tweak-mode, as changing selection
+ * while in tweak-mode is really evil!
+ * - we disable "solo" flags too, to make it easier to work with stashed actions
+ * with less trouble
+ */
+ if (nlaedit_is_tweakmode_on(ac)) {
+ /* Exit tweak-mode immediately. */
+ nlaedit_disable_tweakmode(ac, true);
/* changes to NLA-Action occurred */
notifierFlags |= ND_NLA_ACTCHANGE;
ale->update |= ANIM_UPDATE_DEPS;
}
- /* OR rest of name... */
else {
- /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block
- * - this is useful when there's no clear divider, and makes more sense in
- * the case of users trying to use this to change actions
- * - in tweak-mode, clicking here gets us out of tweak-mode, as changing selection
- * while in tweak-mode is really evil!
- * - we disable "solo" flags too, to make it easier to work with stashed actions
- * with less trouble
- */
- if (nlaedit_is_tweakmode_on(ac)) {
- /* Exit tweak-mode immediately. */
- nlaedit_disable_tweakmode(ac, true);
-
- /* changes to NLA-Action occurred */
- notifierFlags |= ND_NLA_ACTCHANGE;
- ale->update |= ANIM_UPDATE_DEPS;
+ /* select/deselect */
+ if (selectmode == SELECT_INVERT) {
+ /* inverse selection status of this AnimData block only */
+ adt->flag ^= ADT_UI_SELECTED;
}
else {
- /* select/deselect */
- if (selectmode == SELECT_INVERT) {
- /* inverse selection status of this AnimData block only */
- adt->flag ^= ADT_UI_SELECTED;
- }
- else {
- /* select AnimData block by itself */
- ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_CLEAR);
- adt->flag |= ADT_UI_SELECTED;
- }
-
- /* set active? */
- if (adt->flag & ADT_UI_SELECTED) {
- adt->flag |= ADT_UI_ACTIVE;
- }
+ /* select AnimData block by itself */
+ ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_CLEAR);
+ adt->flag |= ADT_UI_SELECTED;
+ }
- notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ /* set active? */
+ if (adt->flag & ADT_UI_SELECTED) {
+ adt->flag |= ADT_UI_ACTIVE;
}
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
}
break;
}
@@ -386,7 +324,7 @@ static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEv
&channel_index);
/* handle mouse-click in the relevant channel then */
- notifierFlags = mouse_nla_channels(C, &ac, x, channel_index, selectmode);
+ notifierFlags = mouse_nla_channels(C, &ac, channel_index, selectmode);
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL);
diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc
index 958a9fdfc60..d5507619e0d 100644
--- a/source/blender/editors/space_node/drawnode.cc
+++ b/source/blender/editors/space_node/drawnode.cc
@@ -213,6 +213,11 @@ static void node_buts_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *pt
uiItemR(layout, ptr, "use_clamp", DEFAULT_FLAGS, nullptr, ICON_NONE);
}
+static void node_buts_combsep_color(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
NodeResizeDirection node_get_resize_direction(const bNode *node, const int x, const int y)
{
if (node->type == NODE_FRAME) {
@@ -480,6 +485,10 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_MATH:
ntype->draw_buttons = node_buts_math;
break;
+ case SH_NODE_COMBINE_COLOR:
+ case SH_NODE_SEPARATE_COLOR:
+ ntype->draw_buttons = node_buts_combsep_color;
+ break;
case SH_NODE_TEX_IMAGE:
ntype->draw_buttons = node_shader_buts_tex_image;
ntype->draw_buttons_ex = node_shader_buts_tex_image_ex;
@@ -589,6 +598,19 @@ static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), Pointe
uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
}
+static void node_composit_buts_combsep_color(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ bNode *node = (bNode *)ptr->data;
+ NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)node->storage;
+
+ uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
+ if (storage->mode == CMP_NODE_COMBSEP_COLOR_YCC) {
+ uiItemR(layout, ptr, "ycc_mode", DEFAULT_FLAGS, "", ICON_NONE);
+ }
+}
+
static void node_composit_backdrop_viewer(
SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
{
@@ -821,8 +843,12 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_HUECORRECT:
ntype->draw_buttons = node_composit_buts_huecorrect;
break;
- case CMP_NODE_COMBYCCA:
- case CMP_NODE_SEPYCCA:
+ case CMP_NODE_COMBINE_COLOR:
+ case CMP_NODE_SEPARATE_COLOR:
+ ntype->draw_buttons = node_composit_buts_combsep_color;
+ break;
+ case CMP_NODE_COMBYCCA_LEGACY:
+ case CMP_NODE_SEPYCCA_LEGACY:
ntype->draw_buttons = node_composit_buts_ycc;
break;
case CMP_NODE_MASK_BOX:
@@ -975,6 +1001,11 @@ static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), Poin
uiItemR(layout, ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE);
}
+static void node_texture_buts_combsep_color(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
/* only once called */
static void node_texture_set_butfunc(bNodeType *ntype)
{
@@ -1020,6 +1051,11 @@ static void node_texture_set_butfunc(bNodeType *ntype)
case TEX_NODE_OUTPUT:
ntype->draw_buttons = node_texture_buts_output;
break;
+
+ case TEX_NODE_COMBINE_COLOR:
+ case TEX_NODE_SEPARATE_COLOR:
+ ntype->draw_buttons = node_texture_buts_combsep_color;
+ break;
}
}
}
diff --git a/source/blender/editors/space_node/node_context_path.cc b/source/blender/editors/space_node/node_context_path.cc
index 4247d5a1fbc..dfc0beb13fc 100644
--- a/source/blender/editors/space_node/node_context_path.cc
+++ b/source/blender/editors/space_node/node_context_path.cc
@@ -139,7 +139,7 @@ static void get_context_path_node_geometry(const bContext &C,
Object *object = CTX_data_active_object(&C);
ui::context_path_add_generic(path, RNA_Object, object);
ModifierData *modifier = BKE_object_active_modifier(object);
- ui::context_path_add_generic(path, RNA_Modifier, modifier, ICON_MODIFIER);
+ ui::context_path_add_generic(path, RNA_Modifier, modifier, ICON_GEOMETRY_NODES);
context_path_add_node_tree_and_node_groups(snode, path);
}
}
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index 9076b17a926..f5048e0cc67 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -895,9 +895,9 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo
BLI_snprintf(line,
sizeof(line),
TIP_("\u2022 Mesh: %s vertices, %s edges, %s faces"),
- to_string(mesh_info.tot_verts).c_str(),
- to_string(mesh_info.tot_edges).c_str(),
- to_string(mesh_info.tot_faces).c_str());
+ to_string(mesh_info.verts_num).c_str(),
+ to_string(mesh_info.edges_num).c_str(),
+ to_string(mesh_info.faces_num).c_str());
ss << line << line_end;
break;
}
@@ -908,7 +908,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo
BLI_snprintf(line,
sizeof(line),
TIP_("\u2022 Point Cloud: %s points"),
- to_string(pointcloud_info.tot_points).c_str());
+ to_string(pointcloud_info.points_num).c_str());
ss << line << line_end;
break;
}
@@ -918,7 +918,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo
BLI_snprintf(line,
sizeof(line),
TIP_("\u2022 Curve: %s splines"),
- to_string(curve_info.tot_splines).c_str());
+ to_string(curve_info.splines_num).c_str());
ss << line << line_end;
break;
}
@@ -928,7 +928,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo
BLI_snprintf(line,
sizeof(line),
TIP_("\u2022 Instances: %s"),
- to_string(instances_info.tot_instances).c_str());
+ to_string(instances_info.instances_num).c_str());
ss << line << line_end;
break;
}
diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc
index 2d7972e2291..fb2f1bf3751 100644
--- a/source/blender/editors/space_node/node_edit.cc
+++ b/source/blender/editors/space_node/node_edit.cc
@@ -66,7 +66,9 @@ namespace blender::ed::space_node {
#define USE_ESC_COMPO
-/* ***************** composite job manager ********************** */
+/* -------------------------------------------------------------------- */
+/** \name Composite Job Manager
+ * \{ */
enum {
COM_RECALC_COMPOSITE = 1,
@@ -293,6 +295,12 @@ static void compo_startjob(void *cjv,
} // namespace blender::ed::space_node
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Composite Job C API
+ * \{ */
+
void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene *scene_owner)
{
using namespace blender::ed::space_node;
@@ -336,9 +344,13 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
+/** \} */
+
namespace blender::ed::space_node {
-/* ***************************************** */
+/* -------------------------------------------------------------------- */
+/** \name Composite Poll & Utility Functions
+ * \{ */
bool composite_node_active(bContext *C)
{
@@ -388,8 +400,14 @@ static void send_notifiers_after_tree_change(ID *id, bNodeTree *ntree)
}
}
+/** \} */
+
} // namespace blender::ed::space_node
+/* -------------------------------------------------------------------- */
+/** \name Node Editor Public API Functions
+ * \{ */
+
void ED_node_tree_propagate_change(const bContext *C, Main *bmain, bNodeTree *root_ntree)
{
if (C != nullptr) {
@@ -783,9 +801,13 @@ void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree))
// node_update_nodetree(C, ntree, 0.0f, 0.0f);
}
+/** \} */
+
namespace blender::ed::space_node {
-/* ***************** generic operator functions for nodes ***************** */
+/* -------------------------------------------------------------------- */
+/** \name Generic Operator Functions for Nodes
+ * \{ */
#if 0 /* UNUSED */
@@ -861,7 +883,11 @@ static void edit_node_properties_get(
}
#endif
-/* ************************** Node generic ************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Generic
+ * \{ */
/* is rct in visible part of node? */
static bNode *visible_node(SpaceNode &snode, const rctf &rct)
@@ -874,7 +900,11 @@ static bNode *visible_node(SpaceNode &snode, const rctf &rct)
return nullptr;
}
-/* ********************** size widget operator ******************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Size Widget Operator
+ * \{ */
struct NodeSizeWidget {
float mxstart, mystart;
@@ -1077,7 +1107,11 @@ void NODE_OT_resize(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING;
}
-/* ********************** hidden sockets ******************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Hidden Sockets
+ * \{ */
bool node_has_hidden_sockets(bNode *node)
{
@@ -1211,7 +1245,11 @@ bool node_find_indicated_socket(SpaceNode &snode,
return false;
}
-/* ****************** Link Dimming *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Link Dimming
+ * \{ */
float node_link_dim_factor(const View2D &v2d, const bNodeLink &link)
{
@@ -1237,7 +1275,11 @@ bool node_link_is_hidden_or_dimmed(const View2D &v2d, const bNodeLink &link)
return nodeLinkIsHidden(&link) || node_link_dim_factor(v2d, link) < 0.5f;
}
-/* ****************** Duplicate *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Duplicate Operator
+ * \{ */
static void node_duplicate_reparent_recursive(const Map<const bNode *, bNode *> &node_map,
bNode *node)
@@ -1422,8 +1464,7 @@ void node_select_all(ListBase *lb, int action)
}
}
-/* ******************************** */
-/* XXX some code needing updating to operators. */
+/* XXX: some code needing updating to operators. */
/* goes over all scenes, reads render layers */
static int node_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op))
@@ -1526,7 +1567,11 @@ void NODE_OT_render_changed(wmOperatorType *ot)
ot->flag = 0;
}
-/* ****************** Hide operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Hide Operator
+ * \{ */
static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
{
@@ -1722,7 +1767,11 @@ void NODE_OT_hide_socket_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ****************** Mute operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Mute Operator
+ * \{ */
static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -1758,7 +1807,11 @@ void NODE_OT_mute_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ****************** Delete operator ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Delete Operator
+ * \{ */
static int node_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -1793,7 +1846,11 @@ void NODE_OT_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ****************** Switch View ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Switch View
+ * \{ */
static bool node_switch_view_poll(bContext *C)
{
@@ -1837,7 +1894,12 @@ void NODE_OT_switch_view_update(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ****************** Delete with reconnect ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Delete with Reconnect Operator
+ * \{ */
+
static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
@@ -1872,7 +1934,11 @@ void NODE_OT_delete_reconnect(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ****************** File Output Add Socket ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node File Output Add Socket Operator
+ * \{ */
static int node_output_file_add_socket_exec(bContext *C, wmOperator *op)
{
@@ -1922,7 +1988,11 @@ void NODE_OT_output_file_add_socket(wmOperatorType *ot)
ot->srna, "file_path", "Image", MAX_NAME, "File Path", "Subpath of the output file");
}
-/* ****************** Multi File Output Remove Socket ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Multi File Output Remove Socket Operator
+ * \{ */
static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -1968,7 +2038,11 @@ void NODE_OT_output_file_remove_active_socket(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ****************** Multi File Output Move Socket ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Multi File Output Move Socket Node
+ * \{ */
static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
{
@@ -2040,7 +2114,11 @@ void NODE_OT_output_file_move_active_socket(wmOperatorType *ot)
RNA_def_enum(ot->srna, "direction", direction_items, 2, "Direction", "");
}
-/* ****************** Copy Node Color ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Copy Node Color Operator
+ * \{ */
static int node_copy_color_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -2085,7 +2163,11 @@ void NODE_OT_node_copy_color(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ****************** Copy to clipboard ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Copy to Clipboard Operator
+ * \{ */
static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -2163,7 +2245,11 @@ void NODE_OT_clipboard_copy(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ****************** Paste from clipboard ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Paste from Clipboard
+ * \{ */
static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
{
@@ -2287,7 +2373,11 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/********************** Add interface socket operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node-Tree Add Interface Socket Operator
+ * \{ */
static bNodeSocket *ntree_get_active_interface_socket(ListBase *lb)
{
@@ -2357,7 +2447,11 @@ void NODE_OT_tree_socket_add(wmOperatorType *ot)
RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
}
-/********************** Remove interface socket operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node-Tree Remove Interface Socket Operator
+ * \{ */
static int ntree_socket_remove_exec(bContext *C, wmOperator *op)
{
@@ -2403,7 +2497,11 @@ void NODE_OT_tree_socket_remove(wmOperatorType *ot)
RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
}
-/********************** Change interface socket type operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node-Tree Change Interface Socket Type Operator
+ * \{ */
static int ntree_socket_change_type_exec(bContext *C, wmOperator *op)
{
@@ -2503,7 +2601,11 @@ void NODE_OT_tree_socket_change_type(wmOperatorType *ot)
ot->prop = prop;
}
-/********************** Move interface socket operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node-Tree Move Interface Socket Operator
+ * \{ */
static const EnumPropertyItem move_direction_items[] = {
{1, "UP", 0, "Up", ""},
@@ -2577,7 +2679,11 @@ void NODE_OT_tree_socket_move(wmOperatorType *ot)
RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
}
-/* ********************** Shader Script Update ******************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Shader Script Update
+ * \{ */
static bool node_shader_script_update_poll(bContext *C)
{
@@ -2722,7 +2828,11 @@ void NODE_OT_shader_script_update(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************** Viewer border ******************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Viewer Border
+ * \{ */
static void viewer_border_corner_to_backdrop(SpaceNode *snode,
ARegion *region,
@@ -2844,7 +2954,11 @@ void NODE_OT_clear_viewer_border(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ****************** Cryptomatte Add Socket ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cryptomatte Add Socket
+ * \{ */
static int node_cryptomatte_add_socket_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -2888,7 +3002,11 @@ void NODE_OT_cryptomatte_layer_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ****************** Cryptomatte Remove Socket ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cryptomatte Remove Socket
+ * \{ */
static int node_cryptomatte_remove_socket_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -2933,4 +3051,7 @@ void NODE_OT_cryptomatte_layer_remove(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/** \} */
+
} // namespace blender::ed::space_node
diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh
index 6d7348bfffc..924537d0e8a 100644
--- a/source/blender/editors/space_node/node_intern.hh
+++ b/source/blender/editors/space_node/node_intern.hh
@@ -31,7 +31,9 @@ struct wmKeyConfig;
struct wmWindow;
/* Outside of blender namespace to avoid Python documentation build error with `ctypes`. */
+extern "C" {
extern const char *node_context_dir[];
+};
namespace blender::ed::space_node {
@@ -74,13 +76,17 @@ struct SpaceNode_Runtime {
/** Mouse position for drawing socket-less links and adding nodes. */
float2 cursor;
- /* Indicates that the compositing tree in the space needs to be re-evaluated using the
+ /**
+ * Indicates that the compositing tree in the space needs to be re-evaluated using the
* auto-compositing pipeline.
- * Takes priority over the regular compsiting. */
+ * Takes priority over the regular compositing.
+ */
bool recalc_auto_compositing;
- /* Indicates that the compositing int the space tree needs to be re-evaluated using
- * regular compositing pipeline. */
+ /**
+ * Indicates that the compositing int the space tree needs to be re-evaluated using
+ * regular compositing pipeline.
+ */
bool recalc_regular_compositing;
/** Temporary data for modal linking operator. */
@@ -100,7 +106,7 @@ enum NodeResizeDirection {
};
ENUM_OPERATORS(NodeResizeDirection, NODE_RESIZE_LEFT);
-/* Nodes draw without dpi - the view zoom is flexible. */
+/* Nodes draw without DPI - the view zoom is flexible. */
#define HIDDEN_RAD (0.75f * U.widget_unit)
#define BASIS_RAD (0.2f * U.widget_unit)
#define NODE_DYS (U.widget_unit / 2)
diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc
index 005dbc1eb10..9d73156edab 100644
--- a/source/blender/editors/space_node/node_select.cc
+++ b/source/blender/editors/space_node/node_select.cc
@@ -716,7 +716,7 @@ void NODE_OT_select(wmOperatorType *ot)
prop = RNA_def_int_vector(ot->srna,
"location",
2,
- NULL,
+ nullptr,
INT_MIN,
INT_MAX,
"Location",
diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc
index 296cd1ff133..3963186f73b 100644
--- a/source/blender/editors/space_node/space_node.cc
+++ b/source/blender/editors/space_node/space_node.cc
@@ -327,8 +327,9 @@ static bool any_node_uses_id(const bNodeTree *ntree, const ID *id)
/**
* Tag the space to recalculate the compositing tree using auto-compositing pipeline.
*
- * Will check the space to be using a compsiting tree, and check whether auto-compositing
- * is enabled. If the checks do not pass then the function has no affect. */
+ * Will check the space to be using a compositing tree, and check whether auto-compositing
+ * is enabled. If the checks do not pass then the function has no affect.
+ */
static void node_area_tag_recalc_auto_compositing(SpaceNode *snode, ScrArea *area)
{
if (!ED_node_is_compositor(snode)) {
@@ -347,7 +348,8 @@ static void node_area_tag_recalc_auto_compositing(SpaceNode *snode, ScrArea *are
* For all node trees this will do `snode_set_context()` which takes care of setting an active
* tree. This will be done in the area refresh callback.
*
- * For compositor tree this will additionally start of the compositor job. */
+ * For compositor tree this will additionally start of the compositor job.
+ */
static void node_area_tag_tree_recalc(SpaceNode *snode, ScrArea *area)
{
if (ED_node_is_compositor(snode)) {
@@ -824,8 +826,10 @@ static void node_region_listener(const wmRegionListenerParams *params)
} // namespace blender::ed::space_node
/* Outside of blender namespace to avoid Python documentation build error with `ctypes`. */
+extern "C" {
const char *node_context_dir[] = {
"selected_nodes", "active_node", "light", "material", "world", nullptr};
+};
namespace blender::ed::space_node {
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index fae0e4be2a8..59f6bd85d59 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -38,8 +38,8 @@ set(SRC
tree/tree_display_data.cc
tree/tree_display_libraries.cc
tree/tree_display_orphaned.cc
- tree/tree_display_override_library_properties.cc
tree/tree_display_override_library_hierarchies.cc
+ tree/tree_display_override_library_properties.cc
tree/tree_display_scenes.cc
tree/tree_display_sequencer.cc
tree/tree_display_view_layer.cc
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.cc b/source/blender/editors/space_outliner/outliner_dragdrop.cc
index 88640210ea3..a22ce9d3d24 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.cc
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.cc
@@ -170,7 +170,8 @@ static TreeElement *outliner_drop_insert_find(bContext *C,
*r_insert_type = TE_INSERT_BEFORE;
return first;
}
- BLI_assert(0);
+
+ BLI_assert_unreachable();
return nullptr;
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc
index 36e21cf51a5..d165e98d7d4 100644
--- a/source/blender/editors/space_outliner/outliner_draw.cc
+++ b/source/blender/editors/space_outliner/outliner_draw.cc
@@ -38,6 +38,7 @@
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
+#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_report.h"
@@ -1817,7 +1818,7 @@ static void outliner_draw_overrides_rna_buts(uiBlock *block,
te->ys + pad_y,
item_max_width,
item_height,
- NULL,
+ nullptr,
0.0f,
0.0f,
0.0f,
@@ -2524,6 +2525,11 @@ static BIFIconID tree_element_get_icon_from_id(const ID *id)
return ICON_WORKSPACE;
case ID_MSK:
return ICON_MOD_MASK;
+ case ID_NT: {
+ const bNodeTree *ntree = (bNodeTree *)id;
+ const bNodeTreeType *ntreetype = ntree->typeinfo;
+ return (BIFIconID)ntreetype->ui_icon;
+ }
case ID_MC:
return ICON_SEQUENCE;
case ID_PC:
diff --git a/source/blender/editors/space_outliner/outliner_edit.cc b/source/blender/editors/space_outliner/outliner_edit.cc
index d6c5901b546..1de45b0ec96 100644
--- a/source/blender/editors/space_outliner/outliner_edit.cc
+++ b/source/blender/editors/space_outliner/outliner_edit.cc
@@ -334,8 +334,16 @@ static void do_item_rename(ARegion *region,
add_textbut = true;
}
}
- else if (te->idcode == ID_LI && ((Library *)tselem->id)->parent) {
- BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library");
+ else if (te->idcode == ID_LI) {
+ if (reinterpret_cast<Library *>(tselem->id)->parent) {
+ BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library");
+ }
+ else {
+ BKE_report(
+ reports,
+ RPT_WARNING,
+ "Library path is not editable from here anymore, please use Relocate operation instead");
+ }
}
else {
add_textbut = true;
diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc
index 5da64177e51..7321fd8fc7a 100644
--- a/source/blender/editors/space_outliner/outliner_tools.cc
+++ b/source/blender/editors/space_outliner/outliner_tools.cc
@@ -231,43 +231,51 @@ static void unlink_material_fn(bContext *UNUSED(C),
Material **matar = nullptr;
int a, totcol = 0;
- if (GS(tsep->id->name) == ID_OB) {
- Object *ob = (Object *)tsep->id;
- totcol = ob->totcol;
- matar = ob->mat;
- }
- else if (GS(tsep->id->name) == ID_ME) {
- Mesh *me = (Mesh *)tsep->id;
- totcol = me->totcol;
- matar = me->mat;
- }
- else if (GS(tsep->id->name) == ID_CU_LEGACY) {
- Curve *cu = (Curve *)tsep->id;
- totcol = cu->totcol;
- matar = cu->mat;
- }
- else if (GS(tsep->id->name) == ID_MB) {
- MetaBall *mb = (MetaBall *)tsep->id;
- totcol = mb->totcol;
- matar = mb->mat;
- }
- else if (GS(tsep->id->name) == ID_CV) {
- Curves *curves = (Curves *)tsep->id;
- totcol = curves->totcol;
- matar = curves->mat;
- }
- else if (GS(tsep->id->name) == ID_PT) {
- PointCloud *pointcloud = (PointCloud *)tsep->id;
- totcol = pointcloud->totcol;
- matar = pointcloud->mat;
- }
- else if (GS(tsep->id->name) == ID_VO) {
- Volume *volume = (Volume *)tsep->id;
- totcol = volume->totcol;
- matar = volume->mat;
- }
- else {
- BLI_assert(0);
+ switch (GS(tsep->id->name)) {
+ case ID_OB: {
+ Object *ob = (Object *)tsep->id;
+ totcol = ob->totcol;
+ matar = ob->mat;
+ break;
+ }
+ case ID_ME: {
+ Mesh *me = (Mesh *)tsep->id;
+ totcol = me->totcol;
+ matar = me->mat;
+ break;
+ }
+ case ID_CU_LEGACY: {
+ Curve *cu = (Curve *)tsep->id;
+ totcol = cu->totcol;
+ matar = cu->mat;
+ break;
+ }
+ case ID_MB: {
+ MetaBall *mb = (MetaBall *)tsep->id;
+ totcol = mb->totcol;
+ matar = mb->mat;
+ break;
+ }
+ case ID_CV: {
+ Curves *curves = (Curves *)tsep->id;
+ totcol = curves->totcol;
+ matar = curves->mat;
+ break;
+ }
+ case ID_PT: {
+ PointCloud *pointcloud = (PointCloud *)tsep->id;
+ totcol = pointcloud->totcol;
+ matar = pointcloud->mat;
+ break;
+ }
+ case ID_VO: {
+ Volume *volume = (Volume *)tsep->id;
+ totcol = volume->totcol;
+ matar = volume->mat;
+ break;
+ }
+ default:
+ BLI_assert_unreachable();
}
if (LIKELY(matar != nullptr)) {
@@ -492,7 +500,7 @@ static int outliner_scene_operation_exec(bContext *C, wmOperator *op)
ED_undo_push(C, "Delete Scene(s)");
}
else {
- BLI_assert(0);
+ BLI_assert_unreachable();
return OPERATOR_CANCELLED;
}
@@ -755,6 +763,10 @@ static void id_local_fn(bContext *C,
struct OutlinerLibOverrideData {
bool do_hierarchy;
+
+ /** When creating new overrides, make them all user-editable. */
+ bool do_fully_editable;
+
/**
* For resync operation, force keeping newly created override IDs (or original linked IDs)
* instead of re-applying relevant existing ID pointer property override operations. Helps
@@ -949,7 +961,8 @@ static void id_override_library_create_fn(bContext *C,
id_root_reference,
id_hierarchy_root_reference,
id_instance_hint,
- &id_root_override);
+ &id_root_override,
+ data->do_fully_editable);
BLI_assert(id_root_override != nullptr);
BLI_assert(!ID_IS_LINKED(id_root_override));
@@ -1726,53 +1739,60 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
event = RNA_enum_get(op->ptr, "type");
- if (event == OL_OP_SELECT) {
- Scene *sce = scene; /* To be able to delete, scenes are set... */
- outliner_do_object_operation(
- C, op->reports, scene, space_outliner, &space_outliner->tree, object_select_fn);
- if (scene != sce) {
- WM_window_set_active_scene(bmain, C, win, sce);
- }
+ switch (event) {
+ case OL_OP_SELECT: {
+ Scene *sce = scene; /* To be able to delete, scenes are set... */
+ outliner_do_object_operation(
+ C, op->reports, scene, space_outliner, &space_outliner->tree, object_select_fn);
+ /* FIXME: This is most certainly broken, maybe check should rather be
+ * `if (CTX_data_scene(C) != scene)` ? */
+ if (scene != sce) {
+ WM_window_set_active_scene(bmain, C, win, sce);
+ }
- str = "Select Objects";
- selection_changed = true;
- }
- else if (event == OL_OP_SELECT_HIERARCHY) {
- Scene *sce = scene; /* To be able to delete, scenes are set... */
- outliner_do_object_operation_ex(C,
- op->reports,
- scene,
- space_outliner,
- &space_outliner->tree,
- object_select_hierarchy_fn,
- nullptr,
- false);
- if (scene != sce) {
- WM_window_set_active_scene(bmain, C, win, sce);
- }
- str = "Select Object Hierarchy";
- selection_changed = true;
- }
- else if (event == OL_OP_DESELECT) {
- outliner_do_object_operation(
- C, op->reports, scene, space_outliner, &space_outliner->tree, object_deselect_fn);
- str = "Deselect Objects";
- selection_changed = true;
- }
- else if (event == OL_OP_REMAP) {
- outliner_do_libdata_operation(
- C, op->reports, scene, space_outliner, &space_outliner->tree, id_remap_fn, nullptr);
- /* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth
- * trick does not work here). */
- }
- else if (event == OL_OP_RENAME) {
- outliner_do_object_operation(
- C, op->reports, scene, space_outliner, &space_outliner->tree, item_rename_fn);
- str = "Rename Object";
- }
- else {
- BLI_assert(0);
- return OPERATOR_CANCELLED;
+ str = "Select Objects";
+ selection_changed = true;
+ break;
+ }
+ case OL_OP_SELECT_HIERARCHY: {
+ Scene *sce = scene; /* To be able to delete, scenes are set... */
+ outliner_do_object_operation_ex(C,
+ op->reports,
+ scene,
+ space_outliner,
+ &space_outliner->tree,
+ object_select_hierarchy_fn,
+ nullptr,
+ false);
+ /* FIXME: This is most certainly broken, maybe check should rather be
+ * `if (CTX_data_scene(C) != scene)` ? */
+ if (scene != sce) {
+ WM_window_set_active_scene(bmain, C, win, sce);
+ }
+ str = "Select Object Hierarchy";
+ selection_changed = true;
+ break;
+ }
+ case OL_OP_DESELECT:
+ outliner_do_object_operation(
+ C, op->reports, scene, space_outliner, &space_outliner->tree, object_deselect_fn);
+ str = "Deselect Objects";
+ selection_changed = true;
+ break;
+ case OL_OP_REMAP:
+ outliner_do_libdata_operation(
+ C, op->reports, scene, space_outliner, &space_outliner->tree, id_remap_fn, nullptr);
+ /* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth
+ * trick does not work here). */
+ break;
+ case OL_OP_RENAME:
+ outliner_do_object_operation(
+ C, op->reports, scene, space_outliner, &space_outliner->tree, item_rename_fn);
+ str = "Rename Object";
+ break;
+ default:
+ BLI_assert_unreachable();
+ return OPERATOR_CANCELLED;
}
if (selection_changed) {
@@ -1964,6 +1984,7 @@ enum eOutlinerIdOpTypes {
OUTLINER_IDOP_LOCAL,
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE,
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY,
+ OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY_FULLY_EDITABLE,
OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY,
@@ -2009,6 +2030,12 @@ static const EnumPropertyItem prop_id_op_types[] = {
"Make Library Override Hierarchy",
"Make a local override of this linked data-block, and its hierarchy of dependencies - only "
"applies to active Outliner item"},
+ {OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY_FULLY_EDITABLE,
+ "OVERRIDE_LIBRARY_CREATE_HIERARCHY_FULLY_EDITABLE",
+ 0,
+ "Make Library Override Hierarchy Fully Editable",
+ "Make a local override of this linked data-block, and its hierarchy of dependencies, making "
+ "them all fully user-editable - only applies to active Outliner item"},
{OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE,
"OVERRIDE_LIBRARY_MAKE_EDITABLE",
0,
@@ -2088,6 +2115,7 @@ static bool outliner_id_operation_item_poll(bContext *C,
}
return false;
case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY:
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY_FULLY_EDITABLE:
if (ID_IS_OVERRIDABLE_LIBRARY(tselem->id) || (ID_IS_LINKED(tselem->id))) {
return true;
}
@@ -2285,6 +2313,29 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
ED_undo_push(C, "Overridden Data Hierarchy");
break;
}
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY_FULLY_EDITABLE: {
+ OutlinerLibOverrideData override_data{};
+ override_data.do_hierarchy = true;
+ override_data.do_fully_editable = true;
+ outliner_do_libdata_operation(C,
+ op->reports,
+ scene,
+ space_outliner,
+ &space_outliner->tree,
+ id_override_library_create_hierarchy_pre_process_fn,
+ &override_data);
+ outliner_do_libdata_operation(C,
+ op->reports,
+ scene,
+ space_outliner,
+ &space_outliner->tree,
+ id_override_library_create_fn,
+ &override_data);
+ id_override_library_create_hierarchy_post_process(C, &override_data);
+
+ ED_undo_push(C, "Overridden Data Hierarchy Fully Editable");
+ break;
+ }
case OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE: {
outliner_do_libdata_operation(C,
op->reports,
@@ -2527,14 +2578,12 @@ void OUTLINER_OT_id_operation(wmOperatorType *ot)
enum eOutlinerLibOpTypes {
OL_LIB_INVALID = 0,
- OL_LIB_RENAME,
OL_LIB_DELETE,
OL_LIB_RELOCATE,
OL_LIB_RELOAD,
};
static const EnumPropertyItem outliner_lib_op_type_items[] = {
- {OL_LIB_RENAME, "RENAME", 0, "Rename", ""},
{OL_LIB_DELETE,
"DELETE",
ICON_X,
@@ -2566,14 +2615,6 @@ static int outliner_lib_operation_exec(bContext *C, wmOperator *op)
eOutlinerLibOpTypes event = (eOutlinerLibOpTypes)RNA_enum_get(op->ptr, "type");
switch (event) {
- case OL_LIB_RENAME: {
- outliner_do_libdata_operation(
- C, op->reports, scene, space_outliner, &space_outliner->tree, item_rename_fn, nullptr);
-
- WM_event_add_notifier(C, NC_ID | NA_EDITED, nullptr);
- ED_undo_push(C, "Rename Library");
- break;
- }
case OL_LIB_DELETE: {
outliner_do_libdata_operation(
C, op->reports, scene, space_outliner, &space_outliner->tree, id_delete_fn, nullptr);
diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt
index b5355efec7a..44f919ca361 100644
--- a/source/blender/editors/space_sequencer/CMakeLists.txt
+++ b/source/blender/editors/space_sequencer/CMakeLists.txt
@@ -25,10 +25,10 @@ set(INC
set(SRC
sequencer_add.c
sequencer_buttons.c
- sequencer_drag_drop.c
- sequencer_draw.c
sequencer_channels_draw.c
sequencer_channels_edit.c
+ sequencer_drag_drop.c
+ sequencer_draw.c
sequencer_edit.c
sequencer_modifier.c
sequencer_ops.c
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 469169cf4cc..10c6e828e96 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -31,6 +31,7 @@
#include "BKE_mask.h"
#include "BKE_movieclip.h"
#include "BKE_report.h"
+#include "BKE_scene.h"
#include "BKE_sound.h"
#include "IMB_imbuf.h"
@@ -54,6 +55,7 @@
#include "SEQ_transform.h"
#include "SEQ_utils.h"
+#include "ED_scene.h"
/* For menu, popup, icons, etc. */
#include "ED_screen.h"
#include "ED_sequencer.h"
@@ -469,6 +471,125 @@ void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot)
ot->prop = prop;
}
+static EnumPropertyItem strip_new_scene_items[] = {
+ {SCE_COPY_NEW, "NEW", 0, "New", "Add new Strip with a new empty Scene with default settings"},
+ {SCE_COPY_EMPTY,
+ "EMPTY",
+ 0,
+ "Copy Settings",
+ "Add a new Strip, with an empty scene, and copy settings from the current scene"},
+ {SCE_COPY_LINK_COLLECTION,
+ "LINK_COPY",
+ 0,
+ "Linked Copy",
+ "Add a Strip and link in the collections from the current scene (shallow copy)"},
+ {SCE_COPY_FULL,
+ "FULL_COPY",
+ 0,
+ "Full Copy",
+ "Add a Strip and make a full copy of the current scene"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static int sequencer_add_scene_strip_new_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ const Editing *ed = SEQ_editing_ensure(scene);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ ED_sequencer_deselect_all(scene);
+ }
+
+ SeqLoadData load_data;
+ load_data_init_from_operator(&load_data, C, op);
+
+ int type = RNA_enum_get(op->ptr, "type");
+ Scene *scene_new = ED_scene_sequencer_add(bmain, C, type, false);
+ if (scene_new == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ load_data.scene = scene_new;
+
+ Sequence *seq = SEQ_add_scene_strip(scene, ed->seqbasep, &load_data);
+ seq_load_apply_generic_options(C, op, seq);
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+static int sequencer_add_scene_strip_new_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
+{
+ sequencer_disable_one_time_properties(C, op);
+ sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_SCENE);
+ return sequencer_add_scene_strip_new_exec(C, op);
+}
+
+static const EnumPropertyItem *strip_new_sequencer_enum_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+ uint item_index;
+
+ item_index = RNA_enum_from_value(strip_new_scene_items, SCE_COPY_NEW);
+ RNA_enum_item_add(&item, &totitem, &strip_new_scene_items[item_index]);
+
+ bool has_scene_or_no_context = false;
+ if (C == NULL) {
+ /* For documentation generation. */
+ has_scene_or_no_context = true;
+ }
+ else {
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq = SEQ_select_active_get(scene);
+ if ((seq && (seq->type == SEQ_TYPE_SCENE) && (seq->scene != NULL))) {
+ has_scene_or_no_context = true;
+ }
+ }
+
+ if (has_scene_or_no_context) {
+ int values[] = {SCE_COPY_EMPTY, SCE_COPY_LINK_COLLECTION, SCE_COPY_FULL};
+ for (int i = 0; i < ARRAY_SIZE(values); i++) {
+ item_index = RNA_enum_from_value(strip_new_scene_items, values[i]);
+ RNA_enum_item_add(&item, &totitem, &strip_new_scene_items[item_index]);
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+ return item;
+}
+
+void SEQUENCER_OT_scene_strip_add_new(struct wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Add Strip with a new Scene";
+ ot->idname = "SEQUENCER_OT_scene_strip_add_new";
+ ot->description = "Create a new Strip and add a assign a new Scene as source";
+
+ /* Api callbacks. */
+ ot->invoke = sequencer_add_scene_strip_new_invoke;
+ ot->exec = sequencer_add_scene_strip_new_exec;
+ ot->poll = ED_operator_sequencer_active_editable;
+
+ /* Flags. */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
+
+ ot->prop = RNA_def_enum(ot->srna, "type", strip_new_scene_items, SCE_COPY_NEW, "Type", "");
+ RNA_def_enum_funcs(ot->prop, strip_new_sequencer_enum_itemf);
+ RNA_def_property_flag(ot->prop, PROP_ENUM_NO_TRANSLATE);
+}
+
static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -672,8 +793,8 @@ static void sequencer_add_movie_clamp_sound_strip_length(Scene *scene,
return;
}
- SEQ_transform_set_right_handle_frame(seq_sound, SEQ_transform_get_right_handle_frame(seq_movie));
- SEQ_transform_set_left_handle_frame(seq_sound, SEQ_transform_get_left_handle_frame(seq_movie));
+ SEQ_time_right_handle_frame_set(seq_sound, SEQ_time_right_handle_frame_get(seq_movie));
+ SEQ_time_left_handle_frame_set(seq_sound, SEQ_time_left_handle_frame_get(seq_movie));
SEQ_time_update_sequence(scene, seqbase, seq_sound);
}
@@ -1179,7 +1300,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
/* Adjust length. */
if (load_data.image.len == 1) {
- SEQ_transform_set_right_handle_frame(seq, load_data.image.end_frame);
+ SEQ_time_right_handle_frame_set(seq, load_data.image.end_frame);
SEQ_time_update_sequence(scene, SEQ_active_seqbase_get(ed), seq);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_channels_draw.c b/source/blender/editors/space_sequencer/sequencer_channels_draw.c
index a777132e9fc..c11388e8555 100644
--- a/source/blender/editors/space_sequencer/sequencer_channels_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_channels_draw.c
@@ -200,7 +200,7 @@ static float text_size_get(const SeqChannelDrawContext *context)
return UI_fontstyle_height_max(&style->widget) * 1.5f * context->scale;
}
-/* Todo: decide what gets priority - label or buttons */
+/* TODO: decide what gets priority - label or buttons. */
static rctf label_rect_init(const SeqChannelDrawContext *context,
const int channel_index,
const float used_width)
@@ -286,7 +286,7 @@ static void draw_channel_labels(const SeqChannelDrawContext *context,
}
}
-/* Todo: different text/buttons alignment */
+/* TODO: different text/buttons alignment. */
static void draw_channel_header(const SeqChannelDrawContext *context,
uiBlock *block,
const int channel_index)
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index a561de1ef64..02e77732e02 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -1098,26 +1098,23 @@ static void draw_seq_background(Scene *scene,
/* Draw the main strip body. */
if (is_single_image) {
- immRectf(pos,
- SEQ_transform_get_left_handle_frame(seq),
- y1,
- SEQ_transform_get_right_handle_frame(seq),
- y2);
+ immRectf(
+ pos, SEQ_time_left_handle_frame_get(seq), y1, SEQ_time_right_handle_frame_get(seq), y2);
}
else {
immRectf(pos, x1, y1, x2, y2);
}
/* Draw background for hold still regions. */
- if (!is_single_image && (seq->startstill || seq->endstill)) {
+ if (!is_single_image && SEQ_time_has_still_frames(seq)) {
UI_GetColorPtrShade3ubv(col, col, -35);
immUniformColor4ubv(col);
- if (seq->startstill) {
+ if (SEQ_time_has_left_still_frames(seq)) {
const float content_start = min_ff(seq->enddisp, seq->start);
immRectf(pos, seq->startdisp, y1, content_start, y2);
}
- if (seq->endstill) {
+ if (SEQ_time_has_right_still_frames(seq)) {
const float content_end = max_ff(seq->startdisp, seq->start + seq->len);
immRectf(pos, content_end, y1, seq->enddisp, y2);
}
@@ -1336,9 +1333,9 @@ static void draw_seq_strip(const bContext *C,
SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG);
/* Draw strip body. */
- x1 = (seq->startstill) ? seq->start : seq->startdisp;
+ x1 = SEQ_time_has_left_still_frames(seq) ? seq->start : seq->startdisp;
y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
- x2 = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp;
+ x2 = SEQ_time_has_right_still_frames(seq) ? (seq->start + seq->len) : seq->enddisp;
y2 = seq->machine + SEQ_STRIP_OFSTOP;
/* Limit body to strip bounds. Meta strip can end up with content outside of strip range. */
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 0305ad279a0..08f98dfb161 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -57,6 +57,7 @@
#include "ED_keyframing.h"
#include "ED_numinput.h"
#include "ED_outliner.h"
+#include "ED_scene.h"
#include "ED_screen.h"
#include "ED_sequencer.h"
@@ -76,7 +77,6 @@
typedef struct TransSeq {
int start, machine;
- int startstill, endstill;
int startdisp, enddisp;
int startofs, endofs;
int anim_startofs, anim_endofs;
@@ -357,15 +357,14 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
if (seq->flag & SELECT && !SEQ_transform_is_locked(channels, seq) &&
SEQ_transform_sequence_can_be_translated(seq)) {
if ((seq->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) {
- SEQ_transform_translate_sequence(
- scene, seq, (snap_frame - seq->startofs + seq->startstill) - seq->start);
+ SEQ_transform_translate_sequence(scene, seq, (snap_frame - seq->startofs) - seq->start);
}
else {
if (seq->flag & SEQ_LEFTSEL) {
- SEQ_transform_set_left_handle_frame(seq, snap_frame);
+ SEQ_time_left_handle_frame_set(seq, snap_frame);
}
else { /* SEQ_RIGHTSEL */
- SEQ_transform_set_right_handle_frame(seq, snap_frame);
+ SEQ_time_right_handle_frame_set(seq, snap_frame);
}
SEQ_transform_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
SEQ_transform_fix_single_image_seq_offsets(seq);
@@ -478,8 +477,6 @@ static void transseq_backup(TransSeq *ts, Sequence *seq)
{
ts->start = seq->start;
ts->machine = seq->machine;
- ts->startstill = seq->startstill;
- ts->endstill = seq->endstill;
ts->startdisp = seq->startdisp;
ts->enddisp = seq->enddisp;
ts->startofs = seq->startofs;
@@ -493,8 +490,6 @@ static void transseq_restore(TransSeq *ts, Sequence *seq)
{
seq->start = ts->start;
seq->machine = ts->machine;
- seq->startstill = ts->startstill;
- seq->endstill = ts->endstill;
seq->startdisp = ts->startdisp;
seq->enddisp = ts->enddisp;
seq->startofs = ts->startofs;
@@ -595,11 +590,8 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
return OPERATOR_RUNNING_MODAL;
}
-static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
+static void sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
{
- /* Only data types supported for now. */
- bool changed = false;
-
/* Iterate in reverse so meta-strips are iterated after their children. */
for (int i = data->num_seq - 1; i >= 0; i--) {
Sequence *seq = data->seq_array[i];
@@ -613,33 +605,13 @@ static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
endframe = seq->start + seq->len;
/* Compute the sequence offsets. */
- if (endframe > seq->enddisp) {
- seq->endstill = 0;
- seq->endofs = endframe - seq->enddisp;
- changed = true;
- }
- else {
- seq->endstill = seq->enddisp - endframe;
- seq->endofs = 0;
- changed = true;
- }
-
- if (seq->start > seq->startdisp) {
- seq->startstill = seq->start - seq->startdisp;
- seq->startofs = 0;
- changed = true;
- }
- else {
- seq->startstill = 0;
- seq->startofs = seq->startdisp - seq->start;
- changed = true;
- }
+ seq->endofs = endframe - seq->enddisp;
+ seq->startofs = seq->startdisp - seq->start;
}
else {
/* No transform data (likely effect strip). Only move start and end. */
seq->startdisp = data->ts[i].startdisp + offset;
seq->enddisp = data->ts[i].enddisp + offset;
- changed = true;
}
/* Effects are only added if we they are in a meta-strip.
@@ -651,13 +623,11 @@ static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
SEQ_time_update_sequence(scene, seqbase, seq);
}
}
- if (changed) {
- for (int i = data->num_seq - 1; i >= 0; i--) {
- Sequence *seq = data->seq_array[i];
- SEQ_relations_invalidate_cache_preprocessed(scene, seq);
- }
+
+ for (int i = data->num_seq - 1; i >= 0; i--) {
+ Sequence *seq = data->seq_array[i];
+ SEQ_relations_invalidate_cache_preprocessed(scene, seq);
}
- return changed;
}
/* Make sure, that each strip contains at least 1 frame of content. */
@@ -687,7 +657,6 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene);
int offset = RNA_int_get(op->ptr, "offset");
- bool success = false;
/* Recursively count the trimmed elements. */
int num_seq = slip_count_sequences_recursive(ed->seqbasep, true);
@@ -709,19 +678,16 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
}
sequencer_slip_apply_limits(data, &offset);
- success = sequencer_slip_recursively(scene, data, offset);
+ sequencer_slip_recursively(scene, data, offset);
MEM_freeN(data->seq_array);
MEM_freeN(data->trim);
MEM_freeN(data->ts);
MEM_freeN(data);
- if (success) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
- return OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
+ return OPERATOR_FINISHED;
}
static void sequencer_slip_update_header(Scene *scene, ScrArea *area, SlipData *data, int offset)
@@ -762,9 +728,8 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
RNA_int_set(op->ptr, "offset", offset);
- if (sequencer_slip_recursively(scene, data, offset)) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- }
+ sequencer_slip_recursively(scene, data, offset);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_RUNNING_MODAL;
}
@@ -795,9 +760,8 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
RNA_int_set(op->ptr, "offset", offset);
- if (sequencer_slip_recursively(scene, data, offset)) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- }
+ sequencer_slip_recursively(scene, data, offset);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
}
break;
}
@@ -875,9 +839,8 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
RNA_int_set(op->ptr, "offset", offset);
- if (sequencer_slip_recursively(scene, data, offset)) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- }
+ sequencer_slip_recursively(scene, data, offset);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
}
return OPERATOR_RUNNING_MODAL;
@@ -1719,11 +1682,26 @@ void SEQUENCER_OT_duplicate(wmOperatorType *ot)
/** \name Erase Strips Operator
* \{ */
-static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
+static void sequencer_delete_strip_data(bContext *C, Sequence *seq)
+{
+ if (seq->type != SEQ_TYPE_SCENE) {
+ return;
+ }
+
+ Main *bmain = CTX_data_main(C);
+ if (seq->scene) {
+ if (ED_scene_delete(C, bmain, seq->scene)) {
+ WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, seq->scene);
+ }
+ }
+}
+
+static int sequencer_delete_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ListBase *seqbasep = SEQ_active_seqbase_get(SEQ_editing_get(scene));
+ const bool delete_data = RNA_boolean_get(op->ptr, "delete_data");
if (sequencer_view_has_preview_poll(C) && !sequencer_view_preview_only_poll(C)) {
return OPERATOR_CANCELLED;
@@ -1736,6 +1714,9 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
SEQ_ITERATOR_FOREACH (seq, selected_strips) {
SEQ_edit_flag_for_removal(scene, seqbasep, seq);
+ if (delete_data) {
+ sequencer_delete_strip_data(C, seq);
+ }
}
SEQ_edit_remove_flagged_sequences(scene, seqbasep);
@@ -1778,6 +1759,14 @@ void SEQUENCER_OT_delete(wmOperatorType *ot)
/* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties. */
+ ot->prop = RNA_def_boolean(ot->srna,
+ "delete_data",
+ false,
+ "Delete Data",
+ "After removing the Strip, delete the associated data also");
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
}
/** \} */
@@ -1795,7 +1784,7 @@ static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op))
/* For effects, try to find a replacement input. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
- seq->startofs = seq->endofs = seq->startstill = seq->endstill = 0;
+ seq->startofs = seq->endofs = 0;
}
}
@@ -1869,8 +1858,8 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
/* TODO: remove f-curve and assign to split image strips.
* The old animation system would remove the user of `seq->ipo`. */
- start_ofs = timeline_frame = SEQ_transform_get_left_handle_frame(seq);
- frame_end = SEQ_transform_get_right_handle_frame(seq);
+ start_ofs = timeline_frame = SEQ_time_left_handle_frame_get(seq);
+ frame_end = SEQ_time_right_handle_frame_get(seq);
while (timeline_frame < frame_end) {
/* New seq. */
@@ -1881,7 +1870,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
seq_new->start = start_ofs;
seq_new->type = SEQ_TYPE_IMAGE;
seq_new->len = 1;
- seq_new->endstill = step - 1;
+ seq_new->endofs = 1 - step;
/* New strip. */
strip_new = seq_new->strip;
@@ -2596,7 +2585,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op)
}
/* Paste animation.
- * Note: Only fcurves are copied. Drivers and NLA action strips are not copied.
+ * NOTE: Only fcurves are copied. Drivers and NLA action strips are not copied.
* First backup original curves from scene and move curves from clipboard into scene. This way,
* when pasted strips are renamed, pasted fcurves are renamed with them. Finally restore original
* curves from backup.
@@ -3040,6 +3029,81 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Change Strip Scene Operator
+ * \{ */
+
+static bool sequencer_strip_change_scene_poll(bContext *C)
+{
+ Editing *ed = SEQ_editing_get(CTX_data_scene(C));
+ if (ed == NULL) {
+ return false;
+ }
+ Sequence *seq = ed->act_seq;
+ return ((seq != NULL) && (seq->type == SEQ_TYPE_SCENE));
+}
+static int sequencer_change_scene_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Scene *scene_seq = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene"));
+
+ if (scene_seq == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Scene not found");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Assign new scene. */
+ Sequence *seq = SEQ_select_active_get(scene);
+ if (seq) {
+ seq->scene = scene_seq;
+ /* Do a refresh of the sequencer data. */
+ SEQ_relations_invalidate_cache_raw(scene, seq);
+ DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO | ID_RECALC_SEQUENCER_STRIPS);
+ DEG_relations_tag_update(bmain);
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+static int sequencer_change_scene_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (!RNA_struct_property_is_set(op->ptr, "scene")) {
+ return WM_enum_search_invoke(C, op, event);
+ }
+
+ return sequencer_change_scene_exec(C, op);
+}
+
+void SEQUENCER_OT_change_scene(struct wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* Identifiers. */
+ ot->name = "Change Scene";
+ ot->idname = "SEQUENCER_OT_change_scene";
+ ot->description = "Change Scene assigned to Strip";
+
+ /* Api callbacks. */
+ ot->exec = sequencer_change_scene_exec;
+ ot->invoke = sequencer_change_scene_invoke;
+ ot->poll = sequencer_strip_change_scene_poll;
+
+ /* Flags. */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties. */
+ prop = RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
+ RNA_def_enum_funcs(prop, RNA_scene_without_active_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Export Subtitles Operator
* \{ */
@@ -3049,8 +3113,8 @@ static int seq_cmp_time_startdisp_channel(const void *a, const void *b)
Sequence *seq_a = (Sequence *)a;
Sequence *seq_b = (Sequence *)b;
- int seq_a_start = SEQ_transform_get_left_handle_frame(seq_a);
- int seq_b_start = SEQ_transform_get_left_handle_frame(seq_b);
+ int seq_a_start = SEQ_time_left_handle_frame_get(seq_a);
+ int seq_b_start = SEQ_time_left_handle_frame_get(seq_b);
/* If strips have the same start frame favor the one with a higher channel. */
if (seq_a_start == seq_b_start) {
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 67df065ef35..3307c3fde2f 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -197,6 +197,7 @@ void SEQUENCER_OT_rendersize(struct wmOperatorType *ot);
void SEQUENCER_OT_change_effect_input(struct wmOperatorType *ot);
void SEQUENCER_OT_change_effect_type(struct wmOperatorType *ot);
void SEQUENCER_OT_change_path(struct wmOperatorType *ot);
+void SEQUENCER_OT_change_scene(struct wmOperatorType *ot);
void SEQUENCER_OT_copy(struct wmOperatorType *ot);
void SEQUENCER_OT_paste(struct wmOperatorType *ot);
@@ -231,6 +232,7 @@ void SEQUENCER_OT_select_grouped(struct wmOperatorType *ot);
/* sequencer_add.c */
void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot);
+void SEQUENCER_OT_scene_strip_add_new(struct wmOperatorType *ot);
void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot);
void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot);
void SEQUENCER_OT_mask_strip_add(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index 1aa2991f07a..f7a9bcf41e6 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -58,6 +58,7 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_change_effect_input);
WM_operatortype_append(SEQUENCER_OT_change_effect_type);
WM_operatortype_append(SEQUENCER_OT_change_path);
+ WM_operatortype_append(SEQUENCER_OT_change_scene);
WM_operatortype_append(SEQUENCER_OT_set_range_to_strips);
WM_operatortype_append(SEQUENCER_OT_strip_transform_clear);
@@ -81,6 +82,7 @@ void sequencer_operatortypes(void)
/* sequencer_add.c */
WM_operatortype_append(SEQUENCER_OT_scene_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_scene_strip_add_new);
WM_operatortype_append(SEQUENCER_OT_movieclip_strip_add);
WM_operatortype_append(SEQUENCER_OT_mask_strip_add);
WM_operatortype_append(SEQUENCER_OT_movie_strip_add);
diff --git a/source/blender/editors/space_sequencer/sequencer_thumbnails.c b/source/blender/editors/space_sequencer/sequencer_thumbnails.c
index 43c5e004040..eab17d876f3 100644
--- a/source/blender/editors/space_sequencer/sequencer_thumbnails.c
+++ b/source/blender/editors/space_sequencer/sequencer_thumbnails.c
@@ -23,6 +23,7 @@
#include "SEQ_relations.h"
#include "SEQ_render.h"
#include "SEQ_sequencer.h"
+#include "SEQ_time.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -443,7 +444,8 @@ void draw_seq_strip_thumbnail(View2D *v2d,
float thumb_y_end = y1 + thumb_height;
float cut_off = 0;
- float upper_thumb_bound = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp;
+ float upper_thumb_bound = SEQ_time_has_right_still_frames(seq) ? (seq->start + seq->len) :
+ seq->enddisp;
if (seq->type == SEQ_TYPE_IMAGE) {
upper_thumb_bound = seq->enddisp;
}
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
index 4afa70d9ef6..7f696efabf7 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
@@ -64,7 +64,7 @@ std::unique_ptr<ColumnValues> ExtraColumns::get_column_values(
void GeometryDataSource::foreach_default_column_ids(
FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
{
- if (component_->attribute_domain_size(domain_) == 0) {
+ if (component_->attribute_domain_num(domain_) == 0) {
return;
}
@@ -110,8 +110,8 @@ void GeometryDataSource::foreach_default_column_ids(
std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
const SpreadsheetColumnID &column_id) const
{
- const int domain_size = component_->attribute_domain_size(domain_);
- if (domain_size == 0) {
+ const int domain_num = component_->attribute_domain_num(domain_);
+ if (domain_num == 0) {
return {};
}
@@ -129,7 +129,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
Span<InstanceReference> references = instances.references();
return std::make_unique<ColumnValues>(
column_id.name,
- VArray<InstanceReference>::ForFunc(domain_size,
+ VArray<InstanceReference>::ForFunc(domain_num,
[reference_handles, references](int64_t index) {
return references[reference_handles[index]];
}));
@@ -137,13 +137,13 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
Span<float4x4> transforms = instances.instance_transforms();
if (STREQ(column_id.name, "Rotation")) {
return std::make_unique<ColumnValues>(
- column_id.name, VArray<float3>::ForFunc(domain_size, [transforms](int64_t index) {
+ column_id.name, VArray<float3>::ForFunc(domain_num, [transforms](int64_t index) {
return transforms[index].to_euler();
}));
}
if (STREQ(column_id.name, "Scale")) {
return std::make_unique<ColumnValues>(
- column_id.name, VArray<float3>::ForFunc(domain_size, [transforms](int64_t index) {
+ column_id.name, VArray<float3>::ForFunc(domain_num, [transforms](int64_t index) {
return transforms[index].scale();
}));
}
@@ -210,7 +210,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
int GeometryDataSource::tot_rows() const
{
- return component_->attribute_domain_size(domain_);
+ return component_->attribute_domain_num(domain_);
}
/**
@@ -256,7 +256,7 @@ IndexMask GeometryDataSource::apply_selection_filter(Vector<int64_t> &indices) c
BMesh *bm = mesh_orig->edit_mesh->bm;
BM_mesh_elem_table_ensure(bm, BM_VERT);
- int *orig_indices = (int *)CustomData_get_layer(&mesh_eval->vdata, CD_ORIGINDEX);
+ const int *orig_indices = (int *)CustomData_get_layer(&mesh_eval->vdata, CD_ORIGINDEX);
if (orig_indices != nullptr) {
/* Use CD_ORIGINDEX layer if it exists. */
VArray<bool> selection = mesh_component->attribute_try_adapt_domain<bool>(
@@ -524,17 +524,17 @@ static void add_fields_as_extra_columns(SpaceSpreadsheet *sspreadsheet,
std::make_unique<GeometryComponentCacheKey>(component));
const AttributeDomain domain = (AttributeDomain)sspreadsheet->attribute_domain;
- const int domain_size = component.attribute_domain_size(domain);
+ const int domain_num = component.attribute_domain_num(domain);
for (const auto item : fields_to_show.items()) {
StringRef name = item.key;
const GField &field = item.value;
/* Use the cached evaluated array if it exists, otherwise evaluate the field now. */
GArray<> &evaluated_array = cache.arrays.lookup_or_add_cb({domain, field}, [&]() {
- GArray<> evaluated_array(field.cpp_type(), domain_size);
+ GArray<> evaluated_array(field.cpp_type(), domain_num);
bke::GeometryComponentFieldContext field_context{component, domain};
- fn::FieldEvaluator field_evaluator{field_context, domain_size};
+ fn::FieldEvaluator field_evaluator{field_context, domain_num};
field_evaluator.add_with_destination(field, evaluated_array);
field_evaluator.evaluate();
return evaluated_array;
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc
index c4b5228758c..724d0783707 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc
@@ -144,7 +144,7 @@ void GeometryDataSetTreeViewItem::build_row(uiLayout &row)
/* Using the tree row button instead of a separate right aligned button gives padding
* to the right side of the number, which it didn't have with the button. */
char element_count[7];
- BLI_str_format_attribute_domain_size(element_count, *count);
+ BLI_str_format_decimal_unit(element_count, *count);
UI_but_hint_drawstr_set((uiBut *)this->tree_row_button(), element_count);
}
}
@@ -194,7 +194,7 @@ std::optional<int> GeometryDataSetTreeViewItem::count() const
}
if (const GeometryComponent *component = geometry.get_component_for_read(component_type_)) {
- return component->attribute_domain_size(*domain_);
+ return component->attribute_domain_num(*domain_);
}
return 0;
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 36eafedbc80..c93ffccd477 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -1603,7 +1603,7 @@ void draw_text_main(SpaceText *st, ARegion *region)
return;
}
- /* dpi controlled line height and font size */
+ /* DPI controlled line height and font size. */
st->runtime.lheight_px = (U.widget_unit * st->lheight) / 20;
/* don't draw lines below this */
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 7776119a594..8add6886584 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -6,12 +6,14 @@
*/
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BLI_math.h"
+#include "BLI_math_vector.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_object.h"
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 85d239507ce..1230515a180 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -30,7 +30,7 @@
void ED_view3d_project_float_v2_m4(const ARegion *region,
const float co[3],
float r_co[2],
- float mat[4][4])
+ const float mat[4][4])
{
float vec4[4];
@@ -52,7 +52,7 @@ void ED_view3d_project_float_v2_m4(const ARegion *region,
void ED_view3d_project_float_v3_m4(const ARegion *region,
const float co[3],
float r_co[3],
- float mat[4][4])
+ const float mat[4][4])
{
float vec4[4];
@@ -312,7 +312,7 @@ float ED_view3d_calc_depth_for_comparison(const RegionView3D *rv3d, const float
return -dot_v3v3(rv3d->viewinv[2], co);
}
-static void view3d_win_to_ray_segment(struct Depsgraph *depsgraph,
+static void view3d_win_to_ray_segment(const struct Depsgraph *depsgraph,
const ARegion *region,
const View3D *v3d,
const float mval[2],
@@ -642,9 +642,9 @@ void ED_view3d_win_to_vector(const ARegion *region, const float mval[2], float r
normalize_v3(r_out);
}
-bool ED_view3d_win_to_segment_clipped(struct Depsgraph *depsgraph,
+bool ED_view3d_win_to_segment_clipped(const struct Depsgraph *depsgraph,
const ARegion *region,
- View3D *v3d,
+ const View3D *v3d,
const float mval[2],
float r_ray_start[3],
float r_ray_end[3],
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index d99063a9b26..efe89621e7b 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -126,6 +126,7 @@ void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc, Depsgraph *depsgra
void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
{
vc->obact = obact;
+ /* See public doc-string for rationale on checking the existing values first. */
if (vc->obedit) {
BLI_assert(BKE_object_is_in_editmode(obact));
vc->obedit = obact;
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 51f50633468..306394ce53d 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -106,7 +106,7 @@ void ED_view3d_dist_range_get(const View3D *v3d, float r_dist_range[2])
r_dist_range[1] = v3d->clip_end * 10.0f;
}
-bool ED_view3d_clip_range_get(Depsgraph *depsgraph,
+bool ED_view3d_clip_range_get(const Depsgraph *depsgraph,
const View3D *v3d,
const RegionView3D *rv3d,
float *r_clipsta,
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 7ae041f2b2f..a7e2f616c9e 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1174,7 +1174,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
stopConstraint(t);
initSelectConstraint(t);
- /* In this case we might just want to remove the contraint,
+ /* In this case we might just want to remove the constraint,
* so set #TREDRAW_SOFT to only select the constraint on the next mouse move event.
* This way we can kind of "cancel" due to confirmation without constraint. */
t->redraw = TREDRAW_SOFT;
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index dbe67bd0d66..018468dcd03 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -479,6 +479,45 @@ TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTr
/** \name UV Coordinates
* \{ */
+/**
+ * Find the correction for the scaling factor when "Constrain to Bounds" is active.
+ * \param numerator: How far the UV boundary (unit square) is from the origin of the scale.
+ * \param denominator: How far the AABB is from the origin of the scale.
+ * \param scale: Scale parameter to update.
+ */
+static void constrain_scale_to_boundary(const float numerator,
+ const float denominator,
+ float *scale)
+{
+ if (denominator == 0.0f) {
+ /* The origin of the scale is on the edge of the boundary. */
+ if (numerator < 0.0f) {
+ /* Negative scale will wrap around and put us outside the boundary. */
+ *scale = 0.0f; /* Hold at the boundary instead. */
+ }
+ return; /* Nothing else we can do without more info. */
+ }
+
+ const float correction = numerator / denominator;
+ if (correction < 0.0f || !isfinite(correction)) {
+ /* TODO: Correction is negative or invalid, but we lack context to fix `*scale`. */
+ return;
+ }
+
+ if (denominator < 0.0f) {
+ /* Scale origin is outside boundary, only make scale bigger. */
+ if (*scale < correction) {
+ *scale = correction;
+ }
+ return;
+ }
+
+ /* Scale origin is inside boundary, the "regular" case, limit maximum scale. */
+ if (*scale > correction) {
+ *scale = correction;
+ }
+}
+
bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
{
bool clipx = true, clipy = true;
@@ -517,31 +556,29 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
}
if (resize) {
- if (min[0] < base_offset[0] && t->center_global[0] > base_offset[0] &&
- t->center_global[0] < base_offset[0] + (t->aspect[0] * 0.5f)) {
- vec[0] *= (t->center_global[0] - base_offset[0]) / (t->center_global[0] - min[0]);
- }
- else if (max[0] > (base_offset[0] + t->aspect[0]) &&
- t->center_global[0] < (base_offset[0] + t->aspect[0])) {
- vec[0] *= (t->center_global[0] - (base_offset[0] + t->aspect[0])) /
- (t->center_global[0] - max[0]);
- }
- else {
- clipx = 0;
- }
-
- if (min[1] < base_offset[1] && t->center_global[1] > base_offset[1] &&
- t->center_global[1] < base_offset[1] + (t->aspect[1] * 0.5f)) {
- vec[1] *= (t->center_global[1] - base_offset[1]) / (t->center_global[1] - min[1]);
- }
- else if (max[1] > (base_offset[1] + t->aspect[1]) &&
- t->center_global[1] < (base_offset[1] + t->aspect[1])) {
- vec[1] *= (t->center_global[1] - (base_offset[1] + t->aspect[1])) /
- (t->center_global[1] - max[1]);
- }
- else {
- clipy = 0;
- }
+ /* Assume no change is required. */
+ float scalex = 1.0f;
+ float scaley = 1.0f;
+
+ /* Update U against the left border. */
+ constrain_scale_to_boundary(
+ t->center_global[0] - base_offset[0], t->center_global[0] - min[0], &scalex);
+ /* Now the right border, negated, because `-1.0 / -1.0 = 1.0` */
+ constrain_scale_to_boundary(base_offset[0] + t->aspect[0] - t->center_global[0],
+ max[0] - t->center_global[0],
+ &scalex);
+
+ /* Do the same for the V co-ordinate, which is called `y`. */
+ constrain_scale_to_boundary(
+ t->center_global[1] - base_offset[1], t->center_global[1] - min[1], &scaley);
+ constrain_scale_to_boundary(base_offset[1] + t->aspect[1] - t->center_global[1],
+ max[1] - t->center_global[1],
+ &scaley);
+
+ clipx = (scalex != 1.0f);
+ clipy = (scaley != 1.0f);
+ vec[0] *= scalex;
+ vec[1] *= scaley;
}
else {
if (min[0] < base_offset[0]) {
diff --git a/source/blender/editors/transform/transform_convert_node.c b/source/blender/editors/transform/transform_convert_node.c
index d5d79bedbf4..8281052c314 100644
--- a/source/blender/editors/transform/transform_convert_node.c
+++ b/source/blender/editors/transform/transform_convert_node.c
@@ -46,7 +46,7 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node, const
}
/* use top-left corner as the transform origin for nodes */
- /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
+ /* Weirdo - but the node system is a mix of free 2d elements and DPI sensitive UI. */
#ifdef USE_NODE_CENTER
td2d->loc[0] = (locx * dpi_fac) + (BLI_rctf_size_x(&node->totr) * +0.5f);
td2d->loc[1] = (locy * dpi_fac) + (BLI_rctf_size_y(&node->totr) * -0.5f);
@@ -194,7 +194,7 @@ void flushTransNodes(TransInfo *t)
loc[1] += 0.5f * BLI_rctf_size_y(&node->totr);
#endif
- /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
+ /* Weirdo - but the node system is a mix of free 2d elements and DPI sensitive UI. */
loc[0] /= dpi_fac;
loc[1] /= dpi_fac;
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 5964af7ed4b..3735ff0727c 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -91,8 +91,8 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_count, int *r_flag)
/* *** Extend Transform *** */
int cfra = CFRA;
- int left = SEQ_transform_get_left_handle_frame(seq);
- int right = SEQ_transform_get_right_handle_frame(seq);
+ int left = SEQ_time_left_handle_frame_get(seq);
+ int right = SEQ_time_right_handle_frame_get(seq);
if (((seq->flag & SELECT) == 0 || SEQ_transform_is_locked(channels, seq))) {
*r_count = 0;
@@ -173,16 +173,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 = SEQ_transform_get_left_handle_frame(seq);
+ start_left = SEQ_time_left_handle_frame_get(seq);
td2d->loc[0] = start_left;
tdsq->start_offset = start_left - seq->start; /* use to apply the original location */
break;
case SEQ_LEFTSEL:
- start_left = SEQ_transform_get_left_handle_frame(seq);
+ start_left = SEQ_time_left_handle_frame_get(seq);
td2d->loc[0] = start_left;
break;
case SEQ_RIGHTSEL:
- td2d->loc[0] = SEQ_transform_get_right_handle_frame(seq);
+ td2d->loc[0] = SEQ_time_right_handle_frame_get(seq);
break;
}
@@ -489,11 +489,11 @@ static void seq_transform_handle_overwrite_trim(Scene *scene,
continue;
}
if (overlap == STRIP_OVERLAP_LEFT_SIDE) {
- SEQ_transform_set_left_handle_frame(seq, transformed->enddisp);
+ SEQ_time_left_handle_frame_set(seq, transformed->enddisp);
}
else {
BLI_assert(overlap == STRIP_OVERLAP_RIGHT_SIDE);
- SEQ_transform_set_right_handle_frame(seq, transformed->startdisp);
+ SEQ_time_right_handle_frame_set(seq, transformed->startdisp);
}
SEQ_time_update_sequence(scene, seqbasep, seq);
@@ -915,7 +915,7 @@ static void flushTransSeq(TransInfo *t)
}
case SEQ_LEFTSEL: { /* No vertical transform. */
int old_startdisp = seq->startdisp;
- SEQ_transform_set_left_handle_frame(seq, new_frame);
+ SEQ_time_left_handle_frame_set(seq, new_frame);
SEQ_transform_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
SEQ_transform_fix_single_image_seq_offsets(seq);
SEQ_time_update_sequence(t->scene, seqbasep, seq);
@@ -926,7 +926,7 @@ static void flushTransSeq(TransInfo *t)
}
case SEQ_RIGHTSEL: { /* No vertical transform. */
int old_enddisp = seq->enddisp;
- SEQ_transform_set_right_handle_frame(seq, new_frame);
+ SEQ_time_right_handle_frame_set(seq, new_frame);
SEQ_transform_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
SEQ_transform_fix_single_image_seq_offsets(seq);
SEQ_time_update_sequence(t->scene, seqbasep, seq);
diff --git a/source/blender/editors/transform/transform_convert_tracking.c b/source/blender/editors/transform/transform_convert_tracking.c
index bf9f929dd65..d447cd71a40 100644
--- a/source/blender/editors/transform/transform_convert_tracking.c
+++ b/source/blender/editors/transform/transform_convert_tracking.c
@@ -713,23 +713,23 @@ void recalcData_tracking(TransInfo *t)
if (t->mode == TFM_TRANSLATION) {
if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) {
- BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
+ BKE_tracking_marker_clamp_pattern_position(marker);
}
if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) {
- BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_POS);
+ BKE_tracking_marker_clamp_search_position(marker);
}
}
else if (t->mode == TFM_RESIZE) {
if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) {
- BKE_tracking_marker_clamp(marker, CLAMP_PAT_DIM);
+ BKE_tracking_marker_clamp_search_size(marker);
}
if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) {
- BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_DIM);
+ BKE_tracking_marker_clamp_search_size(marker);
}
}
else if (t->mode == TFM_ROTATION) {
if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) {
- BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
+ BKE_tracking_marker_clamp_pattern_position(marker);
}
}
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index afad4df2c88..769fd28c57b 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -15,6 +15,7 @@
#include "BLI_math.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "GPU_state.h"
#include "BKE_context.h"
@@ -25,6 +26,7 @@
#include "RNA_access.h"
+#include "WM_api.h"
#include "WM_types.h"
#include "ED_gizmo_library.h"
@@ -173,20 +175,20 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
return;
}
- UI_GetThemeColor3ubv(TH_TRANSFORM, col);
- col[3] = 128;
-
- UI_GetThemeColor3ubv(TH_SELECT, selectedCol);
- selectedCol[3] = 128;
-
- UI_GetThemeColor3ubv(TH_ACTIVE, activeCol);
- activeCol[3] = 192;
-
if (t->spacetype == SPACE_VIEW3D) {
bool draw_target = (t->tsnap.status & TARGET_INIT) &&
(t->tsnap.mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR);
if (draw_target || validSnap(t)) {
+ UI_GetThemeColor3ubv(TH_TRANSFORM, col);
+ col[3] = 128;
+
+ UI_GetThemeColor3ubv(TH_SELECT, selectedCol);
+ selectedCol[3] = 128;
+
+ UI_GetThemeColor3ubv(TH_ACTIVE, activeCol);
+ activeCol[3] = 192;
+
const float *loc_cur = NULL;
const float *loc_prev = NULL;
const float *normal = NULL;
@@ -240,8 +242,26 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
}
else if (t->spacetype == SPACE_IMAGE) {
if (validSnap(t)) {
- /* This will not draw, and I'm nor sure why - campbell */
- /* TODO: see 2.7x for non-working code */
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ float x, y;
+ const float snap_point[2] = {
+ t->tsnap.snapPoint[0] / t->aspect[0],
+ t->tsnap.snapPoint[1] / t->aspect[1],
+ };
+ UI_view2d_view_to_region_fl(&t->region->v2d, UNPACK2(snap_point), &x, &y);
+ float radius = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize;
+
+ GPU_matrix_push_projection();
+ wmOrtho2_region_pixelspace(t->region);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ub(255, 255, 255);
+ imm_draw_circle_wire_2d(pos, x, y, radius, 8);
+ immUnbindProgram();
+
+ GPU_matrix_pop_projection();
}
}
else if (t->spacetype == SPACE_NODE) {
@@ -990,17 +1010,19 @@ static void snap_calc_uv_fn(TransInfo *t, float *UNUSED(vec))
{
BLI_assert(t->spacetype == SPACE_IMAGE);
if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) {
- float co[2];
-
- UI_view2d_region_to_view(&t->region->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
-
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
t->view_layer, NULL, &objects_len);
- float dist_sq = FLT_MAX;
- if (ED_uvedit_nearest_uv_multi(
- t->scene, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) {
+ float dist_sq = square_f((float)SNAP_MIN_DISTANCE);
+ if (ED_uvedit_nearest_uv_multi(&t->region->v2d,
+ t->scene,
+ objects,
+ objects_len,
+ t->mval,
+ t->tsnap.modeSelect == SNAP_NOT_SELECTED,
+ &dist_sq,
+ t->tsnap.snapPoint)) {
t->tsnap.snapPoint[0] *= t->aspect[0];
t->tsnap.snapPoint[1] *= t->aspect[1];
diff --git a/source/blender/editors/util/ed_util_ops.cc b/source/blender/editors/util/ed_util_ops.cc
index 803e65590a0..af3589e50f0 100644
--- a/source/blender/editors/util/ed_util_ops.cc
+++ b/source/blender/editors/util/ed_util_ops.cc
@@ -67,19 +67,19 @@ static bool lib_id_preview_editing_poll(bContext *C)
static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op)
{
- char path[FILE_MAX];
+ char filepath[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", path);
+ RNA_string_get(op->ptr, "filepath", filepath);
- if (!BLI_is_file(path)) {
- BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", path);
+ if (!BLI_is_file(filepath)) {
+ BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", filepath);
return OPERATOR_CANCELLED;
}
PointerRNA idptr = CTX_data_pointer_get(C, "id");
ID *id = (ID *)idptr.data;
- BKE_previewimg_id_custom_set(id, path);
+ BKE_previewimg_id_custom_set(id, filepath);
WM_event_add_notifier(C, NC_ASSET | NA_EDITED, nullptr);
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index 6405d2df66a..ead017a91bf 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -1022,8 +1022,13 @@ bool uv_find_nearest_vert_multi(Scene *scene,
return found;
}
-bool ED_uvedit_nearest_uv(
- const Scene *scene, Object *obedit, const float co[2], float *dist_sq, float r_uv[2])
+static bool uvedit_nearest_uv(const Scene *scene,
+ Object *obedit,
+ const float co[2],
+ const float scale[2],
+ const bool ignore_selected,
+ float *dist_sq,
+ float r_uv[2])
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMIter iter;
@@ -1038,8 +1043,14 @@ bool ED_uvedit_nearest_uv(
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
do {
+ if (ignore_selected && uvedit_uv_select_test(scene, l_iter, cd_loop_uv_offset)) {
+ continue;
+ }
+
const float *uv = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
- const float dist_test = len_squared_v2v2(co, uv);
+ float co_tmp[2];
+ mul_v2_v2v2(co_tmp, scale, uv);
+ const float dist_test = len_squared_v2v2(co, co_tmp);
if (dist_best > dist_test) {
dist_best = dist_test;
uv_best = uv;
@@ -1055,17 +1066,27 @@ bool ED_uvedit_nearest_uv(
return false;
}
-bool ED_uvedit_nearest_uv_multi(const Scene *scene,
+bool ED_uvedit_nearest_uv_multi(const View2D *v2d,
+ const Scene *scene,
Object **objects,
const uint objects_len,
- const float co[2],
+ const int mval[2],
+ const bool ignore_selected,
float *dist_sq,
float r_uv[2])
{
bool found = false;
+
+ float scale[2], offset[2];
+ UI_view2d_scale_get(v2d, &scale[0], &scale[1]);
+ UI_view2d_view_to_region_fl(v2d, 0.0f, 0.0f, &offset[0], &offset[1]);
+
+ float co[2];
+ sub_v2_v2v2(co, (float[2]){UNPACK2(mval)}, offset);
+
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
- if (ED_uvedit_nearest_uv(scene, obedit, co, dist_sq, r_uv)) {
+ if (uvedit_nearest_uv(scene, obedit, co, scale, ignore_selected, dist_sq, r_uv)) {
found = true;
}
}
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index c0ea753ed51..945c2fc616e 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -103,7 +103,7 @@ static bool ED_uvedit_ensure_uvs(Object *obedit)
int cd_loop_uv_offset;
if (em && em->bm->totface && !CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
- ED_mesh_uv_texture_add(obedit->data, NULL, true, true, NULL);
+ ED_mesh_uv_add(obedit->data, NULL, true, true, NULL);
}
/* Happens when there are no faces. */
@@ -3038,7 +3038,7 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob)
* since we are not in edit mode we need to ensure only the uv flags are tested */
scene->toolsettings->uv_flag &= ~UV_SYNC_SELECTION;
- ED_mesh_uv_texture_ensure(me, NULL);
+ ED_mesh_uv_ensure(me, NULL);
BM_mesh_bm_from_me(bm,
me,