From 47a84bb33870d0fc8636d8d96f136d34e01ebce1 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 21 Oct 2020 15:51:15 +0200 Subject: Fix (studio-reported) Armature: bug in handling of custom bone transform. This specific pose channel pointer was not handled at all during rebuilding of poses, meaning that it could end up pointing at some freed pchan. --- source/blender/blenkernel/intern/armature.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source') diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index e0b12228162..7b8ed47c513 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2540,6 +2540,13 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { /* Find the custom B-Bone handles. */ BKE_pchan_rebuild_bbone_handles(pose, pchan); + /* Re-validate that we are still using a valid pchan form custom transform. */ + /* Note that we could store pointers of freed pchan in a GSet to speed this up, however this is + * supposed to be a rarely used feature, so for now assuming that always building that GSet + * would be less optimal. */ + if (pchan->custom_tx != NULL && BLI_findindex(&pose->chanbase, pchan->custom_tx) == -1) { + pchan->custom_tx = NULL; + } } /* printf("rebuild pose %s, %d bones\n", ob->id.name, counter); */ -- cgit v1.2.3 From 959a06b8ffdfe7eb28721c6ec559354825819058 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 21 Oct 2020 09:54:22 -0500 Subject: UI: Fix typo in sculpt trim tool description --- source/blender/editors/sculpt_paint/paint_mask.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source') diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index ef22766cd0c..f130c2ee685 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -850,7 +850,7 @@ static EnumPropertyItem prop_trim_operation_types[] = { "JOIN", 0, "Join", - "Join the new mesh as separate geometry, without preforming any boolean operation"}, + "Join the new mesh as separate geometry, without performing any boolean operation"}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From 62528677bf5d1feadeb8a6020922de3b59e8cbb2 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 21 Oct 2020 16:58:06 +0200 Subject: Fix 'Make Local' operation to support liboverrides. One can now use 'make local' from the Outliner or the 3DView to also fully localize overrides of linked data. --- source/blender/blenkernel/intern/lib_id.c | 3 +++ source/blender/editors/space_outliner/outliner_tools.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'source') diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 27422440cd5..ae6ee71da82 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -1884,6 +1884,9 @@ void BKE_library_make_local(Main *bmain, if (id->lib == NULL) { id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW); id->flag &= ~LIB_INDIRECT_WEAK_LINK; + if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + BKE_lib_override_library_free(&id->override_library, true); + } } /* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so it's possible to tag data * you don't want to be made local, used for appending data, diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 3357b0b7346..cbdeb350ba4 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -730,6 +730,9 @@ static void id_local_fn(bContext *C, BKE_main_id_clear_newpoins(bmain); } } + else if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id)) { + BKE_lib_override_library_free(&tselem->id->override_library, true); + } } static void object_proxy_to_override_convert_fn(bContext *C, -- cgit v1.2.3 From dd82a0d6239124a14bb554296364f6c951a8491e Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Wed, 21 Oct 2020 17:23:46 +0200 Subject: GPencil: Fix unreported problem with strokes bounding box that makes impossible sculpt When the stroke was not flat, the bounding box projected could not be right and the strokes could not be painted or sculpted. Now, the 2D bounding box is calculated using the extremes of the 2D bounding box and not the original 3D min and max values. --- source/blender/editors/gpencil/gpencil_utils.c | 56 +++++++++++++++++--------- 1 file changed, 37 insertions(+), 19 deletions(-) (limited to 'source') diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 5a45afe9c5a..28a90a26a9d 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -2916,6 +2916,40 @@ void ED_gpencil_sbuffer_vertex_color_set(Depsgraph *depsgraph, } } +/* Helper to get the bigger 2D bound box points. */ +static void gpencil_projected_2d_bound_box(GP_SpaceConversion *gsc, + bGPDstroke *gps, + const float diff_mat[4][4], + float r_min[2], + float r_max[2]) +{ + float bounds[8][2]; + BoundBox bb; + BKE_boundbox_init_from_minmax(&bb, gps->boundbox_min, gps->boundbox_max); + + /* Project 8 vertices in 2D. */ + for (int i = 0; i < 8; i++) { + bGPDspoint pt_dummy, pt_dummy_ps; + copy_v3_v3(&pt_dummy.x, bb.vec[i]); + gpencil_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps); + gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &bounds[i][0], &bounds[i][1]); + } + + /* Take extremes. */ + INIT_MINMAX2(r_min, r_max); + for (int i = 0; i < 8; i++) { + minmax_v2v2_v2(r_min, r_max, bounds[i]); + } + + /* Ensure the bounding box is oriented to axis. */ + if (r_max[0] < r_min[0]) { + SWAP(float, r_min[0], r_max[0]); + } + if (r_max[1] < r_min[1]) { + SWAP(float, r_min[1], r_max[1]); + } +} + /* Check if the stroke collides with brush. */ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc, bGPDstroke *gps, @@ -2924,31 +2958,15 @@ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc, const float diff_mat[4][4]) { const int offset = (int)ceil(sqrt((radius * radius) * 2)); - bGPDspoint pt_dummy, pt_dummy_ps; - float boundbox_min[2] = {0.0f}; - float boundbox_max[2] = {0.0f}; + float boundbox_min[2]; + float boundbox_max[2]; /* Check we have something to use (only for old files). */ if (is_zero_v3(gps->boundbox_min)) { BKE_gpencil_stroke_boundingbox_calc(gps); } - /* Convert bound box to 2d */ - copy_v3_v3(&pt_dummy.x, gps->boundbox_min); - gpencil_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps); - gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &boundbox_min[0], &boundbox_min[1]); - - copy_v3_v3(&pt_dummy.x, gps->boundbox_max); - gpencil_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps); - gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &boundbox_max[0], &boundbox_max[1]); - - /* Ensure the bounding box is oriented to axis. */ - if (boundbox_max[0] < boundbox_min[0]) { - SWAP(float, boundbox_min[0], boundbox_max[0]); - } - if (boundbox_max[1] < boundbox_min[1]) { - SWAP(float, boundbox_min[1], boundbox_max[1]); - } + gpencil_projected_2d_bound_box(gsc, gps, diff_mat, boundbox_min, boundbox_max); rcti rect_stroke = {boundbox_min[0], boundbox_max[0], boundbox_min[1], boundbox_max[1]}; -- cgit v1.2.3 From 187cc5e26d28b1a89e667915fa3a458f32f7f4a9 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 21 Oct 2020 12:18:30 +0200 Subject: UI: Move Properties path pin button next to the data-path The pin button should be next to the data-path, which is what it belongs to. Note that this makes the placement of the search button in the header look quite off. That is because it's centered to the absolute header width, not the width of the main region (which is smaller because of the tab region on the left). Technically it's correct that way, visually it looks wrong. This will be addressed in a followup commit. --- source/blender/editors/space_buttons/buttons_context.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source') diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 0d1efcab125..60ce86740cd 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -1163,6 +1163,15 @@ static void buttons_panel_context_draw(const bContext *C, Panel *panel) first = false; } + + uiLayout *pin_row = uiLayoutRow(row, false); + uiLayoutSetAlignment(pin_row, UI_LAYOUT_ALIGN_RIGHT); + uiItemSpacer(pin_row); + uiLayoutSetEmboss(pin_row, UI_EMBOSS_NONE); + uiItemO(pin_row, + "", + (sbuts->flag & SB_PIN_CONTEXT) ? ICON_PINNED : ICON_UNPINNED, + "BUTTONS_OT_toggle_pin"); } void buttons_context_register(ARegionType *art) -- cgit v1.2.3 From 3601cdd27bb351bce70e40e0f033ca6ddd9c9217 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 21 Oct 2020 17:34:53 +0200 Subject: UI: Swap order of increment and decrement file name icon in File Browser Swaps the order of the '+' and '-' button in the File Browser file name field, so that '-' comes first. For increasing or decreasing a value it makes more sense to have decreasing first, increasing last. Consistent to how you press on the left side of a number button for decrease, and right to increase. However this is inconsistent in another way: Usually we have a '+' button before a '-' button, but that refers to adding and removing items, not increasing or decreasing. The icons are also placed in their own buttons then, making them look more separate. So the UI Team agreed on accepting that trade-off, see today's meeting notes: https://devtalk.blender.org/t/2020-10-21-ui-team-upcoming/15849 --- source/blender/editors/space_file/file_panels.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source') diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c index ff9454cd922..a71dec99e61 100644 --- a/source/blender/editors/space_file/file_panels.c +++ b/source/blender/editors/space_file/file_panels.c @@ -180,12 +180,12 @@ static void file_panel_execution_buttons_draw(const bContext *C, Panel *panel) UI_but_funcN_set(but, file_filename_enter_handle, NULL, but); if (params->flag & FILE_CHECK_EXISTING) { - but_extra_rna_ptr = UI_but_extra_operator_icon_add( - but, "FILE_OT_filenum", WM_OP_EXEC_REGION_WIN, ICON_ADD); - RNA_int_set(but_extra_rna_ptr, "increment", 1); but_extra_rna_ptr = UI_but_extra_operator_icon_add( but, "FILE_OT_filenum", WM_OP_EXEC_REGION_WIN, ICON_REMOVE); RNA_int_set(but_extra_rna_ptr, "increment", -1); + but_extra_rna_ptr = UI_but_extra_operator_icon_add( + but, "FILE_OT_filenum", WM_OP_EXEC_REGION_WIN, ICON_ADD); + RNA_int_set(but_extra_rna_ptr, "increment", 1); } /* check if this overrides a file and if the operator option is used */ -- cgit v1.2.3 From 15cebd8565d093e141a1ca0332eee372fd4ba89e Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Tue, 20 Oct 2020 22:59:12 +0200 Subject: Fix T81901: Use the 2.90 scrape brush preset as default The new preset I made for 2.91 is way more controllable with lower strength values and does not have the accumulate bug, but until the brush management is in place to ship multiple versions of the brush, probably most people expect something closer to the old version to be the default. Reviewed By: sergey Maniphest Tasks: T81901 Differential Revision: https://developer.blender.org/D9289 --- source/blender/blenkernel/intern/brush.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index da4d9ea485c..17243b328e8 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1707,11 +1707,10 @@ void BKE_brush_sculpt_reset(Brush *br) case SCULPT_TOOL_SCRAPE: case SCULPT_TOOL_FILL: br->alpha = 0.7f; - br->area_radius_factor = 1.0f; + br->area_radius_factor = 0.5f; br->spacing = 7; br->flag |= BRUSH_ACCUMULATE; br->flag |= BRUSH_INVERT_TO_SCRAPE_FILL; - br->flag2 |= BRUSH_AREA_RADIUS_PRESSURE; break; case SCULPT_TOOL_ROTATE: br->alpha = 1.0; -- cgit v1.2.3 From 9216b8d6cb0be1bd83f5d3aaaccde6e2f209f580 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Wed, 21 Oct 2020 17:44:00 +0200 Subject: UI: Allow changing the active side of line gestures Line gesture use always the right side of the line as active (the area of the mesh that is going to be modified) by default. This adds the ability to change the active side when the line gesture is active by pressing the F key. This allows more freedom to position the line after starting the gestures, as it won't be required to cancel the operation or undo if the line was used in the wrong direction. Reviewed By: Severin Differential Revision: https://developer.blender.org/D9301 --- source/blender/editors/sculpt_paint/paint_mask.c | 9 +++++++++ source/blender/windowmanager/WM_types.h | 3 +++ source/blender/windowmanager/intern/wm_gesture.c | 8 +++++--- source/blender/windowmanager/intern/wm_gesture_ops.c | 12 ++++++++++++ source/blender/windowmanager/intern/wm_operator_props.c | 2 ++ source/blender/windowmanager/intern/wm_operators.c | 1 + source/blender/windowmanager/wm_event_types.h | 3 +++ 7 files changed, 35 insertions(+), 3 deletions(-) (limited to 'source') diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index f130c2ee685..305347b46a7 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -248,6 +248,7 @@ typedef struct LassoGestureData { typedef struct LineGestureData { float true_plane[4]; float plane[4]; + bool flip; } LineGestureData; struct SculptGestureOperation; @@ -461,6 +462,8 @@ static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperat line_points[1][0] = RNA_int_get(op->ptr, "xend"); line_points[1][1] = RNA_int_get(op->ptr, "yend"); + sgcontext->line.flip = RNA_boolean_get(op->ptr, "flip"); + float depth_point[3]; float plane_points[3][3]; @@ -481,6 +484,12 @@ static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperat if (!sgcontext->vc.rv3d->is_persp) { mul_v3_fl(normal, -1.0f); } + + /* Apply flip. */ + if (sgcontext->line.flip) { + mul_v3_fl(normal, -1.0f); + } + mul_v3_mat3_m4v3(normal, sgcontext->vc.obact->imat, normal); float plane_point_object_space[3]; mul_v3_m4v3(plane_point_object_space, sgcontext->vc.obact->imat, plane_points[0]); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index b23446e0dce..1b693160e56 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -503,6 +503,9 @@ typedef struct wmGesture { /** For gestures that support snapping, stores if snapping is enabled using the modal keymap * toggle. */ uint use_snap : 1; + /** For gestures that support flip, stores if flip is enabled using the modal keymap + * toggle. */ + uint use_flip : 1; /** * customdata diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index ae8b78876c2..4c1b403ac96 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -200,7 +200,7 @@ int wm_gesture_evaluate(wmGesture *gesture, const wmEvent *event) /* ******************* gesture draw ******************* */ -static void wm_gesture_draw_line_active_side(rcti *rect) +static void wm_gesture_draw_line_active_side(rcti *rect, const bool flip) { GPUVertFormat *format = immVertexFormat(); uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); @@ -222,7 +222,9 @@ static void wm_gesture_draw_line_active_side(rcti *rect) sub_v2_v2v2(line_dir, line_end, line_start); normalize_v2(line_dir); ortho_v2_v2(gradient_dir, line_dir); - mul_v2_fl(gradient_dir, -1.0f); + if (!flip) { + mul_v2_fl(gradient_dir, -1.0f); + } mul_v2_fl(gradient_dir, gradient_length); add_v2_v2v2(gradient_point[0], line_start, gradient_dir); add_v2_v2v2(gradient_point[1], line_end, gradient_dir); @@ -252,7 +254,7 @@ static void wm_gesture_draw_line(wmGesture *gt) rcti *rect = (rcti *)gt->customdata; if (gt->draw_active_side) { - wm_gesture_draw_line_active_side(rect); + wm_gesture_draw_line_active_side(rect, gt->use_flip); } uint shdr_pos = GPU_vertformat_attr_add( diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c index 00112e82771..edf9a3bc693 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.c +++ b/source/blender/windowmanager/intern/wm_gesture_ops.c @@ -851,6 +851,7 @@ static bool gesture_straightline_apply(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "ystart", rect->ymin); RNA_int_set(op->ptr, "xend", rect->xmax); RNA_int_set(op->ptr, "yend", rect->ymax); + RNA_boolean_set(op->ptr, "flip", gesture->use_flip); if (op->type->exec) { int retval = op->type->exec(C, op); @@ -892,6 +893,7 @@ int WM_gesture_straightline_active_side_invoke(bContext *C, wmOperator *op, cons WM_gesture_straightline_invoke(C, op, event); wmGesture *gesture = op->customdata; gesture->draw_active_side = true; + gesture->use_flip = false; return OPERATOR_RUNNING_MODAL; } @@ -950,6 +952,11 @@ int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *ev gesture->use_snap = !gesture->use_snap; break; } + case GESTURE_MODAL_FLIP: { + /* Toggle snapping on/off. */ + gesture->use_flip = !gesture->use_flip; + break; + } case GESTURE_MODAL_SELECT: { if (gesture_straightline_apply(C, op)) { gesture_modal_end(C, op); @@ -1029,6 +1036,11 @@ int WM_gesture_straightline_oneshot_modal(bContext *C, wmOperator *op, const wmE gesture->use_snap = !gesture->use_snap; break; } + case GESTURE_MODAL_FLIP: { + /* Toggle flip on/off. */ + gesture->use_flip = !gesture->use_flip; + break; + } case GESTURE_MODAL_SELECT: case GESTURE_MODAL_DESELECT: case GESTURE_MODAL_IN: diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index 78d8fc9a20d..62294d70306 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -498,6 +498,8 @@ void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_int(ot->srna, "yend", 0, INT_MIN, INT_MAX, "Y End", "", INT_MIN, INT_MAX); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "flip", false, "Flip", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); if (cursor) { prop = RNA_def_int(ot->srna, diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 5e4a45ea3be..613de5a9b17 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3807,6 +3807,7 @@ static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf) {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""}, {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""}, {GESTURE_MODAL_SNAP, "SNAP", 0, "Snap", ""}, + {GESTURE_MODAL_FLIP, "FLIP", 0, "Flip", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 21662a4e83a..223f6cf543d 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -496,6 +496,9 @@ enum { /** Toggle to activate snapping (angle snapping for straight line). */ GESTURE_MODAL_SNAP = 13, + + /** Toggle to activate flip (flip the active side of a straight line). */ + GESTURE_MODAL_FLIP = 14, }; #ifdef __cplusplus -- cgit v1.2.3 From f2d454c8291db1ee93f86d1365b58b308a4bedd4 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 21 Oct 2020 18:09:44 +0200 Subject: Bump version to 2.92 alpha --- source/blender/blenkernel/BKE_blender_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index aed4dad05ad..987b64c217e 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -31,7 +31,7 @@ extern "C" { */ /* Blender major and minor version. */ -#define BLENDER_VERSION 291 +#define BLENDER_VERSION 292 /* Blender patch version for bugfix releases. */ #define BLENDER_VERSION_PATCH 0 /** Blender release cycle stage: alpha/beta/rc/release. */ @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 8 +#define BLENDER_FILE_SUBVERSION 0 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file -- cgit v1.2.3 From fd96b29dccc47e755345567b0140f58d283dab31 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 21 Oct 2020 18:11:07 +0200 Subject: Bump subversion to 2.91.9 for bcon3 BETA --- source/blender/blenkernel/BKE_blender_version.h | 4 ++-- source/blender/blenloader/intern/versioning_290.c | 26 ++++++++++++---------- .../blender/blenloader/intern/versioning_userdef.c | 6 +++-- 3 files changed, 20 insertions(+), 16 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index aed4dad05ad..741abb50453 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -35,11 +35,11 @@ extern "C" { /* Blender patch version for bugfix releases. */ #define BLENDER_VERSION_PATCH 0 /** Blender release cycle stage: alpha/beta/rc/release. */ -#define BLENDER_VERSION_CYCLE alpha +#define BLENDER_VERSION_CYCLE beta /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 8 +#define BLENDER_FILE_SUBVERSION 9 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 2daa1d48f47..00085cb7d59 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -885,18 +885,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - /** - * Versioning code until next subversion bump goes here. - * - * \note Be sure to check when bumping the version: - * - "versioning_userdef.c", #blo_do_versions_userdef - * - "versioning_userdef.c", #do_versions_theme - * - * \note Keep this message at the bottom of the function. - */ - { - /* Keep this block, even when empty. */ - + if (!MAIN_VERSION_ATLEAST(bmain, 291, 9)) { /* Remove options of legacy UV/Image editor */ for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { @@ -925,4 +914,17 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /** + * Versioning code until next subversion bump goes here. + * + * \note Be sure to check when bumping the version: + * - "versioning_userdef.c", #blo_do_versions_userdef + * - "versioning_userdef.c", #do_versions_theme + * + * \note Keep this message at the bottom of the function. + */ + { + /* Keep this block, even when empty. */ + } } diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index e81735c698d..6b6d226bd90 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -242,6 +242,10 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme) copy_v3_v3_uchar(btheme->space_node.grid, btheme->space_node.back); } + if (!USER_VERSION_ATLEAST(291, 9)) { + FROM_DEFAULT_V4_UCHAR(space_graph.vertex_active); + } + /** * Versioning code until next subversion bump goes here. * @@ -253,8 +257,6 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme) */ { /* Keep this block, even when empty. */ - - FROM_DEFAULT_V4_UCHAR(space_graph.vertex_active); } #undef FROM_DEFAULT_V4_UCHAR -- cgit v1.2.3 From 7ff6bfd1e0af67d2e583d12ce5aee5d2bf8ef96e Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Wed, 21 Oct 2020 17:44:00 +0200 Subject: UI: Allow changing the active side of line gestures Line gesture use always the right side of the line as active (the area of the mesh that is going to be modified) by default. This adds the ability to change the active side when the line gesture is active by pressing the F key. This allows more freedom to position the line after starting the gestures, as it won't be required to cancel the operation or undo if the line was used in the wrong direction. Reviewed By: Severin Differential Revision: https://developer.blender.org/D9301 --- source/blender/editors/sculpt_paint/paint_mask.c | 9 +++++++++ source/blender/windowmanager/WM_types.h | 3 +++ source/blender/windowmanager/intern/wm_gesture.c | 8 +++++--- source/blender/windowmanager/intern/wm_gesture_ops.c | 12 ++++++++++++ source/blender/windowmanager/intern/wm_operator_props.c | 2 ++ source/blender/windowmanager/intern/wm_operators.c | 1 + source/blender/windowmanager/wm_event_types.h | 3 +++ 7 files changed, 35 insertions(+), 3 deletions(-) (limited to 'source') diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index f130c2ee685..305347b46a7 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -248,6 +248,7 @@ typedef struct LassoGestureData { typedef struct LineGestureData { float true_plane[4]; float plane[4]; + bool flip; } LineGestureData; struct SculptGestureOperation; @@ -461,6 +462,8 @@ static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperat line_points[1][0] = RNA_int_get(op->ptr, "xend"); line_points[1][1] = RNA_int_get(op->ptr, "yend"); + sgcontext->line.flip = RNA_boolean_get(op->ptr, "flip"); + float depth_point[3]; float plane_points[3][3]; @@ -481,6 +484,12 @@ static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperat if (!sgcontext->vc.rv3d->is_persp) { mul_v3_fl(normal, -1.0f); } + + /* Apply flip. */ + if (sgcontext->line.flip) { + mul_v3_fl(normal, -1.0f); + } + mul_v3_mat3_m4v3(normal, sgcontext->vc.obact->imat, normal); float plane_point_object_space[3]; mul_v3_m4v3(plane_point_object_space, sgcontext->vc.obact->imat, plane_points[0]); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index b23446e0dce..1b693160e56 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -503,6 +503,9 @@ typedef struct wmGesture { /** For gestures that support snapping, stores if snapping is enabled using the modal keymap * toggle. */ uint use_snap : 1; + /** For gestures that support flip, stores if flip is enabled using the modal keymap + * toggle. */ + uint use_flip : 1; /** * customdata diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index ae8b78876c2..4c1b403ac96 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -200,7 +200,7 @@ int wm_gesture_evaluate(wmGesture *gesture, const wmEvent *event) /* ******************* gesture draw ******************* */ -static void wm_gesture_draw_line_active_side(rcti *rect) +static void wm_gesture_draw_line_active_side(rcti *rect, const bool flip) { GPUVertFormat *format = immVertexFormat(); uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); @@ -222,7 +222,9 @@ static void wm_gesture_draw_line_active_side(rcti *rect) sub_v2_v2v2(line_dir, line_end, line_start); normalize_v2(line_dir); ortho_v2_v2(gradient_dir, line_dir); - mul_v2_fl(gradient_dir, -1.0f); + if (!flip) { + mul_v2_fl(gradient_dir, -1.0f); + } mul_v2_fl(gradient_dir, gradient_length); add_v2_v2v2(gradient_point[0], line_start, gradient_dir); add_v2_v2v2(gradient_point[1], line_end, gradient_dir); @@ -252,7 +254,7 @@ static void wm_gesture_draw_line(wmGesture *gt) rcti *rect = (rcti *)gt->customdata; if (gt->draw_active_side) { - wm_gesture_draw_line_active_side(rect); + wm_gesture_draw_line_active_side(rect, gt->use_flip); } uint shdr_pos = GPU_vertformat_attr_add( diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c index 00112e82771..edf9a3bc693 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.c +++ b/source/blender/windowmanager/intern/wm_gesture_ops.c @@ -851,6 +851,7 @@ static bool gesture_straightline_apply(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "ystart", rect->ymin); RNA_int_set(op->ptr, "xend", rect->xmax); RNA_int_set(op->ptr, "yend", rect->ymax); + RNA_boolean_set(op->ptr, "flip", gesture->use_flip); if (op->type->exec) { int retval = op->type->exec(C, op); @@ -892,6 +893,7 @@ int WM_gesture_straightline_active_side_invoke(bContext *C, wmOperator *op, cons WM_gesture_straightline_invoke(C, op, event); wmGesture *gesture = op->customdata; gesture->draw_active_side = true; + gesture->use_flip = false; return OPERATOR_RUNNING_MODAL; } @@ -950,6 +952,11 @@ int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *ev gesture->use_snap = !gesture->use_snap; break; } + case GESTURE_MODAL_FLIP: { + /* Toggle snapping on/off. */ + gesture->use_flip = !gesture->use_flip; + break; + } case GESTURE_MODAL_SELECT: { if (gesture_straightline_apply(C, op)) { gesture_modal_end(C, op); @@ -1029,6 +1036,11 @@ int WM_gesture_straightline_oneshot_modal(bContext *C, wmOperator *op, const wmE gesture->use_snap = !gesture->use_snap; break; } + case GESTURE_MODAL_FLIP: { + /* Toggle flip on/off. */ + gesture->use_flip = !gesture->use_flip; + break; + } case GESTURE_MODAL_SELECT: case GESTURE_MODAL_DESELECT: case GESTURE_MODAL_IN: diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index 78d8fc9a20d..62294d70306 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -498,6 +498,8 @@ void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_int(ot->srna, "yend", 0, INT_MIN, INT_MAX, "Y End", "", INT_MIN, INT_MAX); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "flip", false, "Flip", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); if (cursor) { prop = RNA_def_int(ot->srna, diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 5e4a45ea3be..613de5a9b17 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3807,6 +3807,7 @@ static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf) {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""}, {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""}, {GESTURE_MODAL_SNAP, "SNAP", 0, "Snap", ""}, + {GESTURE_MODAL_FLIP, "FLIP", 0, "Flip", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 21662a4e83a..223f6cf543d 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -496,6 +496,9 @@ enum { /** Toggle to activate snapping (angle snapping for straight line). */ GESTURE_MODAL_SNAP = 13, + + /** Toggle to activate flip (flip the active side of a straight line). */ + GESTURE_MODAL_FLIP = 14, }; #ifdef __cplusplus -- cgit v1.2.3 From 657e344351740daf97ff28f4fc53d448e3de75ee Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Wed, 21 Oct 2020 19:15:18 +0200 Subject: GPencil: Bake mesh animation for selected keyframes only This new option allows to bake the animation of the selected frames and not the full range of keyframes. --- source/blender/editors/gpencil/gpencil_mesh.c | 80 ++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 14 deletions(-) (limited to 'source') diff --git a/source/blender/editors/gpencil/gpencil_mesh.c b/source/blender/editors/gpencil/gpencil_mesh.c index e4862617d12..7cf4325d03b 100644 --- a/source/blender/editors/gpencil/gpencil_mesh.c +++ b/source/blender/editors/gpencil/gpencil_mesh.c @@ -25,12 +25,15 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BLI_math.h" +#include "DNA_anim_types.h" #include "DNA_gpencil_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "BKE_anim_data.h" #include "BKE_context.h" #include "BKE_duplilist.h" #include "BKE_global.h" @@ -86,6 +89,35 @@ typedef struct GpBakeOb { Object *ob; } GpBakeOb; +/* Get list of keyframes used by selected objects. */ +static void animdata_keyframe_list_get(ListBase *ob_list, + const bool only_selected, + GHash *r_keyframes) +{ + /* Loop all objects to get the list of keyframes used. */ + LISTBASE_FOREACH (GpBakeOb *, elem, ob_list) { + Object *ob = elem->ob; + AnimData *adt = BKE_animdata_from_id(&ob->id); + if ((adt == NULL) || (adt->action == NULL)) { + continue; + } + LISTBASE_FOREACH (FCurve *, fcurve, &adt->action->curves) { + int i; + BezTriple *bezt; + for (i = 0, bezt = fcurve->bezt; i < fcurve->totvert; i++, bezt++) { + /* Keyframe number is x value of point. */ + if ((bezt->f2 & SELECT) || (!only_selected)) { + /* Insert only one key for each keyframe number. */ + int key = (int)bezt->vec[1][0]; + if (!BLI_ghash_haskey(r_keyframes, POINTER_FROM_INT(key))) { + BLI_ghash_insert(r_keyframes, POINTER_FROM_INT(key), POINTER_FROM_INT(key)); + } + } + } + } + } +} + static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *list) { GpBakeOb *elem = NULL; @@ -161,13 +193,13 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); Object *ob_gpencil = NULL; - ListBase list = {NULL, NULL}; - gpencil_bake_ob_list(C, depsgraph, scene, &list); + ListBase ob_selected_list = {NULL, NULL}; + gpencil_bake_ob_list(C, depsgraph, scene, &ob_selected_list); /* Cannot check this in poll because the active object changes. */ - if (list.first == NULL) { + if (ob_selected_list.first == NULL) { BKE_report(op->reports, RPT_INFO, "No valid object selected"); - gpencil_bake_free_ob_list(&list); + gpencil_bake_free_ob_list(&ob_selected_list); return OPERATOR_CANCELLED; } @@ -186,6 +218,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) const int thickness = RNA_int_get(op->ptr, "thickness"); const bool use_seams = RNA_boolean_get(op->ptr, "seams"); const bool use_faces = RNA_boolean_get(op->ptr, "faces"); + const bool only_selected = RNA_boolean_get(op->ptr, "only_selected"); const float offset = RNA_float_get(op->ptr, "offset"); const int frame_offset = RNA_int_get(op->ptr, "frame_target") - frame_start; char target[64]; @@ -206,7 +239,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) if ((ob_gpencil == NULL) || (ob_gpencil->type != OB_GPENCIL)) { BKE_report(op->reports, RPT_ERROR, "Target grease pencil object not valid"); - gpencil_bake_free_ob_list(&list); + gpencil_bake_free_ob_list(&ob_selected_list); return OPERATOR_CANCELLED; } @@ -237,6 +270,13 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) /* Loop all frame range. */ int oldframe = (int)DEG_get_ctime(depsgraph); int key = -1; + + /* Get list of keyframes. */ + GHash *keyframe_list = BLI_ghash_int_new(__func__); + if (only_selected) { + animdata_keyframe_list_get(&ob_selected_list, only_selected, keyframe_list); + } + for (int i = frame_start; i < frame_end + 1; i++) { key++; /* Jump if not step limit but include last frame always. */ @@ -244,12 +284,17 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) continue; } + /* Check if frame is in the list of frames to be exported. */ + if ((only_selected) && (!BLI_ghash_haskey(keyframe_list, POINTER_FROM_INT(i)))) { + continue; + } + /* Move scene to new frame. */ CFRA = i; BKE_scene_graph_update_for_newframe(depsgraph); /* Loop all objects in the list. */ - LISTBASE_FOREACH (GpBakeOb *, elem, &list) { + LISTBASE_FOREACH (GpBakeOb *, elem, &ob_selected_list) { Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, elem->ob); /* Generate strokes. */ @@ -270,13 +315,14 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) if (project_type != GP_REPROJECT_KEEP) { LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { bGPDframe *gpf = gpl->actframe; - if (gpf != NULL) { - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - if ((gps->flag & GP_STROKE_TAG) == 0) { - ED_gpencil_stroke_reproject( - depsgraph, &gsc, sctx, gpl, gpf, gps, project_type, false); - gps->flag |= GP_STROKE_TAG; - } + if (gpf == NULL) { + continue; + } + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + if ((gps->flag & GP_STROKE_TAG) == 0) { + ED_gpencil_stroke_reproject( + depsgraph, &gsc, sctx, gpl, gpf, gps, project_type, false); + gps->flag |= GP_STROKE_TAG; } } } @@ -314,10 +360,14 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) } /* Free memory. */ - gpencil_bake_free_ob_list(&list); + gpencil_bake_free_ob_list(&ob_selected_list); if (sctx != NULL) { ED_transform_snap_object_context_destroy(sctx); } + /* Free temp hash table. */ + if (keyframe_list != NULL) { + BLI_ghash_free(keyframe_list, NULL, NULL); + } /* notifiers */ if (newob) { @@ -394,6 +444,8 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) RNA_def_int(ot->srna, "thickness", 1, 1, 100, "Thickness", "", 1, 100); RNA_def_boolean(ot->srna, "seams", 0, "Only Seam Edges", "Convert only seam edges"); RNA_def_boolean(ot->srna, "faces", 1, "Export Faces", "Export faces as filled strokes"); + RNA_def_boolean( + ot->srna, "only_selected", 0, "Only Selected Keyframes", "Convert only selected keyframes"); RNA_def_float_distance( ot->srna, "offset", 0.001f, 0.0, 100.0, "Offset", "Offset strokes from fill", 0.0, 100.00); RNA_def_int(ot->srna, "frame_target", 1, 1, 100000, "Frame Target", "", 1, 100000); -- cgit v1.2.3 From e296d58cf22076985c7a182498e7f1a4e3edf7e0 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Fri, 25 Sep 2020 17:08:07 +0200 Subject: GPencil: Subdivide Cyclic section of strokes in modifier When use subdivision modifier, the close section of the stroke must be subdivided too. --- source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source') diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c index 6eb12974408..8f17be97710 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c @@ -101,6 +101,11 @@ static void deformStroke(GpencilModifierData *md, } BKE_gpencil_stroke_subdivide(gps, mmd->level, mmd->type); + + /* If the stroke is cyclic, must generate the closing geometry. */ + if (gps->flag & GP_STROKE_CYCLIC) { + BKE_gpencil_stroke_close(gps); + } } static void bakeModifier(struct Main *UNUSED(bmain), -- cgit v1.2.3 From d2f52dccd39ba6fb29c099e35f62559bb28548fa Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Wed, 21 Oct 2020 18:49:21 +0200 Subject: Fix T81929: Sculpt: Mask operators missing drawing update on meshes with shapekeys/modifiers This was failing for all mask filters (sharpen, grow, invert, clear, shrink, contrast, smooth) and mask gestures (box, lasso). Also have to recalc shading, use SCULPT_tag_update_overlays for this. ref D8956 Maniphest Tasks: T81929 Differential Revision: https://developer.blender.org/D9302 --- source/blender/editors/sculpt_paint/paint_mask.c | 3 +-- source/blender/editors/sculpt_paint/sculpt_filter_mask.c | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'source') diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 305347b46a7..2193a31f19b 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -657,8 +657,7 @@ static void sculpt_gesture_apply(bContext *C, SculptGestureContext *sgcontext) SCULPT_undo_push_end(); - ED_region_tag_redraw(sgcontext->vc.region); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, sgcontext->vc.obact); + SCULPT_tag_update_overlays(C); } /* Face Set Gesture Operation. */ diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c index e764df78c88..8fa20aaae50 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c @@ -192,7 +192,6 @@ static void mask_filter_task_cb(void *__restrict userdata, static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) { - ARegion *region = CTX_wm_region(C); Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); @@ -259,8 +258,8 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) SCULPT_undo_push_end(); - ED_region_tag_redraw(region); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + SCULPT_tag_update_overlays(C); + return OPERATOR_FINISHED; } -- cgit v1.2.3 From 23ec1f90e71b8c2a63f42811ab4a7729f005f265 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Wed, 21 Oct 2020 11:04:39 +0200 Subject: Fix T81896: Outliner missing redraw after "Set Parent (Without Inverse)" Outliners listener (outliner_main_region_listener) needs ND_PARENT notifier to redraw, the parenting operator only spawned ND_TRANSFORM (which doesnt do a redraw). Maniphest Tasks: T81896 Differential Revision: https://developer.blender.org/D9295 --- source/blender/editors/object/object_relations.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source') diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 780ce487550..de3e5f3d5f9 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1244,6 +1244,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); return OPERATOR_FINISHED; } -- cgit v1.2.3 From 0cbe6387e90cb8ed85c8bd48e8c0ad413eca7f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 21 Oct 2020 17:57:43 +0200 Subject: EEVEE: Screen Space Raytrace: Fix unreported banding artifacts The artifact manifested as lines of different values caused by faillure to trace the depth buffer correctly. Adding a ad-hoc value to the step size to mitigate the issue. --- source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source') diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl index cad1346609a..225bf9b07db 100644 --- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -173,7 +173,8 @@ vec3 raycast(int index, float iter; for (iter = 1.0; !hit && (ray_time < max_time) && (iter < MAX_STEP); iter++) { /* Minimum stride of 2 because we are using half res minmax zbuffer. */ - float stride = max(1.0, iter * trace_quality) * 2.0; + /* WORKAROUND: Factor is a bit higher than 2 to avoid some banding. To investigate. */ + float stride = max(1.0, iter * trace_quality) * (2.0 + 0.05); float lod = log2(stride * 0.5 * trace_quality) * lod_fac; ray_time += stride; -- cgit v1.2.3 From 27137c479cc309bbb72ed4e41d481cdcfb773716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 21 Oct 2020 22:51:23 +0200 Subject: EEVEE: Screen Space Reflection: Improve contact reflections This patch helps the case of intricate reflections where the ray does not travel far before intersecting the geometry. In these cases there could be false negative exclusion of the ray caused by the backface rejection threshold. --- source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source') diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl index 225bf9b07db..dbb5e660dab 100644 --- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -235,9 +235,10 @@ vec3 raycast(int index, #endif } - if (discard_backface) { - /* Discard backface hits */ - hit = hit && (prev_delta > 0.0); + /* Discard backface hits. Only do this if the ray traveled enough to avoid loosing intricate + * contact reflections. This is only used for SSReflections. */ + if (discard_backface && prev_delta < 0.0 && curr_time > 4.1) { + hit = false; } /* Reject hit if background. */ -- cgit v1.2.3 From ef5d6e9c457a4265467b6aca588c55ba60689ff0 Mon Sep 17 00:00:00 2001 From: Robert Guetzkow Date: Thu, 22 Oct 2020 09:51:51 +1100 Subject: Fix T81925: incorrectly skipped string copy in test_env_path Regression in 6f3a9031f7b93e7c687edde646beed9f02d920d4 --- source/blender/blenkernel/intern/appdir.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 44fc608530b..00c62340e16 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -254,8 +254,12 @@ static bool test_path(char *targetpath, } /** - * Puts the value of the specified environment variable into *path if it exists - * and points at a directory. Returns true if this was done. + * Puts the value of the specified environment variable into \a path if it exists. + * + * \param check_is_dir: When true, checks if it points at a directory. + * + * \returns true when the value of the environment variable is stored + * at the address \a path points to. */ static bool test_env_path(char *path, const char *envvar, const bool check_is_dir) { @@ -266,13 +270,14 @@ static bool test_env_path(char *path, const char *envvar, const bool check_is_di return false; } + BLI_strncpy(path, env_path, FILE_MAX); + if (check_is_dir == false) { CLOG_INFO(&LOG, 3, "using env '%s' without test: '%s'", envvar, env_path); return true; } if (BLI_is_dir(env_path)) { - BLI_strncpy(path, env_path, FILE_MAX); CLOG_INFO(&LOG, 3, "env '%s' found: %s", envvar, env_path); return true; } -- cgit v1.2.3 From e1eaf9e2b4ef85f0f899d1429200fe51c5625c2a Mon Sep 17 00:00:00 2001 From: Robert Guetzkow Date: Thu, 22 Oct 2020 09:51:51 +1100 Subject: Fix T81925: incorrectly skipped string copy in test_env_path Regression in 6f3a9031f7b93e7c687edde646beed9f02d920d4 Ref D9306 --- source/blender/blenkernel/intern/appdir.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 44fc608530b..00c62340e16 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -254,8 +254,12 @@ static bool test_path(char *targetpath, } /** - * Puts the value of the specified environment variable into *path if it exists - * and points at a directory. Returns true if this was done. + * Puts the value of the specified environment variable into \a path if it exists. + * + * \param check_is_dir: When true, checks if it points at a directory. + * + * \returns true when the value of the environment variable is stored + * at the address \a path points to. */ static bool test_env_path(char *path, const char *envvar, const bool check_is_dir) { @@ -266,13 +270,14 @@ static bool test_env_path(char *path, const char *envvar, const bool check_is_di return false; } + BLI_strncpy(path, env_path, FILE_MAX); + if (check_is_dir == false) { CLOG_INFO(&LOG, 3, "using env '%s' without test: '%s'", envvar, env_path); return true; } if (BLI_is_dir(env_path)) { - BLI_strncpy(path, env_path, FILE_MAX); CLOG_INFO(&LOG, 3, "env '%s' found: %s", envvar, env_path); return true; } -- cgit v1.2.3 From 091b43367725f65d3c7f81400ec57624dfa70b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Thu, 22 Oct 2020 00:20:06 +0200 Subject: Fix T77658 EEVEE: Reflection Plane partially missing reflections The degenerate line workaround was ill defined. --- source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source') diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl index dbb5e660dab..db3497bd043 100644 --- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -105,7 +105,9 @@ void prepare_raycast(vec3 ray_origin, /* If the line is degenerate, make it cover at least one pixel * to not have to handle zero-pixel extent as a special case later */ - ss_step.xy += vec2((dot(ss_step.xy, ss_step.xy) < 0.00001) ? 0.001 : 0.0); + if (dot(ss_step.xy, ss_step.xy) < 0.00001) { + ss_step.xy = vec2(0.0, 0.0001); + } /* Make ss_step cover one pixel. */ ss_step /= max(abs(ss_step.x), abs(ss_step.y)); -- cgit v1.2.3 From b0f34eee30c42a485e83ca6f5e9495fc0c9283fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Thu, 22 Oct 2020 00:55:38 +0200 Subject: EEVEE: Principle BSDF: Use multi-scatter switch for the glass variant This avoid strange discrepency between the general purpose variant and the specialized glass variant which did not have a way to turn multi-scatter off. --- source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source') diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl index 3708b8b0531..3bd578e1ffc 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -450,7 +450,7 @@ void node_bsdf_principled_glass(vec4 base_color, eevee_closure_glass(N, vec3(1.0), - vec3(1.0), + vec3((use_multiscatter != 0.0) ? 1.0 : -1.0), int(ssr_id), roughness, 1.0, -- cgit v1.2.3 From 5a65305f8998a72c8bf39bc69414c7ba2da57055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Thu, 22 Oct 2020 01:09:35 +0200 Subject: Fix T81784 BGL: Gizmo glitch when using glEnable/glDisable This was caused by unprotected drawing callbacks. From 2.91, we now require that all python callbacks used for drawing needs to be safeguarded by `GPU_bgl_end()` to end the state tracking override. --- source/blender/makesrna/intern/rna_wm_gizmo.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source') diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c index 971991869e2..27d46e4d25b 100644 --- a/source/blender/makesrna/intern/rna_wm_gizmo.c +++ b/source/blender/makesrna/intern/rna_wm_gizmo.c @@ -61,6 +61,8 @@ # include "MEM_guardedalloc.h" +# include "GPU_state.h" + # ifdef WITH_PYTHON # include "BPY_extern.h" # endif @@ -84,6 +86,8 @@ static void rna_gizmo_draw_cb(const struct bContext *C, struct wmGizmo *gz) RNA_parameter_set_lookup(&list, "context", &C); gzgroup->type->rna_ext.call((bContext *)C, &gz_ptr, func, &list); RNA_parameter_list_free(&list); + /* This callback may have called bgl functions. */ + GPU_bgl_end(); } static void rna_gizmo_draw_select_cb(const struct bContext *C, struct wmGizmo *gz, int select_id) @@ -101,6 +105,8 @@ static void rna_gizmo_draw_select_cb(const struct bContext *C, struct wmGizmo *g RNA_parameter_set_lookup(&list, "select_id", &select_id); gzgroup->type->rna_ext.call((bContext *)C, &gz_ptr, func, &list); RNA_parameter_list_free(&list); + /* This callback may have called bgl functions. */ + GPU_bgl_end(); } static int rna_gizmo_test_select_cb(struct bContext *C, struct wmGizmo *gz, const int location[2]) -- cgit v1.2.3 From cc3fdffbbe450ef75a49571ec75fd8f0ecb45550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Thu, 22 Oct 2020 01:19:10 +0200 Subject: DRW: Fix custom engine not being BGL safe This was caused by unprotected drawing callbacks. As of 2.91, we require that all python callbacks used for drawing needs to be safeguarded by `GPU_bgl_end()` to end the state tracking override. --- source/blender/draw/engines/external/external_engine.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source') diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index bcdd0f9e3dc..bd97fd8a413 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -36,6 +36,7 @@ #include "GPU_matrix.h" #include "GPU_shader.h" +#include "GPU_state.h" #include "GPU_viewport.h" #include "external_engine.h" /* own include */ @@ -243,6 +244,8 @@ static void external_draw_scene_do(void *vedata) type = rv3d->render_engine->type; type->view_draw(rv3d->render_engine, draw_ctx->evil_C, draw_ctx->depsgraph); + GPU_bgl_end(); + GPU_matrix_pop(); GPU_matrix_pop_projection(); -- cgit v1.2.3 From 88660d67a4c5e88e7b7b7304b66e4d893affed91 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 22 Oct 2020 11:53:24 +1100 Subject: WM: ensure is_repeat isn't set for mouse-move events Follow up to d782bad62dc53373bb28811c0672da81924371d6 Also clear this for simulated events. --- source/blender/makesrna/intern/rna_wm_api.c | 1 + source/blender/windowmanager/intern/wm_event_system.c | 1 + 2 files changed, 2 insertions(+) (limited to 'source') diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index 47d5e9b6313..2cabc89feee 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -632,6 +632,7 @@ static wmEvent *rna_Window_event_add_simulate(wmWindow *win, wmEvent e = *win->eventstate; e.type = type; e.val = value; + e.is_repeat = false; e.x = x; e.y = y; /* Note: KM_MOD_FIRST, KM_MOD_SECOND aren't used anywhere, set as bools */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index e6ec68f706c..faec579a7c3 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -3402,6 +3402,7 @@ void wm_event_do_handlers(bContext *C) tevent.type = MOUSEMOVE; tevent.prevx = tevent.x; tevent.prevy = tevent.y; + tevent.is_repeat = false; wm_event_add(win, &tevent); win->addmousemove = 0; } -- cgit v1.2.3 From 8da55990034e2d5b0a9910583706e4ea99d0f3ce Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 22 Oct 2020 11:53:40 +1100 Subject: WM: warn when event's have repeat set for non keyboard events Also add docs to event and keymap item flag. --- source/blender/makesdna/DNA_windowmanager_types.h | 13 +++++++++++++ source/blender/windowmanager/WM_types.h | 7 ++++++- source/blender/windowmanager/intern/wm_event_system.c | 9 +++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) (limited to 'source') diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 3f7e3e61d56..4b4e17b38bd 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -383,6 +383,19 @@ enum { KMI_EXPANDED = (1 << 1), KMI_USER_MODIFIED = (1 << 2), KMI_UPDATE = (1 << 3), + /** + * When set, ignore events with #wmEvent.is_repeat enabled. + * + * \note this flag isn't cleared when editing/loading the key-map items, + * so it may be set in cases which don't make sense (modifier-keys or mouse-motion for example). + * + * Knowing if an event may repeat is something set at the operating-systems event handling level + * so rely on #wmEvent.is_repeat being false non keyboard events instead of checking if this + * flag makes sense. + * + * Only used when: `ISKEYBOARD(kmi->type) || (kmi->type == KM_TEXTINPUT)` + * as mouse, 3d-mouse, timer... etc never repeat. + */ KMI_REPEAT_IGNORE = (1 << 4), }; diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 1b693160e56..a8d24205268 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -559,7 +559,12 @@ typedef struct wmEvent { /** From ghost, fallback if utf8 isn't set. */ char ascii; - /** Generated by auto-repeat. */ + /** + * Generated by auto-repeat, note that this must only ever be set for keyboard events + * where `ISKEYBOARD(event->type) == true`. + * + * See #KMI_REPEAT_IGNORE for details on how key-map handling uses this. + */ char is_repeat; /** Previous state, used for double click and the 'click'. */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index faec579a7c3..8eb9a3b0650 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -155,6 +155,15 @@ wmEvent *WM_event_add_simulate(wmWindow *win, const wmEvent *event_to_add) void wm_event_free(wmEvent *event) { +#ifndef NDEBUG + /* Don't use assert here because it's fairly harmless in most cases, + * more an issue of correctness, something we should avoid in general. */ + if (event->is_repeat && !ISKEYBOARD(event->type)) { + printf("%s: 'is_repeat=true' for non-keyboard event, this should not happen.\n", __func__); + WM_event_print(event); + } +#endif + if (event->customdata) { if (event->customdatafree) { /* Note: pointer to listbase struct elsewhere. */ -- cgit v1.2.3 From b9c8eb3b0c8caff1a593be2a6e7b1bca267aa4f5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 22 Oct 2020 12:29:38 +1100 Subject: PyAPI: expose the file version via bpy.app.version_file This exposes the version saved to the file, compatible with `bpy.data.version`. This is needed to write out version information into key-maps. --- source/blender/python/intern/bpy_app.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source') diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 554ab2645a7..a580b4f10f0 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -82,6 +82,7 @@ static PyTypeObject BlenderAppType; static PyStructSequence_Field app_info_fields[] = { {"version", "The Blender version as a tuple of 3 numbers. eg. (2, 83, 1)"}, + {"version_file", "The blend file version, compatible with ``bpy.data.version``"}, {"version_string", "The Blender version formatted as a string"}, {"version_cycle", "The release status of this build alpha/beta/rc/release"}, {"version_char", "Deprecated, always an empty string"}, @@ -151,6 +152,8 @@ static PyObject *make_app_info(void) SetObjItem( PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_VERSION_PATCH)); + SetObjItem(PyC_Tuple_Pack_I32( + BLENDER_FILE_VERSION / 100, BLENDER_FILE_VERSION % 100, BLENDER_FILE_SUBVERSION)); SetStrItem(BKE_blender_version_string()); SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE)); -- cgit v1.2.3 From f5080c82dd915db6c7b9dd68a52aaaccf2600137 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 22 Oct 2020 12:29:45 +1100 Subject: Keymap: disable 'repeat' by default for keymap items In practice, there are only a limited number of operations we need to use repeat such as navigation, stepping operations that cycle states and text input. Now we don't need to disable repeat explicitly when a modal operator uses checks for a key being held as was needed for 17cb2a6da0c88. Repeat is now included in exported keymaps. Use versioning so existing exported keymaps are loaded properly. --- source/blender/makesrna/intern/rna_wm_api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index 2cabc89feee..2c373eb8d46 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -1135,7 +1135,7 @@ void RNA_api_keymapitems(StructRNA *srna) RNA_def_boolean(func, "alt", 0, "Alt", ""); RNA_def_boolean(func, "oskey", 0, "OS Key", ""); RNA_def_enum(func, "key_modifier", rna_enum_event_type_items, 0, "Key Modifier", ""); - RNA_def_boolean(func, "repeat", true, "Repeat", "When set, accept key-repeat events"); + RNA_def_boolean(func, "repeat", false, "Repeat", "When set, accept key-repeat events"); RNA_def_boolean(func, "head", 0, @@ -1159,7 +1159,7 @@ void RNA_api_keymapitems(StructRNA *srna) RNA_def_boolean(func, "alt", 0, "Alt", ""); RNA_def_boolean(func, "oskey", 0, "OS Key", ""); RNA_def_enum(func, "key_modifier", rna_enum_event_type_items, 0, "Key Modifier", ""); - RNA_def_boolean(func, "repeat", true, "Repeat", "When set, accept key-repeat events"); + RNA_def_boolean(func, "repeat", false, "Repeat", "When set, accept key-repeat events"); parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item"); RNA_def_function_return(func, parm); -- cgit v1.2.3 From c70650785bffb5f111c3c81c7c37dff4d5a9a446 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 22 Oct 2020 14:03:00 +1100 Subject: Fix out of bounds array access in mathutils.noise Regression in 0b2d1badecc48. --- source/blender/python/mathutils/mathutils_noise.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c index eece782f6d0..49a3f114ebb 100644 --- a/source/blender/python/mathutils/mathutils_noise.c +++ b/source/blender/python/mathutils/mathutils_noise.c @@ -140,11 +140,11 @@ static void next_state(void) left = N; next = state; - for (j = N - M + 1; j--; p++) { + for (j = N - M + 1; --j; p++) { *p = p[M] ^ TWIST(p[0], p[1]); } - for (j = M; j--; p++) { + for (j = M; --j; p++) { *p = p[M - N] ^ TWIST(p[0], p[1]); } -- cgit v1.2.3 From c53ac5e1c488628f75133df81d7f7484ec89ae9a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 22 Oct 2020 15:26:22 +1100 Subject: Fix T81939: crash calling bmesh.utils.vert_separate() Missing NULL check in bmesh_kernel_vert_separate. --- source/blender/bmesh/intern/bmesh_core.c | 86 ++++++++++++++++---------------- 1 file changed, 43 insertions(+), 43 deletions(-) (limited to 'source') diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index d5ebc73dc1e..df5e7aadc64 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2343,60 +2343,60 @@ void bmesh_kernel_vert_separate( BLI_assert(!BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT)); BM_ELEM_API_FLAG_ENABLE(e_iter, EDGE_VISIT); } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - } - - while (true) { - /* Considering only edges and faces incident on vertex v, walk - * the edges & collect in the 'edges' list for splitting */ - BMEdge *e = v->e; - BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT); + while (true) { + /* Considering only edges and faces incident on vertex v, walk + * the edges & collect in the 'edges' list for splitting */ - do { - BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)); - BLI_SMALLSTACK_PUSH(edges, e); - edges_found += 1; + BMEdge *e = v->e; + BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT); - if (e->l) { - BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - BMLoop *l_adjacent = (l_iter->v == v) ? l_iter->prev : l_iter->next; - BLI_assert(BM_vert_in_edge(l_adjacent->e, v)); - if (BM_ELEM_API_FLAG_TEST(l_adjacent->e, EDGE_VISIT)) { - BM_ELEM_API_FLAG_DISABLE(l_adjacent->e, EDGE_VISIT); - BLI_SMALLSTACK_PUSH(edges_search, l_adjacent->e); - } - } while ((l_iter = l_iter->radial_next) != l_first); - } - } while ((e = BLI_SMALLSTACK_POP(edges_search))); + do { + BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)); + BLI_SMALLSTACK_PUSH(edges, e); + edges_found += 1; + + if (e->l) { + BMLoop *l_iter, *l_first; + l_iter = l_first = e->l; + do { + BMLoop *l_adjacent = (l_iter->v == v) ? l_iter->prev : l_iter->next; + BLI_assert(BM_vert_in_edge(l_adjacent->e, v)); + if (BM_ELEM_API_FLAG_TEST(l_adjacent->e, EDGE_VISIT)) { + BM_ELEM_API_FLAG_DISABLE(l_adjacent->e, EDGE_VISIT); + BLI_SMALLSTACK_PUSH(edges_search, l_adjacent->e); + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + } while ((e = BLI_SMALLSTACK_POP(edges_search))); - /* now we have all edges connected to 'v->e' */ + /* now we have all edges connected to 'v->e' */ - BLI_assert(edges_found <= v_edges_num); + BLI_assert(edges_found <= v_edges_num); - if (edges_found == v_edges_num) { - /* We're done! The remaining edges in 'edges' form the last fan, - * which can be left as is. - * if 'edges' were alloc'd it'd be freed here. */ - break; - } + if (edges_found == v_edges_num) { + /* We're done! The remaining edges in 'edges' form the last fan, + * which can be left as is. + * if 'edges' were alloc'd it'd be freed here. */ + break; + } - BMVert *v_new; + BMVert *v_new; - v_new = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); - if (copy_select) { - BM_elem_select_copy(bm, v_new, v); - } + v_new = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); + if (copy_select) { + BM_elem_select_copy(bm, v_new, v); + } - while ((e = BLI_SMALLSTACK_POP(edges))) { - bmesh_edge_vert_swap(e, v_new, v); - } + while ((e = BLI_SMALLSTACK_POP(edges))) { + bmesh_edge_vert_swap(e, v_new, v); + } - if (r_vout) { - BLI_SMALLSTACK_PUSH(verts_new, v_new); + if (r_vout) { + BLI_SMALLSTACK_PUSH(verts_new, v_new); + } + verts_num += 1; } - verts_num += 1; } #undef EDGE_VISIT -- cgit v1.2.3 From a308607a53343d6652b4a27576a7a6bb6e8e67a0 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 21 Oct 2020 23:52:29 -0500 Subject: Cleanup: Use LISTBASE_FOREACH macro in curve code These changes should result in more readable and undestandable code, especially where while loops were use instead of for loops. They are not comprehensive, and I skipped wherever the change was not obvious. --- source/blender/blenkernel/intern/curve.c | 114 +++++----------- source/blender/blenkernel/intern/displist.c | 67 +++------- source/blender/editors/curve/editcurve.c | 199 +++++++++------------------- 3 files changed, 118 insertions(+), 262 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 1eb374d1a08..7e9ee1ad153 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -569,10 +569,9 @@ void BKE_curve_texspace_get(Curve *cu, float r_loc[3], float r_size[3]) bool BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3]) { - Nurb *nu; int tot = 0; - for (nu = nurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, nurb) { int tot_nu; if (nu->type == CU_BEZIER) { tot_nu = nu->pntsu; @@ -596,39 +595,33 @@ bool BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3]) int BKE_nurbList_verts_count(ListBase *nurb) { - Nurb *nu; int tot = 0; - nu = nurb->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nurb) { if (nu->bezt) { tot += 3 * nu->pntsu; } else if (nu->bp) { tot += nu->pntsu * nu->pntsv; } - - nu = nu->next; } + return tot; } int BKE_nurbList_verts_count_without_handles(ListBase *nurb) { - Nurb *nu; int tot = 0; - nu = nurb->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nurb) { if (nu->bezt) { tot += nu->pntsu; } else if (nu->bp) { tot += nu->pntsu * nu->pntsv; } - - nu = nu->next; } + return tot; } @@ -636,7 +629,6 @@ int BKE_nurbList_verts_count_without_handles(ListBase *nurb) void BKE_nurb_free(Nurb *nu) { - if (nu == NULL) { return; } @@ -664,17 +656,12 @@ void BKE_nurb_free(Nurb *nu) void BKE_nurbList_free(ListBase *lb) { - Nurb *nu, *next; - if (lb == NULL) { return; } - nu = lb->first; - while (nu) { - next = nu->next; + LISTBASE_FOREACH_MUTABLE (Nurb *, nu, lb) { BKE_nurb_free(nu); - nu = next; } BLI_listbase_clear(lb); } @@ -747,16 +734,11 @@ Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv) void BKE_nurbList_duplicate(ListBase *lb1, const ListBase *lb2) { - Nurb *nu, *nun; - BKE_nurbList_free(lb1); - nu = lb2->first; - while (nu) { - nun = BKE_nurb_duplicate(nu); - BLI_addtail(lb1, nun); - - nu = nu->next; + LISTBASE_FOREACH (const Nurb *, nu, lb2) { + Nurb *nurb_new = BKE_nurb_duplicate(nu); + BLI_addtail(lb1, nurb_new); } } @@ -2625,9 +2607,7 @@ static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl) void BKE_curve_bevelList_free(ListBase *bev) { - BevList *bl, *blnext; - for (bl = bev->first; bl != NULL; bl = blnext) { - blnext = bl->next; + LISTBASE_FOREACH_MUTABLE (BevList *, bl, bev) { if (bl->seglen != NULL) { MEM_freeN(bl->seglen); } @@ -2654,10 +2634,9 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) /* this function needs an object, because of tflag and upflag */ Curve *cu = ob->data; - Nurb *nu; BezTriple *bezt, *prevbezt; BPoint *bp; - BevList *bl, *blnew, *blnext; + BevList *blnew; BevPoint *bevp2, *bevp1 = NULL, *bevp0; const float treshold = 0.00001f; float min, inp; @@ -2685,12 +2664,11 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) /* STEP 1: MAKE POLYS */ BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev); - nu = nurbs->first; if (cu->editnurb && ob->type != OB_FONT) { is_editmode = 1; } - for (; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, nurbs) { if (nu->hide && is_editmode) { continue; } @@ -2706,7 +2684,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) /* check we are a single point? also check we are not a surface and that the orderu is sane, * enforced in the UI but can go wrong possibly */ if (!BKE_nurb_check_valid_u(nu)) { - bl = MEM_callocN(sizeof(BevList), "makeBevelList1"); + BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList1"); bl->bevpoints = MEM_calloc_arrayN(1, sizeof(BevPoint), "makeBevelPoints1"); BLI_addtail(bev, bl); bl->nr = 0; @@ -2726,7 +2704,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) if (nu->type == CU_POLY) { len = nu->pntsu; - bl = MEM_callocN(sizeof(BevList), "makeBevelList2"); + BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList2"); bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints2"); if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList2_seglen"); @@ -2777,7 +2755,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) /* in case last point is not cyclic */ len = segcount * resolu + 1; - bl = MEM_callocN(sizeof(BevList), "makeBevelBPoints"); + BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelBPoints"); bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelBPointsPoints"); if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelBPoints_seglen"); @@ -2930,7 +2908,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) if (nu->pntsv == 1) { len = (resolu * segcount); - bl = MEM_callocN(sizeof(BevList), "makeBevelList3"); + BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList3"); bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints3"); if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList3_seglen"); @@ -2989,8 +2967,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) } /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */ - bl = bev->first; - while (bl) { + LISTBASE_FOREACH (BevList *, bl, bev) { if (bl->nr) { /* null bevel items come from single points */ bool is_cyclic = bl->poly != -1; nr = bl->nr; @@ -3025,11 +3002,9 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) bevp1++; } } - bl = bl->next; } - bl = bev->first; - while (bl) { - blnext = bl->next; + + LISTBASE_FOREACH_MUTABLE (BevList *, bl, bev) { if (bl->nr && bl->dupe_nr) { nr = bl->nr - bl->dupe_nr + 1; /* +1 because vectorbezier sets flag too */ blnew = MEM_mallocN(sizeof(BevList), "makeBevelList4"); @@ -3043,7 +3018,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) blnew->seglen = bl->seglen; blnew->nr = 0; BLI_remlink(bev, bl); - BLI_insertlinkbefore(bev, blnext, blnew); /* to make sure bevlijst is tuned with nurblist */ + BLI_insertlinkbefore(bev, bl->next, blnew); /* to make sure bevlist is tuned with nurblist */ bevp0 = bl->bevpoints; bevp1 = blnew->bevpoints; nr = bl->nr; @@ -3061,26 +3036,22 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) MEM_freeN(bl); blnew->dupe_nr = 0; } - bl = blnext; } /* STEP 3: POLYS COUNT AND AUTOHOLE */ - bl = bev->first; poly = 0; - while (bl) { + LISTBASE_FOREACH (BevList *, bl, bev) { if (bl->nr && bl->poly >= 0) { poly++; bl->poly = poly; bl->hole = 0; } - bl = bl->next; } /* find extreme left points, also test (turning) direction */ if (poly > 0) { sd = sortdata = MEM_malloc_arrayN(poly, sizeof(struct BevelSort), "makeBevelList5"); - bl = bev->first; - while (bl) { + LISTBASE_FOREACH (BevList *, bl, bev) { if (bl->poly > 0) { BevPoint *bevp; @@ -3125,14 +3096,12 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) sd++; } - - bl = bl->next; } qsort(sortdata, poly, sizeof(struct BevelSort), vergxcobev); sd = sortdata + 1; for (a = 1; a < poly; a++, sd++) { - bl = sd->bl; /* is bl a hole? */ + BevList *bl = sd->bl; /* is bl a hole? */ sd1 = sortdata + (a - 1); for (b = a - 1; b >= 0; b--, sd1--) { /* all polys to the left */ if (sd1->bl->charidx == bl->charidx) { /* for text, only check matching char */ @@ -3149,7 +3118,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) sd = sortdata; for (a = 0; a < poly; a++, sd++) { if (sd->bl->hole == sd->dir) { - bl = sd->bl; + BevList *bl = sd->bl; bevp1 = bl->bevpoints; bevp2 = bevp1 + (bl->nr - 1); nr = bl->nr / 2; @@ -3167,7 +3136,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) /* STEP 4: 2D-COSINES or 3D ORIENTATION */ if ((cu->flag & CU_3D) == 0) { /* 2D Curves */ - for (bl = bev->first; bl; bl = bl->next) { + LISTBASE_FOREACH (BevList *, bl, bev) { if (bl->nr < 2) { BevPoint *bevp = bl->bevpoints; unit_qt(bevp->quat); @@ -3182,7 +3151,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) } else { /* 3D Curves */ - for (bl = bev->first; bl; bl = bl->next) { + LISTBASE_FOREACH (BevList *, bl, bev) { if (bl->nr < 2) { BevPoint *bevp = bl->bevpoints; unit_qt(bevp->quat); @@ -4316,12 +4285,8 @@ void BKE_nurb_handles_autocalc(Nurb *nu, uint8_t flag) void BKE_nurbList_handles_autocalc(ListBase *editnurb, uint8_t flag) { - Nurb *nu; - - nu = editnurb->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { BKE_nurb_handles_autocalc(nu, flag); - nu = nu->next; } } @@ -4333,13 +4298,11 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) /* code==4: sets icu flag to become IPO_AUTO_HORIZ, horizontal extremes on auto-handles */ /* code==5: Set align, like 3 but no toggle */ /* code==6: Clear align, like 3 but no toggle */ - Nurb *nu; BezTriple *bezt; int a; if (ELEM(code, HD_AUTO, HD_VECT)) { - nu = editnurb->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -4366,7 +4329,6 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) /* like BKE_nurb_handles_calc but moves selected */ nurb_handles_calc__align_selected(nu); } - nu = nu->next; } } else { @@ -4381,7 +4343,7 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) } else { /* Toggle */ - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -4397,7 +4359,7 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) } h_new = (h_new == HD_FREE) ? HD_ALIGN : HD_FREE; } - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -4423,11 +4385,10 @@ void BKE_nurbList_handles_recalculate(ListBase *editnurb, const bool calc_length, const uint8_t flag) { - Nurb *nu; BezTriple *bezt; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bool changed = false; @@ -4477,12 +4438,11 @@ void BKE_nurbList_handles_recalculate(ListBase *editnurb, void BKE_nurbList_flag_set(ListBase *editnurb, uint8_t flag, bool set) { - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { a = nu->pntsu; bezt = nu->bezt; @@ -4518,7 +4478,7 @@ bool BKE_nurbList_flag_set_from_flag(ListBase *editnurb, uint8_t from_flag, uint { bool changed = false; - for (Nurb *nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { for (int i = 0; i < nu->pntsu; i++) { BezTriple *bezt = &nu->bezt[i]; @@ -5232,12 +5192,11 @@ bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3]) bool BKE_curve_center_median(Curve *cu, float cent[3]) { ListBase *nurb_lb = BKE_curve_nurbs_get(cu); - Nurb *nu; int total = 0; zero_v3(cent); - for (nu = nurb_lb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, nurb_lb) { int i; if (nu->type == CU_BEZIER) { @@ -5285,12 +5244,11 @@ void BKE_curve_transform_ex(Curve *cu, const bool do_props, const float unit_scale) { - Nurb *nu; BPoint *bp; BezTriple *bezt; int i; - for (nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { if (nu->type == CU_BEZIER) { i = nu->pntsu; for (bezt = nu->bezt; i--; bezt++) { @@ -5320,7 +5278,7 @@ void BKE_curve_transform_ex(Curve *cu, float *fp = kb->data; int n = kb->totelem; - for (nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { if (nu->type == CU_BEZIER) { for (i = nu->pntsu; i && (n -= KEYELEM_ELEM_LEN_BEZTRIPLE) >= 0; i--) { mul_m4_v3(mat, &fp[0]); diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index bcb467e1230..f47f350a435 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -92,17 +92,13 @@ void BKE_displist_free(ListBase *lb) DispList *BKE_displist_find_or_create(ListBase *lb, int type) { - DispList *dl; - - dl = lb->first; - while (dl) { + LISTBASE_FOREACH (DispList *, dl, lb) { if (dl->type == type) { return dl; } - dl = dl->next; } - dl = MEM_callocN(sizeof(DispList), "find_disp"); + DispList *dl = MEM_callocN(sizeof(DispList), "find_disp"); dl->type = type; BLI_addtail(lb, dl); @@ -111,14 +107,10 @@ DispList *BKE_displist_find_or_create(ListBase *lb, int type) DispList *BKE_displist_find(ListBase *lb, int type) { - DispList *dl; - - dl = lb->first; - while (dl) { + LISTBASE_FOREACH (DispList *, dl, lb) { if (dl->type == type) { return dl; } - dl = dl->next; } return NULL; @@ -126,9 +118,7 @@ DispList *BKE_displist_find(ListBase *lb, int type) bool BKE_displist_has_faces(ListBase *lb) { - DispList *dl; - - for (dl = lb->first; dl; dl = dl->next) { + LISTBASE_FOREACH (DispList *, dl, lb) { if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) { return true; } @@ -139,13 +129,10 @@ bool BKE_displist_has_faces(ListBase *lb) void BKE_displist_copy(ListBase *lbn, ListBase *lb) { - DispList *dln, *dl; - BKE_displist_free(lbn); - dl = lb->first; - while (dl) { - dln = MEM_dupallocN(dl); + LISTBASE_FOREACH (const DispList *, dl, lb) { + DispList *dln = MEM_dupallocN(dl); BLI_addtail(lbn, dln); dln->verts = MEM_dupallocN(dl->verts); dln->nors = MEM_dupallocN(dl->nors); @@ -154,22 +141,18 @@ void BKE_displist_copy(ListBase *lbn, ListBase *lb) if (dl->bevel_split) { dln->bevel_split = MEM_dupallocN(dl->bevel_split); } - - dl = dl->next; } } void BKE_displist_normals_add(ListBase *lb) { - DispList *dl = NULL; float *vdata, *ndata, nor[3]; float *v1, *v2, *v3, *v4; float *n1, *n2, *n3, *n4; int a, b, p1, p2, p3, p4; - dl = lb->first; + LISTBASE_FOREACH (DispList *, dl, lb) { - while (dl) { if (dl->type == DL_INDEX3) { if (dl->nors == NULL) { dl->nors = MEM_callocN(sizeof(float[3]), "dlnors"); @@ -230,15 +213,12 @@ void BKE_displist_normals_add(ListBase *lb) } } } - dl = dl->next; } } void BKE_displist_count(ListBase *lb, int *totvert, int *totface, int *tottri) { - DispList *dl; - - for (dl = lb->first; dl; dl = dl->next) { + LISTBASE_FOREACH (DispList *, dl, lb) { int vert_tot = 0; int face_tot = 0; int tri_tot = 0; @@ -318,7 +298,6 @@ static void curve_to_displist(Curve *cu, ListBase *dispbase, const bool for_render) { - Nurb *nu; DispList *dl; BezTriple *bezt, *prevbezt; BPoint *bp; @@ -326,8 +305,7 @@ static void curve_to_displist(Curve *cu, int a, len, resolu; const bool editmode = (!for_render && (cu->editnurb || cu->editfont)); - nu = nubase->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nubase) { if (nu->hide == 0 || editmode == false) { if (for_render && cu->resolu_ren != 0) { resolu = cu->resolu_ren; @@ -473,7 +451,6 @@ static void curve_to_displist(Curve *cu, } } } - nu = nu->next; } } @@ -627,19 +604,14 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) { const float z_up[3] = {0.0f, 0.0f, -1.0f}; ListBase front, back; - DispList *dl, *dlnew; float *fp, *fp1; int a, dpoly; - BLI_listbase_clear(&front); - BLI_listbase_clear(&back); - - dl = dispbase->first; - while (dl) { + LISTBASE_FOREACH (DispList *, dl, dispbase) { if (dl->type == DL_SURF) { if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U) == 0) { if ((cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE)) { - dlnew = MEM_callocN(sizeof(DispList), "filldisp"); + DispList *dlnew = MEM_callocN(sizeof(DispList), "filldisp"); BLI_addtail(&front, dlnew); dlnew->verts = fp1 = MEM_mallocN(sizeof(float[3]) * dl->parts, "filldisp1"); dlnew->nr = dl->parts; @@ -660,7 +632,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) } } if ((cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE)) { - dlnew = MEM_callocN(sizeof(DispList), "filldisp"); + DispList *dlnew = MEM_callocN(sizeof(DispList), "filldisp"); BLI_addtail(&back, dlnew); dlnew->verts = fp1 = MEM_mallocN(sizeof(float[3]) * dl->parts, "filldisp1"); dlnew->nr = dl->parts; @@ -682,7 +654,6 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) } } } - dl = dl->next; } BKE_displist_fill(&front, dispbase, z_up, true); @@ -939,18 +910,17 @@ static bool curve_calc_modifiers_pre( static float (*displist_vert_coords_alloc(ListBase *dispbase, int *r_vert_len))[3] { - DispList *dl; float(*allverts)[3], *fp; *r_vert_len = 0; - for (dl = dispbase->first; dl; dl = dl->next) { + LISTBASE_FOREACH (DispList *, dl, dispbase) { *r_vert_len += (dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr; } allverts = MEM_mallocN(sizeof(float[3]) * (*r_vert_len), "displist_vert_coords_alloc allverts"); fp = (float *)allverts; - for (dl = dispbase->first; dl; dl = dl->next) { + LISTBASE_FOREACH (DispList *, dl, dispbase) { int offs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr); memcpy(fp, dl->verts, sizeof(float) * offs); fp += offs; @@ -961,11 +931,10 @@ static float (*displist_vert_coords_alloc(ListBase *dispbase, int *r_vert_len))[ static void displist_vert_coords_apply(ListBase *dispbase, float (*allverts)[3]) { - DispList *dl; const float *fp; fp = (float *)allverts; - for (dl = dispbase->first; dl; dl = dl->next) { + LISTBASE_FOREACH (DispList *, dl, dispbase) { int offs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr); memcpy(dl->verts, fp, sizeof(float) * offs); fp += offs; @@ -1218,7 +1187,6 @@ void BKE_displist_make_surf(Depsgraph *depsgraph, const bool for_orco) { ListBase nubase = {NULL, NULL}; - Nurb *nu; Curve *cu = ob->data; DispList *dl; float *data; @@ -1236,7 +1204,7 @@ void BKE_displist_make_surf(Depsgraph *depsgraph, force_mesh_conversion = curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render); } - for (nu = nubase.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &nubase) { if ((for_render || nu->hide == 0) && BKE_nurb_check_valid_uv(nu)) { int resolu = nu->resolu, resolv = nu->resolv; @@ -1851,12 +1819,11 @@ void BKE_displist_make_curveTypes_forRender(Depsgraph *depsgraph, void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3]) { - DispList *dl; const float *vert; int a, tot = 0; int doit = 0; - for (dl = dispbase->first; dl; dl = dl->next) { + LISTBASE_FOREACH (DispList *, dl, dispbase) { tot = (dl->type == DL_INDEX3) ? dl->nr : dl->nr * dl->parts; vert = dl->verts; for (a = 0; a < tot; a++, vert += 3) { diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 85d86849140..49c75e0b4a1 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -476,19 +476,15 @@ static void keyIndex_switchDirection(EditNurb *editnurb, Nurb *nu) static void switch_keys_direction(Curve *cu, Nurb *actnu) { - KeyBlock *currkey; EditNurb *editnurb = cu->editnurb; ListBase *nubase = &editnurb->nurbs; - Nurb *nu; float *fp; int a; - currkey = cu->key->block.first; - while (currkey) { + LISTBASE_FOREACH (KeyBlock *, currkey, &cu->key->block) { fp = currkey->data; - nu = nubase->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nubase) { if (nu->bezt) { BezTriple *bezt = nu->bezt; a = nu->pntsu; @@ -522,11 +518,7 @@ static void switch_keys_direction(Curve *cu, Nurb *actnu) fp += a * KEYELEM_FLOAT_LEN_BPOINT; } } - - nu = nu->next; } - - currkey = currkey->next; } } @@ -583,13 +575,11 @@ static void bezt_to_key(BezTriple *bezt, float *key) static void calc_keyHandles(ListBase *nurb, float *key) { - Nurb *nu; int a; float *fp = key; BezTriple *bezt; - nu = nurb->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nurb) { if (nu->bezt) { BezTriple *prevp, *nextp; BezTriple cur, prev, next; @@ -649,8 +639,6 @@ static void calc_keyHandles(ListBase *nurb, float *key) a = nu->pntsu * nu->pntsv; fp += a * KEYELEM_FLOAT_LEN_BPOINT; } - - nu = nu->next; } } @@ -666,7 +654,7 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs) KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1); BezTriple *bezt, *oldbezt; BPoint *bp, *oldbp; - Nurb *nu, *newnu; + Nurb *newnu; int totvert = BKE_keyblock_curve_element_count(&editnurb->nurbs); float(*ofs)[3] = NULL; @@ -678,8 +666,8 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs) int totvec = 0; /* Calculate needed memory to store offset */ - nu = editnurb->nurbs.first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { + if (nu->bezt) { /* Three vects to store handles and one for tilt. */ totvec += nu->pntsu * 4; @@ -687,14 +675,11 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs) else { totvec += 2 * nu->pntsu * nu->pntsv; } - - nu = nu->next; } ofs = MEM_callocN(sizeof(float[3]) * totvec, "currkey->data"); - nu = editnurb->nurbs.first; i = 0; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (nu->bezt) { bezt = nu->bezt; a = nu->pntsu; @@ -731,8 +716,6 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs) bp++; } } - - nu = nu->next; } } } @@ -745,7 +728,7 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs) float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert, "currkey->data"); ofp = oldkey = currkey->data; - nu = editnurb->nurbs.first; + Nurb *nu = editnurb->nurbs.first; /* We need to restore to original curve into newnurb, *not* editcurve's nurbs. * Otherwise, in case we update obdata *without* leaving editmode (e.g. viewport render), * we would invalidate editcurve. */ @@ -929,11 +912,10 @@ static void fcurve_path_rename(AnimData *adt, ListBase *orig_curves, ListBase *curves) { - FCurve *fcu, *nfcu, *nextfcu; + FCurve *nfcu; int len = strlen(orig_rna_path); - for (fcu = orig_curves->first; fcu; fcu = nextfcu) { - nextfcu = fcu->next; + LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, orig_curves) { if (STREQLEN(fcu->rna_path, orig_rna_path, len)) { char *spath, *suffix = fcu->rna_path + len; nfcu = BKE_fcurve_copy(fcu); @@ -977,16 +959,15 @@ static void fcurve_remove(AnimData *adt, ListBase *orig_curves, FCurve *fcu) static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) { - int nu_index = 0, a, pt_index; + int a, pt_index; EditNurb *editnurb = cu->editnurb; - Nurb *nu; CVKeyIndex *keyIndex; char rna_path[64], orig_rna_path[64]; AnimData *adt = BKE_animdata_from_id(&cu->id); ListBase curves = {NULL, NULL}; - FCurve *fcu, *next; - for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) { + int nu_index = 0; + LISTBASE_FOREACH_INDEX (Nurb *, nu, &editnurb->nurbs, nu_index) { if (nu->bezt) { BezTriple *bezt = nu->bezt; a = nu->pntsu; @@ -1054,9 +1035,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) /* remove paths for removed control points * need this to make further step with copying non-cv related curves copying * not touching cv's f-curves */ - for (fcu = orig_curves->first; fcu; fcu = next) { - next = fcu->next; - + LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, orig_curves) { if (STREQLEN(fcu->rna_path, "splines", 7)) { const char *ch = strchr(fcu->rna_path, '.'); @@ -1066,7 +1045,8 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) } } - for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) { + nu_index = 0; + LISTBASE_FOREACH_INDEX (Nurb *, nu, &editnurb->nurbs, nu_index) { keyIndex = NULL; if (nu->pntsu) { if (nu->bezt) { @@ -1086,9 +1066,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) /* the remainders in orig_curves can be copied back (like follow path) */ /* (if it's not path to spline) */ - for (fcu = orig_curves->first; fcu; fcu = next) { - next = fcu->next; - + LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, orig_curves) { if (STREQLEN(fcu->rna_path, "splines", 7)) { fcurve_remove(adt, orig_curves, fcu); } @@ -1141,13 +1119,11 @@ static int *init_index_map(Object *obedit, int *r_old_totvert) { Curve *curve = (Curve *)obedit->data; EditNurb *editnurb = curve->editnurb; - Nurb *nu; CVKeyIndex *keyIndex; int *old_to_new_map; - int old_totvert; - int vertex_index; - for (nu = curve->nurb.first, old_totvert = 0; nu != NULL; nu = nu->next) { + int old_totvert = 0; + LISTBASE_FOREACH (Nurb *, nu, &curve->nurb) { if (nu->bezt) { old_totvert += nu->pntsu * 3; } @@ -1161,7 +1137,8 @@ static int *init_index_map(Object *obedit, int *r_old_totvert) old_to_new_map[i] = -1; } - for (nu = editnurb->nurbs.first, vertex_index = 0; nu != NULL; nu = nu->next) { + int vertex_index = 0; + LISTBASE_FOREACH (Nurb *, nu, &curve->nurb) { if (nu->bezt) { BezTriple *bezt = nu->bezt; int a = nu->pntsu; @@ -1205,7 +1182,6 @@ static int *init_index_map(Object *obedit, int *r_old_totvert) static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit) { - Object *object; Curve *curve = (Curve *)obedit->data; EditNurb *editnurb = curve->editnurb; int *old_to_new_map = NULL; @@ -1219,8 +1195,7 @@ static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit) return; } - for (object = bmain->objects.first; object; object = object->id.next) { - ModifierData *md; + LISTBASE_FOREACH (Object *, object, &bmain->objects) { int index; if ((object->parent) && (object->parent->data == curve) && ELEM(object->partype, PARVERT1, PARVERT3)) { @@ -1248,7 +1223,7 @@ static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit) } } if (object->data == curve) { - for (md = object->modifiers.first; md; md = md->next) { + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { if (md->type == eModifierType_Hook) { HookModifierData *hmd = (HookModifierData *)md; int i, j; @@ -1290,13 +1265,12 @@ void ED_curve_editnurb_load(Main *bmain, Object *obedit) if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { Curve *cu = obedit->data; - Nurb *nu, *newnu; ListBase newnurb = {NULL, NULL}, oldnurb = cu->nurb; remap_hooks_and_vertex_parents(bmain, obedit); - for (nu = editnurb->first; nu; nu = nu->next) { - newnu = BKE_nurb_duplicate(nu); + LISTBASE_FOREACH (Nurb *, nu, editnurb) { + Nurb *newnu = BKE_nurb_duplicate(nu); BLI_addtail(&newnurb, newnu); if (nu->type == CU_NURBS) { @@ -1323,7 +1297,6 @@ void ED_curve_editnurb_make(Object *obedit) { Curve *cu = (Curve *)obedit->data; EditNurb *editnurb = cu->editnurb; - Nurb *nu, *newnu; KeyBlock *actkey; if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { @@ -1346,12 +1319,10 @@ void ED_curve_editnurb_make(Object *obedit) cu->editnurb = editnurb; } - nu = cu->nurb.first; - while (nu) { - newnu = BKE_nurb_duplicate(nu); + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { + Nurb *newnu = BKE_nurb_duplicate(nu); BKE_nurb_test_2d(newnu); /* after join, or any other creation of curve */ BLI_addtail(&editnurb->nurbs, newnu); - nu = nu->next; } /* animation could be added in editmode even if there was no animdata in @@ -1722,11 +1693,10 @@ static void rotateflagNurb(ListBase *editnurb, const float rotmat[3][3]) { /* all verts with (flag & 'flag') rotate */ - Nurb *nu; BPoint *bp; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_NURBS) { bp = nu->bp; a = nu->pntsu * nu->pntsv; @@ -1746,12 +1716,11 @@ static void rotateflagNurb(ListBase *editnurb, void ed_editnurb_translate_flag(ListBase *editnurb, uint8_t flag, const float vec[3]) { /* all verts with ('flag' & flag) translate */ - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { a = nu->pntsu; bezt = nu->bezt; @@ -1785,11 +1754,10 @@ void ed_editnurb_translate_flag(ListBase *editnurb, uint8_t flag, const float ve static void weightflagNurb(ListBase *editnurb, short flag, float w) { - Nurb *nu; BPoint *bp; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_NURBS) { a = nu->pntsu * nu->pntsv; bp = nu->bp; @@ -1808,16 +1776,12 @@ static void ed_surf_delete_selected(Object *obedit) { Curve *cu = obedit->data; ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu, *next; BPoint *bp, *bpn, *newbp; int a, b, newu, newv; BLI_assert(obedit->type == OB_SURF); - nu = editnurb->first; - while (nu) { - next = nu->next; - + LISTBASE_FOREACH_MUTABLE (Nurb *, nu, editnurb) { /* is entire nurb selected */ bp = nu->bp; a = nu->pntsu * nu->pntsv; @@ -1903,7 +1867,6 @@ static void ed_surf_delete_selected(Object *obedit) } } } - nu = next; } } @@ -1912,15 +1875,12 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d) Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; ListBase *nubase = &editnurb->nurbs; - Nurb *nu, *next; BezTriple *bezt, *bezt1; BPoint *bp, *bp1; int a, type, nuindex = 0; /* first loop, can we remove entire pieces? */ - nu = nubase->first; - while (nu) { - next = nu->next; + LISTBASE_FOREACH_MUTABLE (Nurb *, nu, nubase) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -1981,13 +1941,10 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d) clamp_nurb_order_u(nu); } #endif - nu = next; nuindex++; } /* 2nd loop, delete small pieces: just for curves */ - nu = nubase->first; - while (nu) { - next = nu->next; + LISTBASE_FOREACH_MUTABLE (Nurb *, nu, nubase) { type = 0; if (nu->type == CU_BEZIER) { bezt = nu->bezt; @@ -2047,21 +2004,17 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d) BKE_nurb_order_clamp_u(nu); BKE_nurb_knot_calc_u(nu); } - nu = next; } } /* only for OB_SURF */ bool ed_editnurb_extrude_flag(EditNurb *editnurb, const uint8_t flag) { - Nurb *nu; BPoint *bp, *bpn, *newbp; int a, u, v, len; bool ok = false; - nu = editnurb->nurbs.first; - while (nu) { - + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (nu->pntsv == 1) { bp = nu->bp; a = nu->pntsu; @@ -2166,7 +2119,6 @@ bool ed_editnurb_extrude_flag(EditNurb *editnurb, const uint8_t flag) } } } - nu = nu->next; } return ok; @@ -2197,14 +2149,15 @@ static void adduplicateflagNurb( Object *obedit, View3D *v3d, ListBase *newnurb, const uint8_t flag, const bool split) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu, *newnu; + Nurb *newnu; BezTriple *bezt, *bezt1; BPoint *bp, *bp1, *bp2, *bp3; Curve *cu = (Curve *)obedit->data; - int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv, i; + int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv; char *usel; - for (i = 0, nu = editnurb->first; nu; i++, nu = nu->next) { + int i = 0; + LISTBASE_FOREACH_INDEX (Nurb *, nu, editnurb, i) { cyclicu = cyclicv = 0; if (nu->type == CU_BEZIER) { for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) { @@ -2569,7 +2522,7 @@ static void adduplicateflagNurb( } if (BLI_listbase_is_empty(newnurb) == false) { - for (nu = newnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, newnurb) { if (nu->type == CU_BEZIER) { if (split) { /* recalc first and last */ @@ -2619,10 +2572,9 @@ static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) } EditNurb *editnurb = cu->editnurb; - Nurb *nu; - int i; - for (nu = editnurb->nurbs.first, i = 0; nu; nu = nu->next, i++) { + int i = 0; + LISTBASE_FOREACH_INDEX (Nurb *, nu, &editnurb->nurbs, i) { if (ED_curve_nurb_select_check(v3d, nu)) { BKE_nurb_direction_switch(nu); keyData_switchDirectionNurb(cu, nu); @@ -2674,13 +2626,12 @@ static int set_goal_weight_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BezTriple *bezt; BPoint *bp; float weight = RNA_float_get(op->ptr, "weight"); int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->bezt) { for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { if (bezt->f2 & SELECT) { @@ -2741,13 +2692,12 @@ static int set_radius_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BezTriple *bezt; BPoint *bp; float radius = RNA_float_get(op->ptr, "radius"); int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->bezt) { for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { if (bezt->f2 & SELECT) { @@ -2853,12 +2803,11 @@ static int smooth_exec(bContext *C, wmOperator *UNUSED(op)) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; int a, a_end; bool changed = false; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->bezt) { /* duplicate the curve to use in weight calculation */ const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt); @@ -2960,7 +2909,6 @@ void CURVE_OT_smooth(wmOperatorType *ot) static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, const int bp_offset) { - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; @@ -2970,7 +2918,7 @@ static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, cons int start_sel, end_sel; /* selection indices, inclusive */ float start_rad, end_rad, fac, range; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->bezt) { #define BEZT_VALUE(bezt) (*((float *)((char *)(bezt) + bezt_offsetof))) @@ -3289,12 +3237,11 @@ static int hide_exec(bContext *C, wmOperator *op) } ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; int a, sel; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -3385,13 +3332,12 @@ static int reveal_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; int a; bool changed = false; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { nu->hide = 0; if (nu->type == CU_BEZIER) { bezt = nu->bezt; @@ -3462,7 +3408,6 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts) { Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; - Nurb *nu; BezTriple *bezt, *beztnew, *beztn; BPoint *bp, *prevbp, *bpnew, *bpn; float vec[15]; @@ -3471,7 +3416,7 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts) // printf("*** subdivideNurb: entering subdivide\n"); - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { amount = 0; if (nu->type == CU_BEZIER) { BezTriple *nextbezt; @@ -3925,7 +3870,6 @@ static int set_spline_type_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); View3D *v3d = CTX_wm_view3d(C); ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; bool changed = false; bool changed_size = false; const bool use_handles = RNA_boolean_get(op->ptr, "use_handles"); @@ -3936,7 +3880,7 @@ static int set_spline_type_exec(bContext *C, wmOperator *op) continue; } - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (ED_curve_nurb_select_check(v3d, nu)) { const int pntsu_prev = nu->pntsu; const char *err_msg = NULL; @@ -4225,12 +4169,11 @@ static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb, ListBase * { ListBase nbase = {NULL, NULL}; NurbSort *nus, *nustest, *headdo, *taildo; - Nurb *nu; BPoint *bp; float dist, headdist, taildist; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (ED_curve_nurb_select_check(v3d, nu)) { nus = (NurbSort *)MEM_callocN(sizeof(NurbSort), "sort"); @@ -4996,7 +4939,6 @@ bool ed_editnurb_spin( { Curve *cu = (Curve *)obedit->data; ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; float cmat[3][3], tmat[3][3], imat[3][3]; float bmat[3][3], rotmat[3][3], scalemat1[3][3], scalemat2[3][3]; float persmat[3][3], persinv[3][3]; @@ -5056,7 +4998,7 @@ bool ed_editnurb_spin( } if (ok) { - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (ED_curve_nurb_select_check(v3d, nu)) { nu->orderv = 4; nu->flagv |= CU_NURB_CYCLIC; @@ -5427,8 +5369,6 @@ static int ed_editcurve_addvert(Curve *cu, View3D *v3d, const float location_init[3]) { - Nurb *nu; - float center[3]; float temp[3]; uint verts_len; @@ -5437,7 +5377,7 @@ static int ed_editcurve_addvert(Curve *cu, zero_v3(center); verts_len = 0; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { int i; if (nu->type == CU_BEZIER) { BezTriple *bezt; @@ -5472,7 +5412,7 @@ static int ed_editcurve_addvert(Curve *cu, ofs[2] = 0.0f; } - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (nu->type == CU_BEZIER) { BezTriple *bezt; for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) { @@ -5511,7 +5451,7 @@ static int ed_editcurve_addvert(Curve *cu, } /* nothing selected: create a new curve */ - nu = BKE_curve_nurb_active_get(cu); + Nurb *nu = BKE_curve_nurb_active_get(cu); if (!nu || nu->type == CU_BEZIER) { Nurb *nurb_new; @@ -5764,8 +5704,7 @@ static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op)) /* First test: curve? */ if (obedit->type != OB_CURVE) { - Nurb *nu; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if ((nu->pntsv == 1) && (ED_curve_nurb_select_count(v3d, nu) == 1)) { as_curve = true; break; @@ -5819,13 +5758,12 @@ void CURVE_OT_extrude(wmOperatorType *ot) static bool curve_toggle_cyclic(View3D *v3d, ListBase *editnurb, int direction) { - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; bool changed = false; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->pntsu > 1 || nu->pntsv > 1) { if (nu->type == CU_POLY) { a = nu->pntsu; @@ -5932,10 +5870,9 @@ static int toggle_cyclic_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS ListBase *editnurb = object_editcurve_get(obedit); uiPopupMenu *pup; uiLayout *layout; - Nurb *nu; if (obedit->type == OB_SURF) { - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->pntsu > 1 || nu->pntsv > 1) { if (nu->type == CU_NURBS) { pup = UI_popup_menu_begin(C, IFACE_("Direction"), ICON_NONE); @@ -6064,12 +6001,12 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; ListBase *nubase = &editnurb->nurbs, newnurb = {NULL, NULL}; - Nurb *nu, *nu1; + Nurb *nu1; BezTriple *bezt, *bezt1, *bezt2; BPoint *bp, *bp1, *bp2; int a, b, starta, enda, cut, cyclicut; - for (nu = nubase->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, nubase) { nu1 = NULL; starta = enda = cut = -1; cyclicut = 0; @@ -6452,7 +6389,7 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) } } - for (nu = newnurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &newnurb) { if (nu->type == CU_BEZIER) { if (split) { /* deselect for split operator */ @@ -6620,9 +6557,8 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) } ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if ((nu->type == CU_BEZIER) && (nu->pntsu > 2)) { uint span_step[2] = {nu->pntsu, nu->pntsu}; uint span_len; @@ -6766,9 +6702,8 @@ static int curve_decimate_exec(bContext *C, wmOperator *op) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { if ((nu->pntsu > 2) && nurb_bezt_flag_any(nu, SELECT)) { const int error_target_len = max_ii(2, nu->pntsu * ratio); @@ -6917,7 +6852,6 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *ob_active = CTX_data_active_object(C); Curve *cu; - Nurb *nu, *newnu; BezTriple *bezt; BPoint *bp; ListBase tempbase; @@ -6955,9 +6889,8 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op) /* watch it: switch order here really goes wrong */ mul_m4_m4m4(cmat, imat, ob_iter->obmat); - nu = cu->nurb.first; - while (nu) { - newnu = BKE_nurb_duplicate(nu); + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { + Nurb *newnu = BKE_nurb_duplicate(nu); if (ob_active->totcol) { /* TODO, merge material lists */ CLAMP(newnu->mat_nr, 0, ob_active->totcol - 1); } @@ -6983,7 +6916,6 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op) bp++; } } - nu = nu->next; } } @@ -7035,12 +6967,11 @@ static int clear_tilt_exec(bContext *C, wmOperator *UNUSED(op)) } ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->bezt) { bezt = nu->bezt; a = nu->pntsu; -- cgit v1.2.3 From 7ddc49ad34acc21dc69ca82c9913234033f7c209 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 22 Oct 2020 15:46:31 +1100 Subject: Fix T81905: Active keyframe unavailable when handle selected Selecting an F-Curve handle caused an assertion as well as treating the key-frame as inactive. Allow active the keyframe to be active when it's handle is selected, as is done with bezier curves. --- source/blender/blenkernel/intern/fcurve.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index fafcbaec10f..dcf4c78dfd8 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -842,7 +842,8 @@ bool BKE_fcurve_calc_range( void BKE_fcurve_active_keyframe_set(FCurve *fcu, const BezTriple *active_bezt) { /* The active keyframe should always be selected. */ - BLI_assert(active_bezt == NULL || (active_bezt->f2 & SELECT)); + BLI_assert((active_bezt == NULL) || + ((active_bezt->f1 | active_bezt->f2 | active_bezt->f3) & SELECT)); fcu->active_keyframe_index = (active_bezt == NULL) ? FCURVE_ACTIVE_KEYFRAME_NONE : active_bezt - fcu->bezt; } @@ -861,7 +862,7 @@ int BKE_fcurve_active_keyframe_index(const FCurve *fcu) } const BezTriple *active_bezt = &fcu->bezt[active_keyframe_index]; - if ((active_bezt->f2 & SELECT) == 0) { + if (((active_bezt->f1 | active_bezt->f2 | active_bezt->f3) & SELECT) == 0) { /* The active keyframe should always be selected. If it's not selected, it can't be active. */ return FCURVE_ACTIVE_KEYFRAME_NONE; } -- cgit v1.2.3 From 9ea345d1cf82f0770d7bb90ccac4bc6df00f9a94 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 22 Oct 2020 17:07:56 +1100 Subject: Fix animation player initialization Updates from 9d30fade3ea9b weren't applied to the animation player causing an assert and missing call to IMB_init. --- source/blender/blenkernel/intern/appdir.c | 1 + source/creator/creator_args.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 00c62340e16..2038079744d 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -109,6 +109,7 @@ static bool is_appdir_init = false; void BKE_appdir_init(void) { #ifndef NDEBUG + BLI_assert(is_appdir_init == false); is_appdir_init = true; #endif } diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index 47ab96bbc7e..3b54811657d 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -48,6 +48,7 @@ # include "BKE_blender_version.h" # include "BKE_context.h" +# include "BKE_appdir.h" # include "BKE_global.h" # include "BKE_image.h" # include "BKE_lib_id.h" @@ -56,9 +57,7 @@ # include "BKE_scene.h" # include "BKE_sound.h" -# ifdef WITH_FFMPEG -# include "IMB_imbuf.h" -# endif +# include "IMB_imbuf.h" # ifdef WITH_PYTHON # include "BPY_extern_python.h" @@ -1205,6 +1204,8 @@ static int arg_handle_playback_mode(int argc, const char **argv, void *UNUSED(da { /* not if -b was given first */ if (G.background == 0) { + BKE_appdir_init(); + IMB_init(); # ifdef WITH_FFMPEG /* Setup FFmpeg with current debug flags. */ IMB_ffmpeg_init(); -- cgit v1.2.3 From cf5ae6718c8cc595f19f40dae80ab55296e34ad0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 22 Oct 2020 16:29:15 +1100 Subject: Cleanup: split BLF default into own file This avoids accidents using user-preferences in the main BLF API, which could cause preferences to be used unintentionally (such as stamping into renders or creating generated images). As well as uses of BLF when preferences aren't loaded such as animation playback. --- source/blender/blenfont/CMakeLists.txt | 1 + source/blender/blenfont/intern/blf.c | 71 ++------------------ source/blender/blenfont/intern/blf_default.c | 95 +++++++++++++++++++++++++++ source/blender/blenfont/intern/blf_internal.h | 2 + 4 files changed, 104 insertions(+), 65 deletions(-) create mode 100644 source/blender/blenfont/intern/blf_default.c (limited to 'source') diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index 3fd0dd95ef8..59a9072de57 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -38,6 +38,7 @@ set(INC_SYS set(SRC intern/blf.c + intern/blf_default.c intern/blf_dir.c intern/blf_font.c intern/blf_font_default.c diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index c8940add738..48f283e67b9 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -37,10 +37,6 @@ #include "MEM_guardedalloc.h" -#include "DNA_listBase.h" -#include "DNA_userdef_types.h" -#include "DNA_vec_types.h" - #include "BLI_math.h" #include "BLI_threads.h" @@ -48,9 +44,6 @@ #include "IMB_colormanagement.h" -#include "UI_interface.h" - -#include "GPU_immediate.h" #include "GPU_matrix.h" #include "GPU_shader.h" @@ -64,9 +57,6 @@ */ #define BLF_MAX_FONT 16 -/* call BLF_default_set first! */ -#define ASSERT_DEFAULT_SET BLI_assert(global_font_default != -1) - #define BLF_RESULT_CHECK_INIT(r_info) \ if (r_info) { \ memset(r_info, 0, sizeof(*(r_info))); \ @@ -76,10 +66,6 @@ /* Font array. */ static FontBLF *global_font[BLF_MAX_FONT] = {NULL}; -/* Default size and dpi, for BLF_draw_default. */ -static int global_font_default = -1; -static int global_font_dpi = 72; - /* XXX, should these be made into global_font_'s too? */ int blf_mono_font = -1; int blf_mono_font_render = -1; @@ -98,16 +84,11 @@ int BLF_init(void) global_font[i] = NULL; } - global_font_dpi = 72; + BLF_default_dpi(72); return blf_font_init(); } -void BLF_default_dpi(int dpi) -{ - global_font_dpi = dpi; -} - void BLF_exit(void) { for (int i = 0; i < BLF_MAX_FONT; i++) { @@ -132,6 +113,11 @@ void BLF_cache_clear(void) } } +bool blf_font_id_is_valid(int fontid) +{ + return blf_get(fontid) != NULL; +} + static int blf_search(const char *name) { for (int i = 0; i < BLF_MAX_FONT; i++) { @@ -155,20 +141,6 @@ static int blf_search_available(void) return -1; } -void BLF_default_set(int fontid) -{ - FontBLF *font = blf_get(fontid); - if (font || fontid == -1) { - global_font_default = fontid; - } -} - -int BLF_default(void) -{ - ASSERT_DEFAULT_SET; - return global_font_default; -} - bool BLF_has_glyph(int fontid, unsigned int unicode) { FontBLF *font = blf_get(fontid); @@ -515,37 +487,6 @@ void BLF_batch_draw_end(void) g_batch.enabled = false; } -void BLF_draw_default(float x, float y, float z, const char *str, size_t len) -{ - ASSERT_DEFAULT_SET; - - const uiStyle *style = UI_style_get(); - BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi); - BLF_position(global_font_default, x, y, z); - BLF_draw(global_font_default, str, len); -} - -/* same as above but call 'BLF_draw_ascii' */ -void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len) -{ - ASSERT_DEFAULT_SET; - - const uiStyle *style = UI_style_get(); - BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi); - BLF_position(global_font_default, x, y, z); - BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */ -} - -int BLF_set_default(void) -{ - ASSERT_DEFAULT_SET; - - const uiStyle *style = UI_style_get(); - BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi); - - return global_font_default; -} - static void blf_draw_gl__start(FontBLF *font) { /* diff --git a/source/blender/blenfont/intern/blf_default.c b/source/blender/blenfont/intern/blf_default.c new file mode 100644 index 00000000000..bd06f14800c --- /dev/null +++ b/source/blender/blenfont/intern/blf_default.c @@ -0,0 +1,95 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup blf + * + * Default API, that uses Blender's user preferences for the default size. + */ + +#include + +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "DNA_userdef_types.h" + +#include "BLI_assert.h" + +#include "BLF_api.h" + +#include "UI_interface.h" + +#include "blf_internal.h" + +/* call BLF_default_set first! */ +#define ASSERT_DEFAULT_SET BLI_assert(global_font_default != -1) + +/* Default size and dpi, for BLF_draw_default. */ +static int global_font_default = -1; +static int global_font_dpi = 72; + +void BLF_default_dpi(int dpi) +{ + global_font_dpi = dpi; +} + +void BLF_default_set(int fontid) +{ + if ((fontid == -1) || blf_font_id_is_valid(fontid)) { + global_font_default = fontid; + } +} + +int BLF_default(void) +{ + ASSERT_DEFAULT_SET; + return global_font_default; +} + +int BLF_set_default(void) +{ + ASSERT_DEFAULT_SET; + + const uiStyle *style = UI_style_get(); + BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi); + + return global_font_default; +} + +void BLF_draw_default(float x, float y, float z, const char *str, size_t len) +{ + ASSERT_DEFAULT_SET; + + const uiStyle *style = UI_style_get(); + BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi); + BLF_position(global_font_default, x, y, z); + BLF_draw(global_font_default, str, len); +} + +/* same as above but call 'BLF_draw_ascii' */ +void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len) +{ + ASSERT_DEFAULT_SET; + + const uiStyle *style = UI_style_get(); + BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi); + BLF_position(global_font_default, x, y, z); + BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */ +} diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index b616f47a897..ada772c53d2 100644 --- a/source/blender/blenfont/intern/blf_internal.h +++ b/source/blender/blenfont/intern/blf_internal.h @@ -43,6 +43,8 @@ char *blf_dir_metrics_search(const char *filename); int blf_font_init(void); void blf_font_exit(void); +bool blf_font_id_is_valid(int fontid); + void blf_draw_buffer__start(struct FontBLF *font); void blf_draw_buffer__end(void); -- cgit v1.2.3 From 36653a92fad456e5ff99573ab82adaa1fca4a273 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 22 Oct 2020 17:30:52 +1100 Subject: Cleanup: centralize BLF default functions in the header --- source/blender/blenfont/BLF_api.h | 20 ++++++++++---------- source/blender/blenfont/intern/blf_default.c | 5 ----- 2 files changed, 10 insertions(+), 15 deletions(-) (limited to 'source') diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index bf84f5c57b3..03877957f42 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -40,9 +40,6 @@ struct rcti; int BLF_init(void); void BLF_exit(void); -void BLF_default_dpi(int dpi); -void BLF_default_set(int fontid); -int BLF_default(void); /* get default font ID so we can pass it to other functions */ void BLF_cache_clear(void); @@ -98,13 +95,6 @@ void BLF_batch_draw_begin(void); void BLF_batch_draw_flush(void); void BLF_batch_draw_end(void); -/* Draw the string using the default font, size and dpi. */ -void BLF_draw_default(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL(); -void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL(); - -/* Set size and DPI, and return default font ID. */ -int BLF_set_default(void); - /* Draw the string using the current font. */ void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info) ATTR_NONNULL(2); @@ -257,6 +247,16 @@ void BLF_thumb_preview(const char *filename, int h, int channels) ATTR_NONNULL(); +/* blf_default.c */ +void BLF_default_dpi(int dpi); +void BLF_default_set(int fontid); +int BLF_default(void); /* get default font ID so we can pass it to other functions */ +/* Draw the string using the default font, size and dpi. */ +void BLF_draw_default(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL(); +void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL(); +/* Set size and DPI, and return default font ID. */ +int BLF_set_default(void); + /* blf_font_default.c */ int BLF_load_default(const bool unique); int BLF_load_mono_default(const bool unique); diff --git a/source/blender/blenfont/intern/blf_default.c b/source/blender/blenfont/intern/blf_default.c index bd06f14800c..7bbc865128d 100644 --- a/source/blender/blenfont/intern/blf_default.c +++ b/source/blender/blenfont/intern/blf_default.c @@ -23,11 +23,6 @@ * Default API, that uses Blender's user preferences for the default size. */ -#include - -#include FT_FREETYPE_H -#include FT_GLYPH_H - #include "DNA_userdef_types.h" #include "BLI_assert.h" -- cgit v1.2.3 From cf8642d9fac4cec7d3ee434a5403c2bbc8c5c21c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 22 Oct 2020 18:42:08 +1100 Subject: Fix T81949: Child Of Constraint can't assign inverse matrix Caused by ad70d4b0956f5, assigning the matrix now clears the flag that would reset it. --- source/blender/makesrna/intern/rna_constraint.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source') diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 653056e4dc1..76b419926a1 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -512,6 +512,17 @@ static void rna_Constraint_influence_update(Main *bmain, Scene *scene, PointerRN rna_Constraint_update(bmain, scene, ptr); } +/* Update only needed so this isn't overwritten on first evaluation. */ +static void rna_Constraint_childof_inverse_matrix_update(Main *bmain, + Scene *scene, + PointerRNA *ptr) +{ + bConstraint *con = ptr->data; + bChildOfConstraint *data = con->data; + data->flag &= ~CHILDOF_SET_INVERSE; + rna_Constraint_update(bmain, scene, ptr); +} + static void rna_Constraint_ik_type_set(struct PointerRNA *ptr, int value) { bConstraint *con = ptr->data; @@ -999,7 +1010,8 @@ static void rna_def_constraint_childof(BlenderRNA *brna) RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Inverse Matrix", "Transformation matrix to apply before"); - RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + RNA_def_property_update( + prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_childof_inverse_matrix_update"); RNA_define_lib_overridable(false); } -- cgit v1.2.3 From 92571abf5645ea3156e892ecfa2a08f0ca88cad4 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 20 Oct 2020 13:43:20 +0200 Subject: GPU: Memory leak when scaling buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `imb_gpu_get_data` could reuse `data_rect` when it was already in used (double alloc). making the first use leak. This was detected after enabling OpenGL Texture Limit. Reviewed By: Clément Foucault Differential Revision: https://developer.blender.org/D9280 --- source/blender/imbuf/intern/util_gpu.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/blender/imbuf/intern/util_gpu.c b/source/blender/imbuf/intern/util_gpu.c index 2826bd63cc1..607ab95f0b4 100644 --- a/source/blender/imbuf/intern/util_gpu.c +++ b/source/blender/imbuf/intern/util_gpu.c @@ -97,6 +97,7 @@ static void *imb_gpu_get_data(const ImBuf *ibuf, { const bool is_float_rect = (ibuf->rect_float != NULL); void *data_rect = (is_float_rect) ? (void *)ibuf->rect_float : (void *)ibuf->rect; + bool freedata = false; if (is_float_rect) { /* Float image is already in scene linear colorspace or non-color data by @@ -104,7 +105,7 @@ static void *imb_gpu_get_data(const ImBuf *ibuf, * currently. */ if (ibuf->channels != 4 || !store_premultiplied) { data_rect = MEM_mallocN(sizeof(float[4]) * ibuf->x * ibuf->y, __func__); - *r_freedata = true; + *r_freedata = freedata = true; if (data_rect == NULL) { return NULL; @@ -124,7 +125,7 @@ static void *imb_gpu_get_data(const ImBuf *ibuf, * and consistency with float images. */ if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) { data_rect = MEM_mallocN(sizeof(uchar[4]) * ibuf->x * ibuf->y, __func__); - *r_freedata = true; + *r_freedata = freedata = true; if (data_rect == NULL) { return NULL; @@ -147,6 +148,10 @@ static void *imb_gpu_get_data(const ImBuf *ibuf, ImBuf *scale_ibuf = IMB_allocFromBuffer(rect, rect_float, ibuf->x, ibuf->y, 4); IMB_scaleImBuf(scale_ibuf, UNPACK2(rescale_size)); + if (freedata) { + MEM_freeN(data_rect); + } + data_rect = (is_float_rect) ? (void *)scale_ibuf->rect_float : (void *)scale_ibuf->rect; *r_freedata = true; /* Steal the rescaled buffer to avoid double free. */ -- cgit v1.2.3 From f68c3d557aa847743b09d8b837278ea785ec40f6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 22 Oct 2020 11:13:34 +0200 Subject: Compositor: Ensure keying node result is pre-multiplied Historically the result of the keying node was violating alpha pre-multiplication rules in Blender: it was simply overriding the alpha channel of input. This change makes it so keying node mixes alpha into the input, which solves the following issues: - The result is properly pre-multiplied, no need in separate alpha-convert node anymore. - Allows to more easily stack keying nodes. This usecase was never really investigated, but since previously alpha is always overwritten it was never possible to easily stack nodes. Now it is at something to be tried. Unfortunately, this breaks compatibility with existing files, where alpha-convert node is to be manually removed. From implementation side this is done as a dedicated operation since there was no ready-to-use operation. Maybe in the future it might be replaced with some sort of vector math node. Reviewed By: brecht Differential Revision: https://developer.blender.org/D9211 --- source/blender/compositor/CMakeLists.txt | 2 + source/blender/compositor/nodes/COM_KeyingNode.cpp | 4 +- .../operations/COM_KeyingSetAlphaOperation.cpp | 55 ++++++++++++++++++++++ .../operations/COM_KeyingSetAlphaOperation.h | 39 +++++++++++++++ 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 source/blender/compositor/operations/COM_KeyingSetAlphaOperation.cpp create mode 100644 source/blender/compositor/operations/COM_KeyingSetAlphaOperation.h (limited to 'source') diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index d524f4a0e1e..54dd121952b 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -353,6 +353,8 @@ set(SRC operations/COM_KeyingDespillOperation.h operations/COM_KeyingOperation.cpp operations/COM_KeyingOperation.h + operations/COM_KeyingSetAlphaOperation.cpp + operations/COM_KeyingSetAlphaOperation.h operations/COM_ColorSpillOperation.cpp operations/COM_ColorSpillOperation.h diff --git a/source/blender/compositor/nodes/COM_KeyingNode.cpp b/source/blender/compositor/nodes/COM_KeyingNode.cpp index b75d06763b7..a0ccaf0b9da 100644 --- a/source/blender/compositor/nodes/COM_KeyingNode.cpp +++ b/source/blender/compositor/nodes/COM_KeyingNode.cpp @@ -32,7 +32,7 @@ #include "COM_DilateErodeOperation.h" -#include "COM_SetAlphaOperation.h" +#include "COM_KeyingSetAlphaOperation.h" #include "COM_GaussianAlphaXBlurOperation.h" #include "COM_GaussianAlphaYBlurOperation.h" @@ -322,7 +322,7 @@ void KeyingNode::convertToOperations(NodeConverter &converter, } /* set alpha channel to output image */ - SetAlphaOperation *alphaOperation = new SetAlphaOperation(); + KeyingSetAlphaOperation *alphaOperation = new KeyingSetAlphaOperation(); converter.addOperation(alphaOperation); converter.mapInputSocket(inputImage, alphaOperation->getInputSocket(0)); diff --git a/source/blender/compositor/operations/COM_KeyingSetAlphaOperation.cpp b/source/blender/compositor/operations/COM_KeyingSetAlphaOperation.cpp new file mode 100644 index 00000000000..dff88d49e80 --- /dev/null +++ b/source/blender/compositor/operations/COM_KeyingSetAlphaOperation.cpp @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +#include "COM_KeyingSetAlphaOperation.h" + +KeyingSetAlphaOperation::KeyingSetAlphaOperation() : NodeOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + + this->m_inputColor = NULL; + this->m_inputAlpha = NULL; +} + +void KeyingSetAlphaOperation::initExecution() +{ + this->m_inputColor = getInputSocketReader(0); + this->m_inputAlpha = getInputSocketReader(1); +} + +void KeyingSetAlphaOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) +{ + float color_input[4]; + float alpha_input[4]; + + this->m_inputColor->readSampled(color_input, x, y, sampler); + this->m_inputAlpha->readSampled(alpha_input, x, y, sampler); + + mul_v4_v4fl(output, color_input, alpha_input[0]); +} + +void KeyingSetAlphaOperation::deinitExecution() +{ + this->m_inputColor = NULL; + this->m_inputAlpha = NULL; +} diff --git a/source/blender/compositor/operations/COM_KeyingSetAlphaOperation.h b/source/blender/compositor/operations/COM_KeyingSetAlphaOperation.h new file mode 100644 index 00000000000..b786240f215 --- /dev/null +++ b/source/blender/compositor/operations/COM_KeyingSetAlphaOperation.h @@ -0,0 +1,39 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +#pragma once + +#include "COM_NodeOperation.h" + +/** + * Operation which is used by keying node to modify image's alpha channels. + * It keeps color properly pre-multiplied. + */ +class KeyingSetAlphaOperation : public NodeOperation { + private: + SocketReader *m_inputColor; + SocketReader *m_inputAlpha; + + public: + KeyingSetAlphaOperation(); + + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); +}; -- cgit v1.2.3 From d11e357824d607645a2e416c35b18bcfb5f5da11 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 22 Oct 2020 12:05:48 +0200 Subject: Multires: Remove legacy compatibility code It was rather a huge chunk of code, which started to become more harder to maintain with the transition to OpenSubdiv based implementation. Because of this transition, the compatibility was also rather on a poor side. Remove compatibility support for pre-2.50.9 multires. Ref T77107 Reviewed By: brecht, mont29 Differential Revision: https://developer.blender.org/D9238 --- source/blender/blenkernel/BKE_multires.h | 6 - source/blender/blenkernel/intern/mesh.c | 44 -- source/blender/blenkernel/intern/multires.c | 720 --------------------- source/blender/blenloader/intern/versioning_250.c | 16 +- .../blender/blenloader/intern/versioning_legacy.c | 18 - source/blender/makesdna/DNA_mesh_types.h | 4 - source/blender/makesdna/DNA_meshdata_types.h | 50 -- 7 files changed, 1 insertion(+), 857 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index fbdfc5b76a7..8ed3741c659 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -36,7 +36,6 @@ struct DerivedMesh; struct MDisps; struct Mesh; struct ModifierData; -struct Multires; struct MultiresModifierData; struct Object; struct Scene; @@ -125,11 +124,6 @@ void multiresModifier_sync_levels_ex(struct Object *ob_dst, void multires_stitch_grids(struct Object *); -/* Related to the old multires */ -void multires_free(struct Multires *mr); -void multires_load_old(struct Object *ob, struct Mesh *me); -void multires_load_old_250(struct Mesh *); - void multiresModifier_scale_disp(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 6ea83cf4330..97520654e7b 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -275,50 +275,6 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) mesh->totselect = 0; } - /* Multires data */ - BLO_read_data_address(reader, &mesh->mr); - if (mesh->mr) { - BLO_read_list(reader, &mesh->mr->levels); - MultiresLevel *lvl = mesh->mr->levels.first; - - CustomData_blend_read(reader, &mesh->mr->vdata, lvl->totvert); - BKE_defvert_blend_read( - reader, lvl->totvert, CustomData_get(&mesh->mr->vdata, 0, CD_MDEFORMVERT)); - CustomData_blend_read(reader, &mesh->mr->fdata, lvl->totface); - - BLO_read_data_address(reader, &mesh->mr->edge_flags); - BLO_read_data_address(reader, &mesh->mr->edge_creases); - - BLO_read_data_address(reader, &mesh->mr->verts); - - /* If mesh has the same number of vertices as the - * highest multires level, load the current mesh verts - * into multires and discard the old data. Needed - * because some saved files either do not have a verts - * array, or the verts array contains out-of-date - * data. */ - if (mesh->totvert == ((MultiresLevel *)mesh->mr->levels.last)->totvert) { - if (mesh->mr->verts) { - MEM_freeN(mesh->mr->verts); - } - mesh->mr->verts = MEM_dupallocN(mesh->mvert); - } - - for (; lvl; lvl = lvl->next) { - BLO_read_data_address(reader, &lvl->verts); - BLO_read_data_address(reader, &lvl->faces); - BLO_read_data_address(reader, &lvl->edges); - BLO_read_data_address(reader, &lvl->colfaces); - } - } - - /* if multires is present but has no valid vertex data, - * there's no way to recover it; silently remove multires */ - if (mesh->mr && !mesh->mr->verts) { - multires_free(mesh->mr); - mesh->mr = NULL; - } - if ((BLO_read_requires_endian_switch(reader)) && mesh->tface) { TFace *tf = mesh->tface; for (int i = 0; i < mesh->totface; i++, tf++) { diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 6e1168d8a16..bd9b1b24844 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -1449,9 +1449,6 @@ DerivedMesh *multires_make_derived_from_derived( return result; } -/**** Old Multires code **** - ***************************/ - /* Adapted from sculptmode.c */ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v) { @@ -1506,723 +1503,6 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, add_v3_v3v3(out, d2[0], d2[1]); } -static void old_mdisps_rotate( - int S, int UNUSED(newside), int oldside, int x, int y, float *u, float *v) -{ - float offset = oldside * 0.5f - 0.5f; - - if (S == 1) { - *u = offset + x; - *v = offset - y; - } - if (S == 2) { - *u = offset + y; - *v = offset + x; - } - if (S == 3) { - *u = offset - x; - *v = offset + y; - } - if (S == 0) { - *u = offset - y; - *v = offset - x; - } -} - -static void old_mdisps_convert(MFace *mface, MDisps *mdisp) -{ - int newlvl = log(sqrt(mdisp->totdisp) - 1) / M_LN2; - int oldlvl = newlvl + 1; - int oldside = multires_side_tot[oldlvl]; - int newside = multires_side_tot[newlvl]; - int nvert = (mface->v4) ? 4 : 3; - int newtotdisp = multires_grid_tot[newlvl] * nvert; - int x, y, S; - float(*disps)[3], (*out)[3], u = 0.0f, v = 0.0f; /* Quite gcc barking. */ - - disps = MEM_calloc_arrayN(newtotdisp, sizeof(float[3]), "multires disps"); - - out = disps; - for (S = 0; S < nvert; S++) { - for (y = 0; y < newside; y++) { - for (x = 0; x < newside; x++, out++) { - old_mdisps_rotate(S, newside, oldside, x, y, &u, &v); - old_mdisps_bilinear(*out, mdisp->disps, oldside, u, v); - - if (S == 1) { - (*out)[1] = -(*out)[1]; - } - else if (S == 2) { - SWAP(float, (*out)[0], (*out)[1]); - } - else if (S == 3) { - (*out)[0] = -(*out)[0]; - } - else if (S == 0) { - SWAP(float, (*out)[0], (*out)[1]); - (*out)[0] = -(*out)[0]; - (*out)[1] = -(*out)[1]; - } - } - } - } - - MEM_freeN(mdisp->disps); - - mdisp->totdisp = newtotdisp; - mdisp->level = newlvl; - mdisp->disps = disps; -} - -void multires_load_old_250(Mesh *me) -{ - MDisps *mdisps, *mdisps2; - MFace *mf; - int i, j, k; - - mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); - - if (mdisps) { - for (i = 0; i < me->totface; i++) { - if (mdisps[i].totdisp) { - old_mdisps_convert(&me->mface[i], &mdisps[i]); - } - } - - CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop); - mdisps2 = CustomData_get_layer(&me->ldata, CD_MDISPS); - - k = 0; - mf = me->mface; - for (i = 0; i < me->totface; i++, mf++) { - int nvert = mf->v4 ? 4 : 3; - int totdisp = mdisps[i].totdisp / nvert; - - for (j = 0; j < nvert; j++, k++) { - mdisps2[k].disps = MEM_calloc_arrayN( - totdisp, sizeof(float[3]), "multires disp in conversion"); - mdisps2[k].totdisp = totdisp; - mdisps2[k].level = mdisps[i].level; - memcpy(mdisps2[k].disps, mdisps[i].disps + totdisp * j, totdisp); - } - } - } -} - -/* Does not actually free lvl itself */ -static void multires_free_level(MultiresLevel *lvl) -{ - if (lvl) { - if (lvl->faces) { - MEM_freeN(lvl->faces); - } - if (lvl->edges) { - MEM_freeN(lvl->edges); - } - if (lvl->colfaces) { - MEM_freeN(lvl->colfaces); - } - } -} - -void multires_free(Multires *mr) -{ - if (mr) { - MultiresLevel *lvl = mr->levels.first; - - /* Free the first-level data */ - if (lvl) { - CustomData_free(&mr->vdata, lvl->totvert); - CustomData_free(&mr->fdata, lvl->totface); - if (mr->edge_flags) { - MEM_freeN(mr->edge_flags); - } - if (mr->edge_creases) { - MEM_freeN(mr->edge_creases); - } - } - - while (lvl) { - multires_free_level(lvl); - lvl = lvl->next; - } - - /* mr->verts may be NULL when loading old files, - * see direct_link_mesh() in readfile.c, and T43560. */ - MEM_SAFE_FREE(mr->verts); - - BLI_freelistN(&mr->levels); - - MEM_freeN(mr); - } -} - -typedef struct IndexNode { - struct IndexNode *next, *prev; - int index; -} IndexNode; - -static void create_old_vert_face_map(ListBase **map, - IndexNode **mem, - const MultiresFace *mface, - const int totvert, - const int totface) -{ - int i, j; - IndexNode *node = NULL; - - (*map) = MEM_calloc_arrayN(totvert, sizeof(ListBase), "vert face map"); - (*mem) = MEM_calloc_arrayN(totface, sizeof(IndexNode[4]), "vert face map mem"); - node = *mem; - - /* Find the users */ - for (i = 0; i < totface; i++) { - for (j = 0; j < (mface[i].v[3] ? 4 : 3); j++, node++) { - node->index = i; - BLI_addtail(&(*map)[mface[i].v[j]], node); - } - } -} - -static void create_old_vert_edge_map(ListBase **map, - IndexNode **mem, - const MultiresEdge *medge, - const int totvert, - const int totedge) -{ - int i, j; - IndexNode *node = NULL; - - (*map) = MEM_calloc_arrayN(totvert, sizeof(ListBase), "vert edge map"); - (*mem) = MEM_calloc_arrayN(totedge, sizeof(IndexNode[2]), "vert edge map mem"); - node = *mem; - - /* Find the users */ - for (i = 0; i < totedge; i++) { - for (j = 0; j < 2; j++, node++) { - node->index = i; - BLI_addtail(&(*map)[medge[i].v[j]], node); - } - } -} - -static MultiresFace *find_old_face( - ListBase *map, MultiresFace *faces, int v1, int v2, int v3, int v4) -{ - IndexNode *n1; - int v[4], i, j; - - v[0] = v1; - v[1] = v2; - v[2] = v3; - v[3] = v4; - - for (n1 = map[v1].first; n1; n1 = n1->next) { - int fnd[4] = {0, 0, 0, 0}; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - if (v[i] == faces[n1->index].v[j]) { - fnd[i] = 1; - } - } - } - - if (fnd[0] && fnd[1] && fnd[2] && fnd[3]) { - return &faces[n1->index]; - } - } - - return NULL; -} - -static MultiresEdge *find_old_edge(ListBase *map, MultiresEdge *edges, int v1, int v2) -{ - IndexNode *n1, *n2; - - for (n1 = map[v1].first; n1; n1 = n1->next) { - for (n2 = map[v2].first; n2; n2 = n2->next) { - if (n1->index == n2->index) { - return &edges[n1->index]; - } - } - } - - return NULL; -} - -static void multires_load_old_edges( - ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst, int v1, int v2, int mov) -{ - int emid = find_old_edge(emap[2], lvl->edges, v1, v2)->mid; - vvmap[dst + mov] = emid; - - if (lvl->next->next) { - multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v1, emid, mov / 2); - multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v2, emid, -mov / 2); - } -} - -static void multires_load_old_faces(ListBase **fmap, - ListBase **emap, - MultiresLevel *lvl, - int *vvmap, - int dst, - int v1, - int v2, - int v3, - int v4, - int st2, - int st3) -{ - int fmid; - int emid13, emid14, emid23, emid24; - - if (lvl && lvl->next) { - fmid = find_old_face(fmap[1], lvl->faces, v1, v2, v3, v4)->mid; - vvmap[dst] = fmid; - - emid13 = find_old_edge(emap[1], lvl->edges, v1, v3)->mid; - emid14 = find_old_edge(emap[1], lvl->edges, v1, v4)->mid; - emid23 = find_old_edge(emap[1], lvl->edges, v2, v3)->mid; - emid24 = find_old_edge(emap[1], lvl->edges, v2, v4)->mid; - - multires_load_old_faces(fmap + 1, - emap + 1, - lvl->next, - vvmap, - dst + st2 * st3 + st3, - fmid, - v2, - emid23, - emid24, - st2, - st3 / 2); - - multires_load_old_faces(fmap + 1, - emap + 1, - lvl->next, - vvmap, - dst - st2 * st3 + st3, - emid14, - emid24, - fmid, - v4, - st2, - st3 / 2); - - multires_load_old_faces(fmap + 1, - emap + 1, - lvl->next, - vvmap, - dst + st2 * st3 - st3, - emid13, - emid23, - v3, - fmid, - st2, - st3 / 2); - - multires_load_old_faces(fmap + 1, - emap + 1, - lvl->next, - vvmap, - dst - st2 * st3 - st3, - v1, - fmid, - emid13, - emid14, - st2, - st3 / 2); - - if (lvl->next->next) { - multires_load_old_edges(emap, lvl->next, vvmap, dst, emid24, fmid, st3); - multires_load_old_edges(emap, lvl->next, vvmap, dst, emid13, fmid, -st3); - multires_load_old_edges(emap, lvl->next, vvmap, dst, emid14, fmid, -st2 * st3); - multires_load_old_edges(emap, lvl->next, vvmap, dst, emid23, fmid, st2 * st3); - } - } -} - -static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; - CCGSubSurf *ss = ccgdm->ss; - CCGElem *vd; - CCGKey key; - int index; - int totvert, totedge, totface; - int gridSize = ccgSubSurf_getGridSize(ss); - int edgeSize = ccgSubSurf_getEdgeSize(ss); - int i = 0; - - dm->getGridKey(dm, &key); - - totface = ccgSubSurf_getNumFaces(ss); - for (index = 0; index < totface; index++) { - CCGFace *f = ccgdm->faceMap[index].face; - int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); - - vd = ccgSubSurf_getFaceCenterData(f); - copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co); - i++; - - for (S = 0; S < numVerts; S++) { - for (x = 1; x < gridSize - 1; x++, i++) { - vd = ccgSubSurf_getFaceGridEdgeData(ss, f, S, x); - copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co); - } - } - - for (S = 0; S < numVerts; S++) { - for (y = 1; y < gridSize - 1; y++) { - for (x = 1; x < gridSize - 1; x++, i++) { - vd = ccgSubSurf_getFaceGridData(ss, f, S, x, y); - copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co); - } - } - } - } - - totedge = ccgSubSurf_getNumEdges(ss); - for (index = 0; index < totedge; index++) { - CCGEdge *e = ccgdm->edgeMap[index].edge; - int x; - - for (x = 1; x < edgeSize - 1; x++, i++) { - vd = ccgSubSurf_getEdgeData(ss, e, x); - copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co); - } - } - - totvert = ccgSubSurf_getNumVerts(ss); - for (index = 0; index < totvert; index++) { - CCGVert *v = ccgdm->vertMap[index].vert; - - vd = ccgSubSurf_getVertData(ss, v); - copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co); - i++; - } - - ccgSubSurf_updateToFaces(ss, 0, NULL, 0); -} - -/* Loads a multires object stored in the old Multires struct into the new format */ -static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl) -{ - MultiresLevel *lvl, *lvl1; - Multires *mr = me->mr; - MVert *vsrc, *vdst; - unsigned int src, dst; - int st_last = multires_side_tot[totlvl - 1] - 1; - int extedgelen = multires_side_tot[totlvl] - 2; - int *vvmap; // inorder for dst, map to src - int crossedgelen; - int s, x, tottri, totquad; - unsigned int i, j, totvert; - - src = 0; - vsrc = mr->verts; - vdst = dm->getVertArray(dm); - totvert = (unsigned int)dm->getNumVerts(dm); - vvmap = MEM_calloc_arrayN(totvert, sizeof(int), "multires vvmap"); - - if (!vvmap) { - return; - } - - lvl1 = mr->levels.first; - /* Load base verts */ - for (i = 0; i < lvl1->totvert; i++) { - vvmap[totvert - lvl1->totvert + i] = src; - src++; - } - - /* Original edges */ - dst = totvert - lvl1->totvert - extedgelen * lvl1->totedge; - for (i = 0; i < lvl1->totedge; i++) { - int ldst = dst + extedgelen * i; - int lsrc = src; - lvl = lvl1->next; - - for (j = 2; j <= mr->level_count; j++) { - int base = multires_side_tot[totlvl - j + 1] - 2; - int skip = multires_side_tot[totlvl - j + 2] - 1; - int st = multires_side_tot[j - 1] - 1; - - for (x = 0; x < st; x++) { - vvmap[ldst + base + x * skip] = lsrc + st * i + x; - } - - lsrc += lvl->totvert - lvl->prev->totvert; - lvl = lvl->next; - } - } - - /* Center points */ - dst = 0; - for (i = 0; i < lvl1->totface; i++) { - int sides = lvl1->faces[i].v[3] ? 4 : 3; - - vvmap[dst] = src + lvl1->totedge + i; - dst += 1 + sides * (st_last - 1) * st_last; - } - - /* The rest is only for level 3 and up */ - if (lvl1->next && lvl1->next->next) { - ListBase **fmap, **emap; - IndexNode **fmem, **emem; - - /* Face edge cross */ - tottri = totquad = 0; - crossedgelen = multires_side_tot[totlvl - 1] - 2; - dst = 0; - for (i = 0; i < lvl1->totface; i++) { - int sides = lvl1->faces[i].v[3] ? 4 : 3; - - lvl = lvl1->next->next; - dst++; - - for (j = 3; j <= mr->level_count; j++) { - int base = multires_side_tot[totlvl - j + 1] - 2; - int skip = multires_side_tot[totlvl - j + 2] - 1; - int st = pow(2, j - 2); - int st2 = pow(2, j - 3); - int lsrc = lvl->prev->totvert; - - /* Skip exterior edge verts */ - lsrc += lvl1->totedge * st; - - /* Skip earlier face edge crosses */ - lsrc += st2 * (tottri * 3 + totquad * 4); - - for (s = 0; s < sides; s++) { - for (x = 0; x < st2; x++) { - vvmap[dst + crossedgelen * (s + 1) - base - x * skip - 1] = lsrc; - lsrc++; - } - } - - lvl = lvl->next; - } - - dst += sides * (st_last - 1) * st_last; - - if (sides == 4) { - totquad++; - } - else { - tottri++; - } - } - - /* calculate vert to edge/face maps for each level (except the last) */ - fmap = MEM_calloc_arrayN((mr->level_count - 1), sizeof(ListBase *), "multires fmap"); - emap = MEM_calloc_arrayN((mr->level_count - 1), sizeof(ListBase *), "multires emap"); - fmem = MEM_calloc_arrayN((mr->level_count - 1), sizeof(IndexNode *), "multires fmem"); - emem = MEM_calloc_arrayN((mr->level_count - 1), sizeof(IndexNode *), "multires emem"); - lvl = lvl1; - for (i = 0; i < (unsigned int)mr->level_count - 1; i++) { - create_old_vert_face_map(fmap + i, fmem + i, lvl->faces, lvl->totvert, lvl->totface); - create_old_vert_edge_map(emap + i, emem + i, lvl->edges, lvl->totvert, lvl->totedge); - lvl = lvl->next; - } - - /* Interior face verts */ - /* lvl = lvl1->next->next; */ /* UNUSED */ - dst = 0; - for (j = 0; j < lvl1->totface; j++) { - int sides = lvl1->faces[j].v[3] ? 4 : 3; - int ldst = dst + 1 + sides * (st_last - 1); - - for (s = 0; s < sides; s++) { - int st2 = multires_side_tot[totlvl - 1] - 2; - int st3 = multires_side_tot[totlvl - 2] - 2; - int st4 = st3 == 0 ? 1 : (st3 + 1) / 2; - int mid = ldst + st2 * st3 + st3; - int cv = lvl1->faces[j].v[s]; - int nv = lvl1->faces[j].v[s == sides - 1 ? 0 : s + 1]; - int pv = lvl1->faces[j].v[s == 0 ? sides - 1 : s - 1]; - - multires_load_old_faces(fmap, - emap, - lvl1->next, - vvmap, - mid, - vvmap[dst], - cv, - find_old_edge(emap[0], lvl1->edges, pv, cv)->mid, - find_old_edge(emap[0], lvl1->edges, cv, nv)->mid, - st2, - st4); - - ldst += (st_last - 1) * (st_last - 1); - } - - dst = ldst; - } - - /*lvl = lvl->next;*/ /*UNUSED*/ - - for (i = 0; i < (unsigned int)(mr->level_count - 1); i++) { - MEM_freeN(fmap[i]); - MEM_freeN(fmem[i]); - MEM_freeN(emap[i]); - MEM_freeN(emem[i]); - } - - MEM_freeN(fmap); - MEM_freeN(emap); - MEM_freeN(fmem); - MEM_freeN(emem); - } - - /* Transfer verts */ - for (i = 0; i < totvert; i++) { - copy_v3_v3(vdst[i].co, vsrc[vvmap[i]].co); - } - - MEM_freeN(vvmap); - - multires_mvert_to_ss(dm, vdst); -} - -/* Copy the first-level vcol data to the mesh, if it exists */ -/* Warning: higher-level vcol data will be lost */ -static void multires_load_old_vcols(Mesh *me) -{ - MultiresLevel *lvl; - MultiresColFace *colface; - MCol *mcol; - int i, j; - - if (!(lvl = me->mr->levels.first)) { - return; - } - - if (!(colface = lvl->colfaces)) { - return; - } - - /* older multires format never supported multiple vcol layers, - * so we can assume the active vcol layer is the correct one */ - if (!(mcol = CustomData_get_layer(&me->fdata, CD_MCOL))) { - return; - } - - for (i = 0; i < me->totface; i++) { - for (j = 0; j < 4; j++) { - mcol[i * 4 + j].a = colface[i].col[j].a; - mcol[i * 4 + j].r = colface[i].col[j].r; - mcol[i * 4 + j].g = colface[i].col[j].g; - mcol[i * 4 + j].b = colface[i].col[j].b; - } - } -} - -/* Copy the first-level face-flag data to the mesh */ -static void multires_load_old_face_flags(Mesh *me) -{ - MultiresLevel *lvl; - MultiresFace *faces; - int i; - - if (!(lvl = me->mr->levels.first)) { - return; - } - - if (!(faces = lvl->faces)) { - return; - } - - for (i = 0; i < me->totface; i++) { - me->mface[i].flag = faces[i].flag; - } -} - -void multires_load_old(Object *ob, Mesh *me) -{ - MultiresLevel *lvl; - ModifierData *md; - MultiresModifierData *mmd; - DerivedMesh *dm, *orig; - CustomDataLayer *l; - int i; - - /* Load original level into the mesh */ - lvl = me->mr->levels.first; - CustomData_free_layers(&me->vdata, CD_MVERT, lvl->totvert); - CustomData_free_layers(&me->edata, CD_MEDGE, lvl->totedge); - CustomData_free_layers(&me->fdata, CD_MFACE, lvl->totface); - me->totvert = lvl->totvert; - me->totedge = lvl->totedge; - me->totface = lvl->totface; - me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); - me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, me->totedge); - me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface); - memcpy(me->mvert, me->mr->verts, sizeof(MVert) * me->totvert); - for (i = 0; i < me->totedge; i++) { - me->medge[i].v1 = lvl->edges[i].v[0]; - me->medge[i].v2 = lvl->edges[i].v[1]; - } - for (i = 0; i < me->totface; i++) { - me->mface[i].v1 = lvl->faces[i].v[0]; - me->mface[i].v2 = lvl->faces[i].v[1]; - me->mface[i].v3 = lvl->faces[i].v[2]; - me->mface[i].v4 = lvl->faces[i].v[3]; - me->mface[i].mat_nr = lvl->faces[i].mat_nr; - } - - /* Copy the first-level data to the mesh */ - /* XXX We must do this before converting tessfaces to polys/lopps! */ - for (i = 0, l = me->mr->vdata.layers; i < me->mr->vdata.totlayer; i++, l++) { - CustomData_add_layer(&me->vdata, l->type, CD_REFERENCE, l->data, me->totvert); - } - for (i = 0, l = me->mr->fdata.layers; i < me->mr->fdata.totlayer; i++, l++) { - CustomData_add_layer(&me->fdata, l->type, CD_REFERENCE, l->data, me->totface); - } - CustomData_reset(&me->mr->vdata); - CustomData_reset(&me->mr->fdata); - - multires_load_old_vcols(me); - multires_load_old_face_flags(me); - - /* multiresModifier_subdivide_legacy (actually, multires_subdivide_legacy) expects polys, not - * tessfaces! */ - BKE_mesh_convert_mfaces_to_mpolys(me); - - /* Add a multires modifier to the object */ - md = ob->modifiers.first; - while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) { - md = md->next; - } - mmd = (MultiresModifierData *)BKE_modifier_new(eModifierType_Multires); - BLI_insertlinkbefore(&ob->modifiers, md, mmd); - - for (i = 0; i < me->mr->level_count - 1; i++) { - multiresModifier_subdivide_legacy(mmd, NULL, ob, 1, 0); - } - - mmd->lvl = mmd->totlvl; - orig = CDDM_from_mesh(me); - /* XXX We *must* alloc paint mask here, else we have some kind of mismatch in - * multires_modifier_update_mdisps() (called by dm->release(dm)), which always creates the - * reference subsurfed dm with this option, before calling multiresModifier_disp_run(), - * which implicitly expects both subsurfs from its first dm and oldGridData parameters to - * be of the same "format"! */ - dm = multires_make_derived_from_derived(orig, mmd, NULL, ob, 0); - - multires_load_old_dm(dm, me, mmd->totlvl + 1); - - multires_dm_mark_as_modified(dm, MULTIRES_COORDS_MODIFIED); - dm->release(dm); - orig->release(orig); - - /* Remove the old multires */ - multires_free(me->mr); - me->mr = NULL; -} - /* If 'ob_src' and 'ob_dst' both have multires modifiers, synchronize them * such that 'ob_dst' has the same total number of levels as 'ob_src'. */ void multiresModifier_sync_levels_ex(Object *ob_dst, diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 5046ee6aab1..f7592308023 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -799,20 +799,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) // BLI_freelistN(&pidlist); - if (ob->type == OB_MESH) { - Mesh *me = blo_do_versions_newlibadr(fd, lib, ob->data); - void *olddata = ob->data; - ob->data = me; - - /* XXX - library meshes crash on loading most yoFrankie levels, - * the multires pointer gets invalid - Campbell */ - if (me && me->id.lib == NULL && me->mr && me->mr->level_count > 1) { - multires_load_old(ob, me); - } - - ob->data = olddata; - } - if (ob->totcol && ob->matbits == NULL) { int a; @@ -1152,7 +1138,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) if (bmain->versionfile == 250 && bmain->subversionfile > 1) { for (me = bmain->meshes.first; me; me = me->id.next) { - multires_load_old_250(me); + CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface); } for (ob = bmain->objects.first; ob; ob = ob->id.next) { diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 4acf98cc58b..9d858da266d 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -1959,7 +1959,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) Light *la; Material *ma; ParticleSettings *part; - Mesh *me; bNodeTree *ntree; Tex *tex; ModifierData *md; @@ -2074,23 +2073,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) } } - /* Copy over old per-level multires vertex data - * into a single vertex array in struct Multires */ - for (me = bmain->meshes.first; me; me = me->id.next) { - if (me->mr && !me->mr->verts) { - MultiresLevel *lvl = me->mr->levels.last; - if (lvl) { - me->mr->verts = lvl->verts; - lvl->verts = NULL; - /* Don't need the other vert arrays */ - for (lvl = lvl->prev; lvl; lvl = lvl->prev) { - MEM_freeN(lvl->verts); - lvl->verts = NULL; - } - } - } - } - if (bmain->versionfile != 245 || bmain->subversionfile < 1) { for (la = bmain->lights.first; la; la = la->id.next) { la->falloff_type = LA_FALLOFF_INVLINEAR; diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index e2837ba85f8..a822a6723fa 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -48,7 +48,6 @@ struct MPropCol; struct MVert; struct Material; struct Mesh; -struct Multires; struct SubdivCCG; # @@ -230,9 +229,6 @@ typedef struct Mesh { * default and Face Sets can be used without affecting the color of the mesh. */ int face_sets_color_default; - /** Deprecated multiresolution modeling data, only keep for loading old files. */ - struct Multires *mr DNA_DEPRECATED; - Mesh_Runtime runtime; } Mesh; diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 45bf6e8c282..7cc94a2ad0b 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -518,54 +518,4 @@ typedef struct MRecast { int i; } MRecast; -/** Multires structs kept for compatibility with old files. */ -typedef struct MultiresCol { - float a, r, g, b; -} MultiresCol; - -typedef struct MultiresColFace { - /* vertex colors */ - MultiresCol col[4]; -} MultiresColFace; - -typedef struct MultiresFace { - unsigned int v[4]; - unsigned int mid; - char flag, mat_nr, _pad[2]; -} MultiresFace; - -typedef struct MultiresEdge { - unsigned int v[2]; - unsigned int mid; -} MultiresEdge; - -typedef struct MultiresLevel { - struct MultiresLevel *next, *prev; - - MultiresFace *faces; - MultiresColFace *colfaces; - MultiresEdge *edges; - - unsigned int totvert, totface, totedge; - char _pad[4]; - - /* Kept for compatibility with even older files */ - MVert *verts; -} MultiresLevel; - -typedef struct Multires { - ListBase levels; - MVert *verts; - - unsigned char level_count, current, newlvl, edgelvl, pinlvl, renderlvl; - unsigned char use_col, flag; - - /* Special level 1 data that cannot be modified from other levels */ - CustomData vdata; - CustomData fdata; - short *edge_flags; - char *edge_creases; -} Multires; -/* End multi-res structs. */ - /** \} */ -- cgit v1.2.3 From 107199426c845bc76a46ea25fe07e63a4ce6f8c4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 22 Oct 2020 12:28:31 +0200 Subject: Multires: Cleanup, unused code --- source/blender/blenkernel/intern/multires.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index bd9b1b24844..42a7869f047 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -76,7 +76,6 @@ typedef enum { ADD_DISPLACEMENTS, } DispOp; -static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert); static void multiresModifier_disp_run( DerivedMesh *dm, Mesh *me, DerivedMesh *dm2, DispOp op, CCGElem **oldGridData, int totlvl); @@ -429,12 +428,6 @@ void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl) mmd->renderlvl = CLAMPIS(MAX2(mmd->renderlvl, lvl), 0, mmd->totlvl); } -static void multires_dm_mark_as_modified(DerivedMesh *dm, MultiresModifiedFlags flags) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; - ccgdm->multires.modified_flags |= flags; -} - static void multires_ccg_mark_as_modified(SubdivCCG *subdiv_ccg, MultiresModifiedFlags flags) { if (flags & MULTIRES_COORDS_MODIFIED) { -- cgit v1.2.3 From dea3b8d9844f1487fc2effbb26f2e9d607c3b0fd Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 22 Oct 2020 12:41:18 +0200 Subject: Multires: Remove legacy subdivision code Is no longer used, fully replaced with more powerful algorithm. --- source/blender/blenkernel/BKE_multires.h | 5 - source/blender/blenkernel/intern/multires.c | 139 ---------------------------- 2 files changed, 144 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 8ed3741c659..763011c8d92 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -113,11 +113,6 @@ int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph, struct MultiresModifierData *mmd, int rebuild_limit, bool switch_view_to_lower_level); -void multiresModifier_subdivide_legacy(struct MultiresModifierData *mmd, - struct Scene *scene, - struct Object *ob, - int updateblock, - int simple); void multiresModifier_sync_levels_ex(struct Object *ob_dst, struct MultiresModifierData *mmd_src, struct MultiresModifierData *mmd_dst); diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 42a7869f047..d7ea662a5d6 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -63,7 +63,6 @@ #include /* MULTIRES MODIFIER */ -static const int multires_max_levels = 13; static const int multires_grid_tot[] = { 0, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; static const int multires_side_tot[] = { @@ -240,40 +239,6 @@ static void multires_mdisps_subdivide_hidden(MDisps *md, int new_level) md->hidden = subd; } -static MDisps *multires_mdisps_init_hidden(Mesh *me, int level) -{ - MDisps *mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop); - int gridsize = BKE_ccg_gridsize(level); - int gridarea = square_i(gridsize); - int i, j; - - for (i = 0; i < me->totpoly; i++) { - bool hide = false; - - for (j = 0; j < me->mpoly[i].totloop; j++) { - if (me->mvert[me->mloop[me->mpoly[i].loopstart + j].v].flag & ME_HIDE) { - hide = true; - break; - } - } - - if (!hide) { - continue; - } - - for (j = 0; j < me->mpoly[i].totloop; j++) { - MDisps *md = &mdisps[me->mpoly[i].loopstart + j]; - - BLI_assert(!md->hidden); - - md->hidden = BLI_BITMAP_NEW(gridarea, "MDisps.hidden initialize"); - BLI_bitmap_set_all(md->hidden, true, gridarea); - } - } - - return mdisps; -} - Mesh *BKE_multires_create_mesh(struct Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd) @@ -843,110 +808,6 @@ static DerivedMesh *subsurf_dm_create_local(Scene *scene, return subsurf_make_derived_from_derived(dm, &smd, scene, NULL, flags); } -static void multires_subdivide_legacy( - MultiresModifierData *mmd, Scene *scene, Object *ob, int totlvl, int updateblock, int simple) -{ - Mesh *me = ob->data; - MDisps *mdisps; - const int lvl = mmd->totlvl; - - if ((totlvl > multires_max_levels) || (me->totpoly == 0)) { - return; - } - - BLI_assert(totlvl > lvl); - - multires_force_sculpt_rebuild(ob); - - mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); - if (!mdisps) { - mdisps = multires_mdisps_init_hidden(me, totlvl); - } - - if (mdisps->disps && !updateblock && lvl != 0) { - /* upsample */ - DerivedMesh *lowdm, *cddm, *highdm; - CCGElem **highGridData, **lowGridData, **subGridData; - CCGKey highGridKey, lowGridKey; - CCGSubSurf *ss; - int i, numGrids, highGridSize; - const bool has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK); - - /* create subsurf DM from original mesh at high level */ - cddm = CDDM_from_mesh(me); - DM_set_only_copy(cddm, &CD_MASK_BAREMESH); - highdm = subsurf_dm_create_local(NULL, - ob, - cddm, - totlvl, - simple, - 0, - mmd->uv_smooth == SUBSURF_UV_SMOOTH_NONE, - has_mask, - false, - SUBSURF_IGNORE_SIMPLIFY); - ss = ((CCGDerivedMesh *)highdm)->ss; - - /* create multires DM from original mesh at low level */ - lowdm = multires_dm_create_local( - scene, ob, cddm, lvl, lvl, simple, has_mask, MULTIRES_IGNORE_SIMPLIFY); - BLI_assert(lowdm != cddm); - cddm->release(cddm); - - /* copy subsurf grids and replace them with low displaced grids */ - numGrids = highdm->getNumGrids(highdm); - highGridSize = highdm->getGridSize(highdm); - highGridData = highdm->getGridData(highdm); - highdm->getGridKey(highdm, &highGridKey); - lowGridData = lowdm->getGridData(lowdm); - lowdm->getGridKey(lowdm, &lowGridKey); - - subGridData = MEM_calloc_arrayN(numGrids, sizeof(float *), "subGridData*"); - - for (i = 0; i < numGrids; i++) { - /* backup subsurf grids */ - subGridData[i] = MEM_calloc_arrayN( - highGridKey.elem_size, highGridSize * highGridSize, "subGridData"); - memcpy(subGridData[i], highGridData[i], highGridKey.elem_size * highGridSize * highGridSize); - - /* overwrite with current displaced grids */ - multires_copy_dm_grid(highGridData[i], lowGridData[i], &highGridKey, &lowGridKey); - } - - /* low lower level dm no longer needed at this point */ - lowdm->release(lowdm); - - /* subsurf higher levels again with displaced data */ - ccgSubSurf_updateFromFaces(ss, lvl, NULL, 0); - ccgSubSurf_updateLevels(ss, lvl, NULL, 0); - - /* reallocate displacements */ - multires_reallocate_mdisps(me->totloop, mdisps, totlvl); - - /* compute displacements */ - multiresModifier_disp_run(highdm, me, NULL, CALC_DISPLACEMENTS, subGridData, totlvl); - - /* free */ - highdm->release(highdm); - for (i = 0; i < numGrids; i++) { - MEM_freeN(subGridData[i]); - } - MEM_freeN(subGridData); - } - else { - /* only reallocate, nothing to upsample */ - multires_reallocate_mdisps(me->totloop, mdisps, totlvl); - } - - multires_set_tot_level(ob, mmd, totlvl); -} - -void multiresModifier_subdivide_legacy( - MultiresModifierData *mmd, Scene *scene, Object *ob, int updateblock, int simple) -{ - multires_subdivide_legacy(mmd, scene, ob, mmd->totlvl + 1, updateblock, simple); -} - static void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *grid, float t[3]) { if (axis == 0) { -- cgit v1.2.3 From 992a88b38b40ab09503b579e7e458ef782e524ea Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 22 Oct 2020 15:14:28 +0200 Subject: Pose: Add a 'pose_ensure' new utils that only rebuilds if needed. Avoids having to spread the check logic everywhere in the code. --- source/blender/blenkernel/BKE_armature.h | 4 ++++ source/blender/blenkernel/intern/armature.c | 21 ++++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 4e8775aefb3..db44a771095 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -180,6 +180,10 @@ void BKE_pose_rebuild(struct Main *bmain, struct Object *ob, struct bArmature *arm, const bool do_id_user); +void BKE_pose_ensure(struct Main *bmain, + struct Object *ob, + struct bArmature *arm, + const bool do_id_user); void BKE_pose_where_is(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); void BKE_pose_where_is_bone(struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 7b8ed47c513..4aa328fcb22 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2573,6 +2573,19 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_ } } +/** + * Ensures object's pose is rebuilt if needed. + * + * \param bmain: May be NULL, only used to tag depsgraph as being dirty... + */ +void BKE_pose_ensure(Main *bmain, Object *ob, bArmature *arm, const bool do_id_user) +{ + BLI_assert(!ELEM(NULL, arm, ob)); + if ((ob->pose == NULL) || (ob->pose->flag & POSE_RECALC)) { + BKE_pose_rebuild(bmain, ob, arm, do_id_user); + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -2711,11 +2724,9 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob) if (ELEM(NULL, arm, scene)) { return; } - if ((ob->pose == NULL) || (ob->pose->flag & POSE_RECALC)) { - /* WARNING! passing NULL bmain here means we won't tag depsgraph's as dirty - - * hopefully this is OK. */ - BKE_pose_rebuild(NULL, ob, arm, true); - } + /* WARNING! passing NULL bmain here means we won't tag depsgraph's as dirty - + * hopefully this is OK. */ + BKE_pose_ensure(NULL, ob, arm, true); ctime = BKE_scene_frame_get(scene); /* not accurate... */ -- cgit v1.2.3 From f73dad211b1dcb94aa83d7447a1a7d1d3ea641c1 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 22 Oct 2020 15:20:04 +0200 Subject: Potential fix for T81963: Random crashes in liboverride code. From the backtrace it looks like in some cases file save (which triggers a general override updates) is done before other code has a chance to re-generate pose data, leading to rna accessing freed memory. I was never able to reproduce that here, so this is a tentative fix in master, if it proves to be working for the studio it will be cherry-picked into 2.91 release branch later. --- source/blender/blenkernel/intern/lib_override.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source') diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index e008058ae39..3bac0cf6289 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -1422,6 +1422,15 @@ void BKE_lib_override_library_main_operations_create(Main *bmain, const bool for FOREACH_MAIN_ID_BEGIN (bmain, id) { if (ID_IS_OVERRIDE_LIBRARY_REAL(id) && (force_auto || (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH))) { + /* Usual issue with pose, it's quiet rare but sometimes they may not be up to date when this + * function is called. */ + if (GS(id->name) == ID_OB) { + Object *ob = (Object *)id; + if (ob->type == OB_ARMATURE) { + BLI_assert(ob->data != NULL); + BKE_pose_ensure(bmain, ob, ob->data, true); + } + } /* Only check overrides if we do have the real reference data available, and not some empty * 'placeholder' for missing data (broken links). */ if ((id->override_library->reference->tag & LIB_TAG_MISSING) == 0) { -- cgit v1.2.3 From 73ba3e2a9ea15a77994fb27a855e0a6e5f232950 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Wed, 21 Oct 2020 16:44:28 +0200 Subject: Sculpt: Remove tools with missing icons experimental option All tools planned for 2.91 now have icons, so this option can be removed. Reviewed By: dfelinto, Severin Differential Revision: https://developer.blender.org/D9299 --- source/blender/makesdna/DNA_userdef_types.h | 3 +-- source/blender/makesrna/intern/rna_userdef.c | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'source') diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index ad032a6d7b6..4a02ac8f429 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -633,10 +633,9 @@ typedef struct UserDef_Experimental { char use_new_hair_type; char use_new_point_cloud_type; char use_sculpt_vertex_colors; - char use_tools_missing_icons; char use_switch_object_operator; char use_sculpt_tools_tilt; - char _pad[6]; + char _pad[7]; /** `makesdna` does not allow empty structs. */ } UserDef_Experimental; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 061026288e6..c31766efe58 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -6175,10 +6175,6 @@ static void rna_def_userdef_experimental(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Switch Object Operator", "Enable the operator to switch objects by pressing D"); - prop = RNA_def_property(srna, "use_tools_missing_icons", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "use_tools_missing_icons", 1); - RNA_def_property_ui_text(prop, "Tools with Missing Icons", "Show tools with missing icons"); - prop = RNA_def_property(srna, "use_sculpt_tools_tilt", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_sculpt_tools_tilt", 1); RNA_def_property_ui_text( -- cgit v1.2.3 From 5b35f1ed2b8362bbf6935b1df2829df00aef0b72 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Thu, 22 Oct 2020 17:04:54 +0200 Subject: GPencil: Fix unreported mistake in material index for trace imagens The material index was not used and only worked with new objects. --- source/blender/editors/gpencil/gpencil_trace_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source') diff --git a/source/blender/editors/gpencil/gpencil_trace_utils.c b/source/blender/editors/gpencil/gpencil_trace_utils.c index 05973afe80c..544cb4fef1e 100644 --- a/source/blender/editors/gpencil/gpencil_trace_utils.c +++ b/source/blender/editors/gpencil/gpencil_trace_utils.c @@ -294,7 +294,7 @@ void ED_gpencil_trace_data_to_strokes(Main *bmain, n = path->curve.n; tag = path->curve.tag; c = path->curve.c; - int mat_idx = path->sign == '+' ? 0 : 1; + int mat_idx = path->sign == '+' ? mat_fill_idx : mat_mask_idx; /* Create a new stroke. */ bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, mat_idx, 0, thickness, false); /* Last point that is equals to start point. */ -- cgit v1.2.3 From 6180ecaea501ef97efd7eb022ed15d9740191224 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 22 Oct 2020 10:25:08 -0500 Subject: Fix T81909: Translation missing for some labels in modifier panels Every label string in uiItem* calls needs an IFACE_ call. --- source/blender/modifiers/intern/MOD_datatransfer.c | 2 +- source/blender/modifiers/intern/MOD_hook.c | 8 ++++---- source/blender/modifiers/intern/MOD_solidify.c | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'source') diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index 94dc8a8c43b..17d716b731c 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -268,7 +268,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL); - uiItemO(layout, "Generate Data Layers", ICON_NONE, "OBJECT_OT_datalayout_transfer"); + uiItemO(layout, IFACE_("Generate Data Layers"), ICON_NONE, "OBJECT_OT_datalayout_transfer"); modifier_panel_end(layout, ptr); } diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index def72af45e8..e0c362171f2 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -492,11 +492,11 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) if (RNA_enum_get(&ob_ptr, "mode") == OB_MODE_EDIT) { row = uiLayoutRow(layout, true); - uiItemO(row, "Reset", ICON_NONE, "OBJECT_OT_hook_reset"); - uiItemO(row, "Recenter", ICON_NONE, "OBJECT_OT_hook_recenter"); + uiItemO(row, IFACE_("Reset"), ICON_NONE, "OBJECT_OT_hook_reset"); + uiItemO(row, IFACE_("Recenter"), ICON_NONE, "OBJECT_OT_hook_recenter"); row = uiLayoutRow(layout, true); - uiItemO(row, "Select", ICON_NONE, "OBJECT_OT_hook_select"); - uiItemO(row, "Assign", ICON_NONE, "OBJECT_OT_hook_assign"); + uiItemO(row, IFACE_("Select"), ICON_NONE, "OBJECT_OT_hook_select"); + uiItemO(row, IFACE_("Assign"), ICON_NONE, "OBJECT_OT_hook_assign"); } modifier_panel_end(layout, ptr); diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index c4f0fff72dd..8886d3718c9 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -230,8 +230,9 @@ static void vertex_group_panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); col = uiLayoutColumn(layout, false); - uiItemPointerR(col, ptr, "shell_vertex_group", &ob_ptr, "vertex_groups", "Shell", ICON_NONE); - uiItemPointerR(col, ptr, "rim_vertex_group", &ob_ptr, "vertex_groups", "Rim", ICON_NONE); + uiItemPointerR( + col, ptr, "shell_vertex_group", &ob_ptr, "vertex_groups", IFACE_("Shell"), ICON_NONE); + uiItemPointerR(col, ptr, "rim_vertex_group", &ob_ptr, "vertex_groups", IFACE_("Rim"), ICON_NONE); } static void panelRegister(ARegionType *region_type) -- cgit v1.2.3 From 2985a745bb016c43e837b908fbd873e2daff3440 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Thu, 22 Oct 2020 17:35:48 +0200 Subject: GPencil: Add new parameter to set caps in Cutter The new parameter allows to define if after cutting the stroke the cap of the cut side will be set as flat. Before, the cap shape of the cut side always was equal to the original stroke, and in some situations, the rounded cap was visible. Note: If the angle of the join is very extreme, it's still possible to view some sections of the cut stroke., --- source/blender/editors/gpencil/gpencil_edit.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index d54bdf552eb..7d79e748f75 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -4678,7 +4678,9 @@ typedef bool (*GPencilTestFn)(bGPDstroke *gps, const float diff_mat[4][4], void *user_data); -static void gpencil_cutter_dissolve(bGPDlayer *hit_layer, bGPDstroke *hit_stroke) +static void gpencil_cutter_dissolve(bGPDlayer *hit_layer, + bGPDstroke *hit_stroke, + const bool flat_caps) { bGPDspoint *pt = NULL; bGPDspoint *pt1 = NULL; @@ -4722,6 +4724,17 @@ static void gpencil_cutter_dissolve(bGPDlayer *hit_layer, bGPDstroke *hit_stroke pt->flag &= ~GP_SPOINT_TAG; } } + /* If flat caps mode check extremes. */ + if (flat_caps) { + if (hit_stroke->points[0].flag & GP_SPOINT_TAG) { + hit_stroke->caps[0] = GP_STROKE_CAP_FLAT; + } + + if (hit_stroke->points[hit_stroke->totpoints - 1].flag & GP_SPOINT_TAG) { + hit_stroke->caps[1] = GP_STROKE_CAP_FLAT; + } + } + gpencil_stroke_delete_tagged_points( hit_layer->actframe, hit_stroke, gpsn, GP_SPOINT_TAG, false, 1); } @@ -4736,6 +4749,7 @@ static int gpencil_cutter_lasso_select(bContext *C, ScrArea *area = CTX_wm_area(C); ToolSettings *ts = CTX_data_tool_settings(C); const float scale = ts->gp_sculpt.isect_threshold; + const bool flat_caps = RNA_boolean_get(op->ptr, "flat_caps"); bGPDspoint *pt; GP_SpaceConversion gsc = {NULL}; @@ -4810,7 +4824,7 @@ static int gpencil_cutter_lasso_select(bContext *C, } LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { if (gps->flag & GP_STROKE_SELECT) { - gpencil_cutter_dissolve(gpl, gps); + gpencil_cutter_dissolve(gpl, gps, flat_caps); } } } @@ -4884,6 +4898,8 @@ void GPENCIL_OT_stroke_cutter(wmOperatorType *ot) /* properties */ WM_operator_properties_gesture_lasso(ot); + + RNA_def_boolean(ot->srna, "flat_caps", 0, "Flat Caps", ""); } bool ED_object_gpencil_exit(struct Main *bmain, Object *ob) -- cgit v1.2.3 From b5169cd2301a021a367fcaee69aa66c262565bb3 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Wed, 21 Oct 2020 22:53:50 +0200 Subject: Fix T81932: Dyntopo crashing with sculpt vertex colors brush tools Paint and smear tools are only implemented for regular mesh PBVH, meaning they are not supported by the dynamic topology and multires sculpting. These tools are to be ignored for an unsupported sculpt modes, regardless of state of user preferences. Reviewed By: sergey Maniphest Tasks: T81932 Differential Revision: https://developer.blender.org/D9308 --- source/blender/editors/sculpt_paint/sculpt.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'source') diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index adc62b23559..3ffa2091560 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -5666,15 +5666,11 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe /* Check for unsupported features. */ PBVHType type = BKE_pbvh_type(ss->pbvh); if (brush->sculpt_tool == SCULPT_TOOL_PAINT && type != PBVH_FACES) { - if (!U.experimental.use_sculpt_vertex_colors) { - return; - } + return; } if (brush->sculpt_tool == SCULPT_TOOL_SMEAR && type != PBVH_FACES) { - if (!U.experimental.use_sculpt_vertex_colors) { - return; - } + return; } /* Build a list of all nodes that are potentially within the brush's area of influence */ -- cgit v1.2.3 From 383c20a6abd6591a3a402504b37fdecaa64fde0f Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Thu, 22 Oct 2020 19:06:00 +0200 Subject: Sculpt: Grab silhouette option This adds a property to the grab that masks vertices based on its original normal and grab delta. When used on thin meshes, it allows to grab the silhouette from one side of the object without affecting the shape of the other side. Reviewed By: sergey Differential Revision: https://developer.blender.org/D9205 --- source/blender/editors/sculpt_paint/sculpt.c | 31 ++++++++++++++++++++-------- source/blender/makesdna/DNA_brush_types.h | 1 + source/blender/makesrna/intern/rna_brush.c | 6 ++++++ 3 files changed, 29 insertions(+), 9 deletions(-) (limited to 'source') diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 3ffa2091560..8e7935e821d 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -3805,20 +3805,33 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata, ss, &test, data->brush->falloff_shape); const int thread_id = BLI_task_parallel_thread_id(tls); + const bool grab_silhouette = brush->flag2 & BRUSH_GRAB_SILHOUETTE; + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + if (grab_silhouette) { + float silhouette_test_dir[3]; + normalize_v3_v3(silhouette_test_dir, grab_delta); + if (dot_v3v3(ss->cache->initial_normal, ss->cache->grab_delta) < 0.0f) { + mul_v3_fl(silhouette_test_dir, -1.0f); + } + float vno[3]; + normal_short_to_float_v3(vno, orig_data.no); + fade *= max_ff(dot_v3v3(vno, silhouette_test_dir), 0.0f); + } mul_v3_v3fl(proxy[vd.i], grab_delta, fade); diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 37b7947dbea..713f5ee2afa 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -775,6 +775,7 @@ typedef enum eBrushFlags2 { BRUSH_POSE_USE_LOCK_ROTATION = (1 << 5), BRUSH_CLOTH_USE_COLLISION = (1 << 6), BRUSH_AREA_RADIUS_PRESSURE = (1 << 7), + BRUSH_GRAB_SILHOUETTE = (1 << 8), } eBrushFlags2; typedef enum { diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index d119be66916..6f227ec210c 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -2968,6 +2968,12 @@ static void rna_def_brush(BlenderRNA *brna) "Apply the maximum grab strength to the active vertex instead of the cursor location"); RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "use_grab_silhouette", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", BRUSH_GRAB_SILHOUETTE); + RNA_def_property_ui_text( + prop, "Grab Silhouette", "Grabs trying to automask the silhouette of the object"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "use_paint_antialiasing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "sampling_flag", BRUSH_PAINT_ANTIALIASING); RNA_def_property_ui_text(prop, "Anti-Aliasing", "Smooths the edges of the strokes"); -- cgit v1.2.3 From 3953833b60d73a1560f5ec70fd449113da4b83c9 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 22 Oct 2020 12:20:34 -0500 Subject: Fix T81967: Crash when using extrude on a text object Caused by rBa308607a5334, which mistakenly removed these lines. --- source/blender/blenkernel/intern/displist.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source') diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index f47f350a435..ff03731b2aa 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -607,6 +607,9 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) float *fp, *fp1; int a, dpoly; + BLI_listbase_clear(&front); + BLI_listbase_clear(&back); + LISTBASE_FOREACH (DispList *, dl, dispbase) { if (dl->type == DL_SURF) { if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U) == 0) { -- cgit v1.2.3 From 8432452f6fcb5f96df900250700f7fed7dfa32b5 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Thu, 22 Oct 2020 20:01:39 +0200 Subject: GPencil: Fix unreported crash using layer solo mode and masked layers The solo mode was skipping the layer creation data and the loop of masks expect to have all layers in the array or the loop crash. The solution is just create the layer array data for the layer, but don't draw any stroke. --- source/blender/blenkernel/intern/gpencil.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 31cd812f8df..6c6ca996caa 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -2549,17 +2549,17 @@ void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer, /* Use evaluated frame (with modifiers for active stroke)/ */ act_gpf = gpl->actframe; if (act_gpf) { + act_gpf->runtime.onion_id = 0; + if (layer_cb) { + layer_cb(gpl, act_gpf, NULL, thunk); + } + /* If layer solo mode and Paint mode, only keyframes with data are displayed. */ if (GPENCIL_PAINT_MODE(gpd) && (gpl->flag & GP_LAYER_SOLO_MODE) && (act_gpf->framenum != cfra)) { continue; } - act_gpf->runtime.onion_id = 0; - if (layer_cb) { - layer_cb(gpl, act_gpf, NULL, thunk); - } - LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) { if (gps->totpoints == 0) { continue; -- cgit v1.2.3 From 3d916c0a966c96fa394d219be4029ca27d68d198 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 22 Oct 2020 15:46:35 -0500 Subject: Cleanup: Simplify outliner mode column drawing function Move the checks for whether to draw the button to the beginning of the function and return early. Also use a shorthand variable for ob_active. Committing to 2.91 as a patch for an upcoming bug fix depends on these changes. Differential Revision: https://developer.blender.org/D9272 --- .../blender/editors/space_outliner/outliner_draw.c | 103 +++++++++++---------- 1 file changed, 54 insertions(+), 49 deletions(-) (limited to 'source') diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 09ccb950c18..3045529747d 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1947,60 +1947,65 @@ static void outliner_draw_mode_column_toggle(uiBlock *block, TreeStoreElem *tselem, const bool lock_object_modes) { - const int active_mode = tvc->obact->mode; - bool draw_active_icon = true; + if (tselem->type != 0 || te->idcode != ID_OB) { + return; + } - if (tselem->type == 0 && te->idcode == ID_OB) { - Object *ob = (Object *)tselem->id; + Object *ob = (Object *)tselem->id; + Object *ob_active = tvc->obact; - /* When not locking object modes, objects can remain in non-object modes. For modes that do not - * allow multi-object editing, these other objects should still show be viewed as not in the - * mode. Otherwise multiple objects show the same mode icon in the outliner even though only - * one object is actually editable in the mode. */ - if (!lock_object_modes && ob != tvc->obact && !(tvc->ob_edit || tvc->ob_pose)) { - draw_active_icon = false; - } + /* Not all objects support particle systems. */ + if (ob_active->mode == OB_MODE_PARTICLE_EDIT && !psys_get_current(ob)) { + return; + } - if (ob->type == tvc->obact->type) { - int icon; - const char *tip; + /* Only for objects with the same type. */ + if (ob->type != ob_active->type) { + return; + } - if (draw_active_icon && ob->mode == tvc->obact->mode) { - icon = UI_icon_from_object_mode(active_mode); - tip = TIP_("Remove from the current mode"); - } - else { - /* Not all objects support particle systems */ - if (active_mode == OB_MODE_PARTICLE_EDIT && !psys_get_current(ob)) { - return; - } - icon = ICON_DOT; - tip = TIP_( - "Change the object in the current mode\n" - "* Ctrl to add to the current mode"); - } + bool draw_active_icon = ob->mode == ob_active->mode; - uiBut *but = uiDefIconBut(block, - UI_BTYPE_ICON_TOGGLE, - 0, - icon, - 0, - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0.0, - 0.0, - tip); - UI_but_func_set(but, outliner_mode_toggle_fn, tselem, NULL); - UI_but_flag_enable(but, UI_BUT_DRAG_LOCK); - - if (ID_IS_LINKED(&ob->id)) { - UI_but_disable(but, TIP_("Can't edit external library data")); - } - } + /* When not locking object modes, objects can remain in non-object modes. For modes that do not + * allow multi-object editing, these other objects should still show be viewed as not in the + * mode. Otherwise multiple objects show the same mode icon in the outliner even though only + * one object is actually editable in the mode. */ + if (!lock_object_modes && ob != ob_active && !(tvc->ob_edit || tvc->ob_pose)) { + draw_active_icon = false; + } + + int icon; + const char *tip; + if (draw_active_icon) { + icon = UI_icon_from_object_mode(ob_active->mode); + tip = TIP_("Remove from the current mode"); + } + else { + icon = ICON_DOT; + tip = TIP_( + "Change the object in the current mode\n" + "* Ctrl to add to the current mode"); + } + + uiBut *but = uiDefIconBut(block, + UI_BTYPE_ICON_TOGGLE, + 0, + icon, + 0, + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + tip); + UI_but_func_set(but, outliner_mode_toggle_fn, tselem, NULL); + UI_but_flag_enable(but, UI_BUT_DRAG_LOCK); + + if (ID_IS_LINKED(&ob->id)) { + UI_but_disable(but, TIP_("Can't edit external library data")); } } -- cgit v1.2.3 From a3f5154448b17e282dd00d33b90cbee94b20d679 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Thu, 22 Oct 2020 17:08:37 -0400 Subject: Cleanup: make format --- source/blender/blenkernel/intern/shrinkwrap.c | 4 ++-- source/blender/blenlib/intern/delaunay_2d.cc | 4 ++-- source/blender/editors/space_file/file_ops.c | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 0c9ee61ca19..ae39b200b56 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -1548,8 +1548,8 @@ void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object ssmd.shrinkMode = MOD_SHRINKWRAP_ON_SURFACE; ssmd.shrinkOpts = MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR | MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR; ssmd.keepDist = 0.0f; - - /* Tolerance value to prevent artifacts on sharp edges of a mesh. + + /* Tolerance value to prevent artifacts on sharp edges of a mesh. * This constant and based on experimenting with different values. */ const float projLimitTolerance = 5.0f; ssmd.projLimit = target_me->remesh_voxel_size * projLimitTolerance; diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc index ac3662284d0..60439f27b01 100644 --- a/source/blender/blenlib/intern/delaunay_2d.cc +++ b/source/blender/blenlib/intern/delaunay_2d.cc @@ -1308,8 +1308,8 @@ template inline int tri_orient(const SymEdge *t) * For case (a), 'vert' will be the vertex, and lambda will be 0, and 'in' will be the #SymEdge * from 'vert' that has as face the one that you go through to get to this vertex. If you go * exactly along an edge then we set 'in' to NULL, since it won't be needed. The first crossing - * will have 'in' = NULL. We set 'out' to the #SymEdge that has the face we go through to get to the - * next crossing, or, if the next crossing is a case (a), then it is the edge that goes to that + * will have 'in' = NULL. We set 'out' to the #SymEdge that has the face we go through to get to + * the next crossing, or, if the next crossing is a case (a), then it is the edge that goes to that * next vertex. 'out' will be NULL for the last one. * * For case (b), vert will be NULL at first, and later filled in with the created split vertex, diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 91653fb7785..7cfd749d013 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -2415,7 +2415,8 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN WM_operator_properties_create_ptr(&ptr, ot); RNA_string_set(&ptr, "directory", sfile->params->dir); RNA_boolean_set(&ptr, "open", true); - /* Enable confirmation prompt, else it's too easy to accidentally create new directories. */ + /* Enable confirmation prompt, else it's too easy + * to accidentally create new directories. */ RNA_boolean_set(&ptr, "confirm", true); if (lastdir) { -- cgit v1.2.3 From baa24f1c91d21e10f51881f8fad012f30f99e26f Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Thu, 22 Oct 2020 17:20:57 -0400 Subject: Pydoc: Fix sphinx compile warnings about freestyle Sphinx expects functions and methods with the same name and different parameters to be written using one directive. See: https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#basic-markup Unfortunately this makes giving different descriptions for each harder. This was already a request for better support for this in sphinx, see: https://github.com/sphinx-doc/sphinx/issues/7787 Reviewed By: campbellbarton Differential Revision: https://developer.blender.org/D9170 --- .../freestyle/intern/python/BPy_FrsMaterial.cpp | 17 +- source/blender/freestyle/intern/python/BPy_Id.cpp | 33 ++-- .../freestyle/intern/python/BPy_Operators.cpp | 183 +++++++-------------- .../blender/freestyle/intern/python/BPy_SShape.cpp | 26 ++- .../intern/python/BPy_StrokeAttribute.cpp | 24 +-- .../freestyle/intern/python/BPy_ViewShape.cpp | 14 +- .../intern/python/Interface0D/BPy_CurvePoint.cpp | 32 ++-- .../intern/python/Interface0D/BPy_SVertex.cpp | 15 +- .../Interface0D/CurvePoint/BPy_StrokeVertex.cpp | 35 +--- .../Interface0D/ViewVertex/BPy_NonTVertex.cpp | 30 ++-- .../intern/python/Interface1D/BPy_FEdge.cpp | 13 +- .../intern/python/Interface1D/BPy_FrsCurve.cpp | 14 +- .../intern/python/Interface1D/BPy_Stroke.cpp | 28 ++-- .../intern/python/Interface1D/BPy_ViewEdge.cpp | 32 ++-- .../intern/python/Interface1D/Curve/BPy_Chain.cpp | 14 +- .../python/Interface1D/FEdge/BPy_FEdgeSharp.cpp | 14 +- .../python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp | 14 +- .../python/Iterator/BPy_AdjacencyIterator.cpp | 14 +- .../python/Iterator/BPy_ChainPredicateIterator.cpp | 95 ++++++----- .../Iterator/BPy_ChainSilhouetteIterator.cpp | 8 +- .../python/Iterator/BPy_ChainingIterator.cpp | 12 +- .../python/Iterator/BPy_CurvePointIterator.cpp | 14 +- .../python/Iterator/BPy_Interface0DIterator.cpp | 10 +- .../intern/python/Iterator/BPy_SVertexIterator.cpp | 60 +++---- .../python/Iterator/BPy_StrokeVertexIterator.cpp | 8 +- .../python/Iterator/BPy_ViewEdgeIterator.cpp | 8 +- .../Iterator/BPy_orientedViewEdgeIterator.cpp | 8 +- .../UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp | 9 +- .../BPy_UnaryFunction1DEdgeNature.cpp | 9 +- .../UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp | 9 +- .../BPy_UnaryFunction1DUnsigned.cpp | 9 +- .../UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp | 9 +- .../UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp | 9 +- .../BPy_UnaryFunction1DVectorViewShape.cpp | 9 +- .../UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp | 9 +- 35 files changed, 306 insertions(+), 541 deletions(-) (limited to 'source') diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp index dbf1c12fb01..3efabbfbdf5 100644 --- a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp +++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp @@ -55,21 +55,14 @@ PyDoc_STRVAR( "Class defining a material.\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(line, diffuse, ambient, specular, emission, shininess, priority)\n" "\n" - " Default constructor.\n" + " Creates a :class:`FrsMaterial` using either default constructor,\n" + " copy constructor, or an overloaded constructor\n" "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" - "\n" - " :arg brother: A Material object.\n" + " :arg brother: A Material object to be used as a copy constructor.\n" " :type brother: :class:`Material`\n" - "\n" - ".. method:: __init__(line, diffuse, ambient, specular, emission, shininess, priority)\n" - "\n" - " Builds a Material from its line, diffuse, ambient, specular, emissive\n" - " colors, a shininess coefficient and line color priority.\n" - "\n" " :arg line: The line color.\n" " :type line: :class:`mathutils.Vector`, list or tuple of 4 float values\n" " :arg diffuse: The diffuse color.\n" diff --git a/source/blender/freestyle/intern/python/BPy_Id.cpp b/source/blender/freestyle/intern/python/BPy_Id.cpp index eb0eb661e3d..8f61f7f3e14 100644 --- a/source/blender/freestyle/intern/python/BPy_Id.cpp +++ b/source/blender/freestyle/intern/python/BPy_Id.cpp @@ -46,24 +46,21 @@ int Id_Init(PyObject *module) //------------------------INSTANCE METHODS ---------------------------------- -PyDoc_STRVAR(Id_doc, - "Class for representing an object Id.\n" - "\n" - ".. method:: __init__(first=0, second=0)\n" - "\n" - " Build the Id from two numbers.\n" - "\n" - " :arg first: The first number.\n" - " :type first: int\n" - " :arg second: The second number.\n" - " :type second: int\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" - "\n" - " :arg brother: An Id object.\n" - " :type brother: :class:`Id`"); +PyDoc_STRVAR( + Id_doc, + "Class for representing an object Id.\n" + "\n" + ".. method:: __init__(brother)\n" + " __init__(first=0, second=0)\n" + "\n" + " Build the Id from two numbers or another :class:`Id` using the copy constructor.\n" + "\n" + " :arg brother: An Id object.\n" + " :type brother: :class:`Id`" + " :arg first: The first number.\n" + " :type first: int\n" + " :arg second: The second number.\n" + " :type second: int\n"); static int Id_init(BPy_Id *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp index 56f95b8ecbb..1235786d5d3 100644 --- a/source/blender/freestyle/intern/python/BPy_Operators.cpp +++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp @@ -101,6 +101,7 @@ static PyObject *Operators_select(BPy_Operators * /*self*/, PyObject *args, PyOb PyDoc_STRVAR(Operators_chain_doc, ".. staticmethod:: chain(it, pred, modifier)\n" + " chain(it, pred)\n" "\n" " Builds a set of chains from the current set of ViewEdges. Each\n" " ViewEdge of the current list starts a new chain. The chaining\n" @@ -116,28 +117,9 @@ PyDoc_STRVAR(Operators_chain_doc, " :type pred: :class:`UnaryPredicate1D`\n" " :arg modifier: A function that takes a ViewEdge as argument and\n" " that is used to modify the processed ViewEdge state (the\n" - " timestamp incrementation is a typical illustration of such a\n" - " modifier).\n" - " :type modifier: :class:`UnaryFunction1DVoid`\n" - "\n" - ".. staticmethod:: chain(it, pred)\n" - "\n" - " Builds a set of chains from the current set of ViewEdges. Each\n" - " ViewEdge of the current list starts a new chain. The chaining\n" - " operator then iterates over the ViewEdges of the ViewMap using the\n" - " user specified iterator. This operator only iterates using the\n" - " increment operator and is therefore unidirectional. This chaining\n" - " operator is different from the previous one because it doesn't take\n" - " any modifier as argument. Indeed, the time stamp (insuring that a\n" - " ViewEdge is processed one time) is automatically managed in this\n" - " case.\n" - "\n" - " :arg it: The iterator on the ViewEdges of the ViewMap. It contains\n" - " the chaining rule. \n" - " :type it: :class:`ViewEdgeIterator`\n" - " :arg pred: The predicate on the ViewEdge that expresses the\n" - " stopping condition.\n" - " :type pred: :class:`UnaryPredicate1D`"); + " timestamp incrementation is a typical illustration of such a modifier).\n" + " If this argument is not given, the time stamp is automatically managed.\n" + " :type modifier: :class:`UnaryFunction1DVoid`\n"); static PyObject *Operators_chain(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds) { @@ -195,6 +177,7 @@ static PyObject *Operators_chain(BPy_Operators * /*self*/, PyObject *args, PyObj PyDoc_STRVAR(Operators_bidirectional_chain_doc, ".. staticmethod:: bidirectional_chain(it, pred)\n" + " bidirectional_chain(it)\n" "\n" " Builds a set of chains from the current set of ViewEdges. Each\n" " ViewEdge of the current list potentially starts a new chain. The\n" @@ -211,30 +194,10 @@ PyDoc_STRVAR(Operators_bidirectional_chain_doc, " :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n" " contains the chaining rule.\n" " :type it: :class:`ChainingIterator`\n" - " :arg pred: The predicate on the ViewEdge that expresses the\n" - " stopping condition.\n" - " :type pred: :class:`UnaryPredicate1D`\n" - "\n" - ".. staticmethod:: bidirectional_chain(it)\n" - "\n" - " The only difference with the above bidirectional chaining algorithm\n" - " is that we don't need to pass a stopping criterion. This might be\n" - " desirable when the stopping criterion is already contained in the\n" - " iterator definition. Builds a set of chains from the current set of\n" - " ViewEdges. Each ViewEdge of the current list potentially starts a new\n" - " chain. The chaining operator then iterates over the ViewEdges of the\n" - " ViewMap using the user specified iterator. This operator iterates\n" - " both using the increment and decrement operators and is therefore\n" - " bidirectional. This operator works with a ChainingIterator which\n" - " contains the chaining rules. It is this last one which can be told to\n" - " chain only edges that belong to the selection or not to process twice\n" - " a ViewEdge during the chaining. Each time a ViewEdge is added to a\n" - " chain, its chaining time stamp is incremented. This allows you to\n" - " keep track of the number of chains to which a ViewEdge belongs to.\n" - "\n" - " :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n" - " contains the chaining rule.\n" - " :type it: :class:`ChainingIterator`"); + " :arg pred: The predicate on the ViewEdge that expresses the stopping condition.\n" + " This parameter is optional, you make not want to pass a stopping criterion\n" + " when the stopping criterion is already contained in the iterator definition.\n" + " :type pred: :class:`UnaryPredicate1D`\n"); static PyObject *Operators_bidirectional_chain(BPy_Operators * /*self*/, PyObject *args, @@ -287,44 +250,34 @@ static PyObject *Operators_bidirectional_chain(BPy_Operators * /*self*/, PyDoc_STRVAR(Operators_sequential_split_doc, ".. staticmethod:: sequential_split(starting_pred, stopping_pred, sampling=0.0)\n" + " sequential_split(pred, sampling=0.0)\n" "\n" " Splits each chain of the current set of chains in a sequential way.\n" " The points of each chain are processed (with a specified sampling)\n" - " sequentially. Each time a user specified starting condition is\n" - " verified, a new chain begins and ends as soon as a user-defined\n" - " stopping predicate is verified. This allows chains overlapping rather\n" - " than chains partitioning. The first point of the initial chain is the\n" + " sequentially. The first point of the initial chain is the\n" " first point of one of the resulting chains. The splitting ends when\n" " no more chain can start.\n" "\n" + " .. tip::\n" + "\n" + " By specifiying a starting and stopping predicate allows\n" + " the chains to overlapp rather than chains partitioning.\n" + "\n" " :arg starting_pred: The predicate on a point that expresses the\n" - " starting condition.\n" + " starting condition. Each time this condition is verified, a new chain begins\n" " :type starting_pred: :class:`UnaryPredicate0D`\n" " :arg stopping_pred: The predicate on a point that expresses the\n" - " stopping condition.\n" + " stopping condition. The chain ends as soon as this predicate is verified.\n" " :type stopping_pred: :class:`UnaryPredicate0D`\n" + " :arg pred: The predicate on a point that expresses the splitting condition.\n" + " Each time the condition is verified, the chain is split into two chains.\n" + " The resulting set of chains is a partition of the initial chain\n" + " :type pred: :class:`UnaryPredicate0D`\n" " :arg sampling: The resolution used to sample the chain for the\n" " predicates evaluation. (The chain is not actually resampled;\n" " a virtual point only progresses along the curve using this\n" " resolution.)\n" - " :type sampling: float\n" - "\n" - ".. staticmethod:: sequential_split(pred, sampling=0.0)\n" - "\n" - " Splits each chain of the current set of chains in a sequential way.\n" - " The points of each chain are processed (with a specified sampling)\n" - " sequentially and each time a user specified condition is verified,\n" - " the chain is split into two chains. The resulting set of chains is a\n" - " partition of the initial chain\n" - "\n" - " :arg pred: The predicate on a point that expresses the splitting\n" - " condition.\n" - " :type pred: :class:`UnaryPredicate0D`\n" - " :arg sampling: The resolution used to sample the chain for the\n" - " predicate evaluation. (The chain is not actually resampled; a\n" - " virtual point only progresses along the curve using this\n" - " resolution.)\n" - " :type sampling: float"); + " :type sampling: float\n"); static PyObject *Operators_sequential_split(BPy_Operators * /*self*/, PyObject *args, @@ -389,61 +342,41 @@ static PyObject *Operators_sequential_split(BPy_Operators * /*self*/, Py_RETURN_NONE; } -PyDoc_STRVAR(Operators_recursive_split_doc, - ".. staticmethod:: recursive_split(func, pred_1d, sampling=0.0)\n" - "\n" - " Splits the current set of chains in a recursive way. We process the\n" - " points of each chain (with a specified sampling) to find the point\n" - " minimizing a specified function. The chain is split in two at this\n" - " point and the two new chains are processed in the same way. The\n" - " recursivity level is controlled through a predicate 1D that expresses\n" - " a stopping condition on the chain that is about to be processed.\n" - "\n" - " :arg func: The Unary Function evaluated at each point of the chain.\n" - " The splitting point is the point minimizing this function.\n" - " :type func: :class:`UnaryFunction0DDouble`\n" - " :arg pred_1d: The Unary Predicate expressing the recursivity stopping\n" - " condition. This predicate is evaluated for each curve before it\n" - " actually gets split. If pred_1d(chain) is true, the curve won't be\n" - " split anymore.\n" - " :type pred_1d: :class:`UnaryPredicate1D`\n" - " :arg sampling: The resolution used to sample the chain for the\n" - " predicates evaluation. (The chain is not actually resampled, a\n" - " virtual point only progresses along the curve using this\n" - " resolution.)\n" - " :type sampling: float\n" - "\n" - ".. staticmethod:: recursive_split(func, pred_0d, pred_1d, sampling=0.0)\n" - "\n" - " Splits the current set of chains in a recursive way. We process the\n" - " points of each chain (with a specified sampling) to find the point\n" - " minimizing a specified function. The chain is split in two at this\n" - " point and the two new chains are processed in the same way. The user\n" - " can specify a 0D predicate to make a first selection on the points\n" - " that can potentially be split. A point that doesn't verify the 0D\n" - " predicate won't be candidate in realizing the min. The recursivity\n" - " level is controlled through a predicate 1D that expresses a stopping\n" - " condition on the chain that is about to be processed.\n" - "\n" - " :arg func: The Unary Function evaluated at each point of the chain.\n" - " The splitting point is the point minimizing this function.\n" - " :type func: :class:`UnaryFunction0DDouble`\n" - " :arg pred_0d: The Unary Predicate 0D used to select the candidate\n" - " points where the split can occur. For example, it is very likely\n" - " that would rather have your chain splitting around its middle\n" - " point than around one of its extremities. A 0D predicate working\n" - " on the curvilinear abscissa allows to add this kind of constraints.\n" - " :type pred_0d: :class:`UnaryPredicate0D`\n" - " :arg pred_1d: The Unary Predicate expressing the recursivity stopping\n" - " condition. This predicate is evaluated for each curve before it\n" - " actually gets split. If pred_1d(chain) is true, the curve won't be\n" - " split anymore.\n" - " :type pred_1d: :class:`UnaryPredicate1D`\n" - " :arg sampling: The resolution used to sample the chain for the\n" - " predicates evaluation. (The chain is not actually resampled; a\n" - " virtual point only progresses along the curve using this\n" - " resolution.)\n" - " :type sampling: float"); +PyDoc_STRVAR( + Operators_recursive_split_doc, + ".. staticmethod:: recursive_split(func, pred_1d, sampling=0.0)\n" + " recursive_split(func, pred_0d, pred_1d, sampling=0.0)\n" + "\n" + " Splits the current set of chains in a recursive way. We process the\n" + " points of each chain (with a specified sampling) to find the point\n" + " minimizing a specified function. The chain is split in two at this\n" + " point and the two new chains are processed in the same way. The\n" + " recursivity level is controlled through a predicate 1D that expresses\n" + " a stopping condition on the chain that is about to be processed.\n" + "\n" + " The user can also specify a 0D predicate to make a first selection on the points\n" + " that can potentially be split. A point that doesn't verify the 0D\n" + " predicate won't be candidate in realizing the min.\n" + "\n" + " :arg func: The Unary Function evaluated at each point of the chain.\n" + " The splitting point is the point minimizing this function.\n" + " :type func: :class:`UnaryFunction0DDouble`\n" + " :arg pred_0d: The Unary Predicate 0D used to select the candidate\n" + " points where the split can occur. For example, it is very likely\n" + " that would rather have your chain splitting around its middle\n" + " point than around one of its extremities. A 0D predicate working\n" + " on the curvilinear abscissa allows to add this kind of constraints.\n" + " :type pred_0d: :class:`UnaryPredicate0D`\n" + " :arg pred_1d: The Unary Predicate expressing the recursivity stopping\n" + " condition. This predicate is evaluated for each curve before it\n" + " actually gets split. If pred_1d(chain) is true, the curve won't be\n" + " split anymore.\n" + " :type pred_1d: :class:`UnaryPredicate1D`\n" + " :arg sampling: The resolution used to sample the chain for the\n" + " predicates evaluation. (The chain is not actually resampled; a\n" + " virtual point only progresses along the curve using this\n" + " resolution.)\n" + " :type sampling: float\n"); static PyObject *Operators_recursive_split(BPy_Operators * /*self*/, PyObject *args, diff --git a/source/blender/freestyle/intern/python/BPy_SShape.cpp b/source/blender/freestyle/intern/python/BPy_SShape.cpp index 9712dccfa5e..b1d5f8f4aac 100644 --- a/source/blender/freestyle/intern/python/BPy_SShape.cpp +++ b/source/blender/freestyle/intern/python/BPy_SShape.cpp @@ -50,20 +50,18 @@ int SShape_Init(PyObject *module) /*----------------------SShape methods ----------------------------*/ -PyDoc_STRVAR(SShape_doc, - "Class to define a feature shape. It is the gathering of feature\n" - "elements from an identified input shape.\n" - "\n" - ".. method:: __init__()\n" - "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" - "\n" - " :arg brother: An SShape object.\n" - " :type brother: :class:`SShape`"); +PyDoc_STRVAR( + SShape_doc, + "Class to define a feature shape. It is the gathering of feature\n" + "elements from an identified input shape.\n" + "\n" + ".. method:: __init__()\n" + " __init__(brother)\n" + "\n" + " Creates a :class:`SShape` class using either a default constructor or copy constructor.\n" + "\n" + " :arg brother: An SShape object.\n" + " :type brother: :class:`SShape`"); static int SShape_init(BPy_SShape *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp index 214385f74ad..3718fddcf20 100644 --- a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp +++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp @@ -53,20 +53,16 @@ PyDoc_STRVAR(StrokeAttribute_doc, "Vertex.\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(red, green, blue, alpha, thickness_right, thickness_left)\n" + " __init__(attribute1, attribute2, t)\n" "\n" - " Default constructor.\n" + " Creates a :class:`StrokeAttribute` object using either a default constructor,\n" + " copy constructor, overloaded constructor, or and interpolation constructor\n" + " to interpolate between two :class:`StrokeAttribute` objects.\n" "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" - "\n" - " :arg brother: A StrokeAttribute object.\n" + " :arg brother: A StrokeAttribute object to be used as a copy constructor.\n" " :type brother: :class:`StrokeAttribute`\n" - "\n" - ".. method:: __init__(red, green, blue, alpha, thickness_right, thickness_left)\n" - "\n" - " Build a stroke vertex attribute from a set of parameters.\n" - "\n" " :arg red: Red component of a stroke color.\n" " :type red: float\n" " :arg green: Green component of a stroke color.\n" @@ -79,12 +75,6 @@ PyDoc_STRVAR(StrokeAttribute_doc, " :type thickness_right: float\n" " :arg thickness_left: Stroke thickness on the left.\n" " :type thickness_left: float\n" - "\n" - ".. method:: __init__(attribute1, attribute2, t)\n" - "\n" - " Interpolation constructor. Build a StrokeAttribute from two\n" - " StrokeAttribute objects and an interpolation parameter.\n" - "\n" " :arg attribute1: The first StrokeAttribute object.\n" " :type attribute1: :class:`StrokeAttribute`\n" " :arg attribute2: The second StrokeAttribute object.\n" diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp index 2adcae13e6d..7d8b5ef6fa9 100644 --- a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp +++ b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp @@ -55,20 +55,14 @@ PyDoc_STRVAR(ViewShape_doc, "and :class:`ViewEdge`) that are issued from the same input shape.\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(sshape)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" + " Builds a :class:`ViewShape` using the default constructor,\n" + " copy constructor, or from a :class:`SShape`.\n" "\n" " :arg brother: A ViewShape object.\n" " :type brother: :class:`ViewShape`\n" - "\n" - ".. method:: __init__(sshape)\n" - "\n" - " Builds a ViewShape from an SShape.\n" - "\n" " :arg sshape: An SShape object.\n" " :type sshape: :class:`SShape`"); diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp index 81dd79ff270..7b3571c479f 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp @@ -44,40 +44,28 @@ PyDoc_STRVAR(CurvePoint_doc, "given resolution.\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(first_vertex, second_vertex, t2d)\n" + " __init__(first_point, second_point, t2d)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" + " Builds a CurvePoint using the default constructor, copy constructor,\n" + " or one of the overloaded constructors. The over loaded constructors\n" + " can either take two :class:`SVertex` or two :class:`CurvePoint`\n" + " objects and an interpolation parameter\n" "\n" " :arg brother: A CurvePoint object.\n" " :type brother: :class:`CurvePoint`\n" - "\n" - ".. method:: __init__(first_vertex, second_vertex, t2d)\n" - "\n" - " Builds a CurvePoint from two SVertex objects and an interpolation parameter.\n" - "\n" " :arg first_vertex: The first SVertex.\n" " :type first_vertex: :class:`SVertex`\n" " :arg second_vertex: The second SVertex.\n" " :type second_vertex: :class:`SVertex`\n" - " :arg t2d: A 2D interpolation parameter used to linearly interpolate\n" - " first_vertex and second_vertex.\n" - " :type t2d: float\n" - "\n" - ".. method:: __init__(first_point, second_point, t2d)\n" - "\n" - " Builds a CurvePoint from two CurvePoint objects and an interpolation\n" - " parameter.\n" - "\n" " :arg first_point: The first CurvePoint.\n" " :type first_point: :class:`CurvePoint`\n" " :arg second_point: The second CurvePoint.\n" " :type second_point: :class:`CurvePoint`\n" - " :arg t2d: The 2D interpolation parameter used to linearly interpolate\n" - " first_point and second_point.\n" - " :type t2d: float"); + " :arg t2d: A 2D interpolation parameter used to linearly interpolate\n" + " first_vertex and second_vertex or first_point and second_point.\n" + " :type t2d: float\n"); static int CurvePoint_init(BPy_CurvePoint *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp index c01f1f17000..63725c6b0e8 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp @@ -38,20 +38,15 @@ PyDoc_STRVAR(SVertex_doc, "Class to define a vertex of the embedding.\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(point_3d, id)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" + " Builds a :class:`SVertex` using the default constructor,\n" + " copy constructor or the overloaded constructor which builds" + " a :class:`SVertex` from 3D coordinates and an Id.\n" "\n" " :arg brother: A SVertex object.\n" " :type brother: :class:`SVertex`\n" - "\n" - ".. method:: __init__(point_3d, id)\n" - "\n" - " Builds a SVertex from 3D coordinates and an Id.\n" - "\n" " :arg point_3d: A three-dimensional vector.\n" " :type point_3d: :class:`mathutils.Vector`\n" " :arg id: An Id object.\n" diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp index 519bd72db3b..5c1a8f8482f 100644 --- a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp @@ -40,46 +40,29 @@ PyDoc_STRVAR( "Class to define a stroke vertex.\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(first_vertex, second_vertex, t3d)\n" + " __init__(point)\n" + " __init__(svertex)\n" + " __init__(svertex, attribute)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" + " Builds a :class:`StrokeVertex` using the default constructor,\n" + " copy constructor, from 2 :class:`StrokeVertex` and an interpolation parameter,\n" + " from a CurvePoint, from a SVertex, or a :class:`SVertex`" + " and a :class:`StrokeAttribute` object.\n" "\n" " :arg brother: A StrokeVertex object.\n" " :type brother: :class:`StrokeVertex`\n" - "\n" - ".. method:: __init__(first_vertex, second_vertex, t3d)\n" - "\n" - " Build a stroke vertex from 2 stroke vertices and an interpolation\n" - " parameter.\n" - "\n" " :arg first_vertex: The first StrokeVertex.\n" " :type first_vertex: :class:`StrokeVertex`\n" " :arg second_vertex: The second StrokeVertex.\n" " :type second_vertex: :class:`StrokeVertex`\n" " :arg t3d: An interpolation parameter.\n" " :type t3d: float\n" - "\n" - ".. method:: __init__(point)\n" - "\n" - " Build a stroke vertex from a CurvePoint\n" - "\n" " :arg point: A CurvePoint object.\n" " :type point: :class:`CurvePoint`\n" - "\n" - ".. method:: __init__(svertex)\n" - "\n" - " Build a stroke vertex from a SVertex\n" - "\n" " :arg svertex: An SVertex object.\n" " :type svertex: :class:`SVertex`\n" - "\n" - ".. method:: __init__(svertex, attribute)\n" - "\n" - " Build a stroke vertex from an SVertex and a StrokeAttribute object.\n" - "\n" " :arg svertex: An SVertex object.\n" " :type svertex: :class:`SVertex`\n" " :arg attribute: A StrokeAttribute object.\n" diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp index 9295e4f424b..ff53f5bfcbe 100644 --- a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp @@ -31,22 +31,20 @@ extern "C" { /*----------------------NonTVertex methods ----------------------------*/ -PyDoc_STRVAR(NonTVertex_doc, - "Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`NonTVertex`\n" - "\n" - "View vertex for corners, cusps, etc. associated to a single SVertex.\n" - "Can be associated to 2 or more view edges.\n" - "\n" - ".. method:: __init__()\n" - "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(svertex)\n" - "\n" - " Build a NonTVertex from a SVertex.\n" - "\n" - " :arg svertex: An SVertex object.\n" - " :type svertex: :class:`SVertex`"); +PyDoc_STRVAR( + NonTVertex_doc, + "Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`NonTVertex`\n" + "\n" + "View vertex for corners, cusps, etc. associated to a single SVertex.\n" + "Can be associated to 2 or more view edges.\n" + "\n" + ".. method:: __init__()\n" + " __init__(svertex)\n" + "\n" + " Builds a :class:`NonTVertex` using the default constructor or a :class:`SVertex`.\n" + "\n" + " :arg svertex: An SVertex object.\n" + " :type svertex: :class:`SVertex`"); /* Note: No copy constructor in Python because the C++ copy constructor is 'protected'. */ diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp index 187ab94360a..e04a89bad3b 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp @@ -48,20 +48,13 @@ PyDoc_STRVAR(FEdge_doc, "from one to the other.\n" "\n" ".. method:: FEdge()\n" + " FEdge(brother)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: FEdge(brother)\n" - "\n" - " Copy constructor.\n" + " Builds an :class:`FEdge` using the default constructor,\n" + " copy constructor, or between two :class:`SVertex` objects.\n" "\n" " :arg brother: An FEdge object.\n" " :type brother: :class:`FEdge`\n" - "\n" - ".. method:: FEdge(first_vertex, second_vertex)\n" - "\n" - " Builds an FEdge going from the first vertex to the second.\n" - "\n" " :arg first_vertex: The first SVertex.\n" " :type first_vertex: :class:`SVertex`\n" " :arg second_vertex: The second SVertex.\n" diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp index 788dfa78992..78c0ee051d6 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp @@ -41,20 +41,14 @@ PyDoc_STRVAR(FrsCurve_doc, "specialization of a Curve.\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(id)\n" "\n" - " Default Constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy Constructor.\n" + " Builds a :class:`FrsCurve` using a default constructor,\n" + " copy constructor or from an :class:`Id`.\n" "\n" " :arg brother: A Curve object.\n" " :type brother: :class:`Curve`\n" - "\n" - ".. method:: __init__(id)\n" - "\n" - " Builds a Curve from its Id.\n" - "\n" " :arg id: An Id object.\n" " :type id: :class:`Id`"); diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp index b31efe1f923..910f9cdfa07 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp @@ -50,12 +50,9 @@ PyDoc_STRVAR(Stroke_doc, "defines the stroke's shape and appearance at this vertex position.\n" "\n" ".. method:: Stroke()\n" + " Stroke(brother)\n" "\n" - " Default constructor\n" - "\n" - ".. method:: Stroke(brother)\n" - "\n" - " Copy constructor"); + " Creates a :class:`Stroke` using the default constructor or copy constructor\n"); static int Stroke_init(BPy_Stroke *self, PyObject *args, PyObject *kwds) { @@ -127,21 +124,18 @@ static PyObject *Stroke_compute_sampling(BPy_Stroke *self, PyObject *args, PyObj PyDoc_STRVAR(Stroke_resample_doc, ".. method:: resample(n)\n" + " resample(sampling)\n" "\n" - " Resamples the stroke so that it eventually has N points. That means\n" - " it is going to add N-vertices_size, where vertices_size is the\n" - " number of points we already have. If vertices_size >= N, no\n" - " resampling is done.\n" + " Resamples the stroke so using one of two methods with the goal\n" + " of creating a stroke with fewer points and the same shape.\n" "\n" - " :arg n: The number of vertices we eventually want in our stroke.\n" + " :arg n: Resamples the stroke so that it eventually has N points. That means\n" + " it is going to add N-vertices_size, where vertices_size is the\n" + " number of points we already have. If vertices_size >= N, no\n" + " resampling is done.\n" " :type n: int\n" - "\n" - ".. method:: resample(sampling)\n" - "\n" - " Resamples the stroke with a given sampling. If the sampling is\n" - " smaller than the actual sampling value, no resampling is done.\n" - "\n" - " :arg sampling: The new sampling value.\n" + " :arg sampling: Resamples the stroke with a given sampling value. If the\n" + " sampling is smaller than the actual sampling value, no resampling is done.\n" " :type sampling: float"); static PyObject *Stroke_resample(BPy_Stroke *self, PyObject *args, PyObject *kwds) diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp index 58c2ba69c79..e9160d7a5c7 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp @@ -36,23 +36,21 @@ extern "C" { /*----------------------ViewEdge methods ----------------------------*/ -PyDoc_STRVAR(ViewEdge_doc, - "Class hierarchy: :class:`Interface1D` > :class:`ViewEdge`\n" - "\n" - "Class defining a ViewEdge. A ViewEdge in an edge of the image graph.\n" - "it connects two :class:`ViewVertex` objects. It is made by connecting\n" - "a set of FEdges.\n" - "\n" - ".. method:: __init__()\n" - "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" - "\n" - " :arg brother: A ViewEdge object.\n" - " :type brother: :class:`ViewEdge`"); +PyDoc_STRVAR( + ViewEdge_doc, + "Class hierarchy: :class:`Interface1D` > :class:`ViewEdge`\n" + "\n" + "Class defining a ViewEdge. A ViewEdge in an edge of the image graph.\n" + "it connects two :class:`ViewVertex` objects. It is made by connecting\n" + "a set of FEdges.\n" + "\n" + ".. method:: __init__()\n" + " __init__(brother)\n" + "\n" + " Builds a :class:`ViewEdge` using the default constructor or the copy constructor.\n" + "\n" + " :arg brother: A ViewEdge object.\n" + " :type brother: :class:`ViewEdge`"); static int ViewEdge_init(BPy_ViewEdge *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp index 9cdc344081e..028e36145b9 100644 --- a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp @@ -40,20 +40,14 @@ PyDoc_STRVAR(Chain_doc, "Splitting and Creation processes.\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(id)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" + " Builds a :class:`Chain` using the default constructor,\n" + " copy constructor or from an :class:`Id`.\n" "\n" " :arg brother: A Chain object.\n" " :type brother: :class:`Chain`\n" - "\n" - ".. method:: __init__(id)\n" - "\n" - " Builds a chain from its Id.\n" - "\n" " :arg id: An Id object.\n" " :type id: :class:`Id`"); diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp index c329a3badd5..018e0449552 100644 --- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp @@ -42,20 +42,14 @@ PyDoc_STRVAR(FEdgeSharp_doc, "a is None.\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(first_vertex, second_vertex)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" + " Builds an :class:`FEdgeSharp` using the default constructor,\n" + " copy constructor, or between two :class:`SVertex` objects.\n" "\n" " :arg brother: An FEdgeSharp object.\n" " :type brother: :class:`FEdgeSharp`\n" - "\n" - ".. method:: __init__(first_vertex, second_vertex)\n" - "\n" - " Builds an FEdgeSharp going from the first vertex to the second.\n" - "\n" " :arg first_vertex: The first SVertex object.\n" " :type first_vertex: :class:`SVertex`\n" " :arg second_vertex: The second SVertex object.\n" diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp index 3fb739b18db..014f0411356 100644 --- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp @@ -39,20 +39,14 @@ PyDoc_STRVAR(FEdgeSmooth_doc, "a suggestive contour.\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(first_vertex, second_vertex)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" + " Builds an :class:`FEdgeSmooth` using the default constructor,\n" + " copy constructor, or between two :class:`SVertex`.\n" "\n" " :arg brother: An FEdgeSmooth object.\n" " :type brother: :class:`FEdgeSmooth`\n" - "\n" - ".. method:: __init__(first_vertex, second_vertex)\n" - "\n" - " Builds an FEdgeSmooth going from the first to the second.\n" - "\n" " :arg first_vertex: The first SVertex object.\n" " :type first_vertex: :class:`SVertex`\n" " :arg second_vertex: The second SVertex object.\n" diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp index 90e751333b9..dc32b73fda1 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp @@ -41,20 +41,14 @@ PyDoc_STRVAR( "traverse() method of the ChainingIterator.\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(vertex, restrict_to_selection=True, restrict_to_unvisited=True)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" + " Builds an :class:`AdjacencyIterator` using the default constructor,\n" + " copy constructor or the overloaded constructor.\n" "\n" " :arg brother: An AdjacencyIterator object.\n" " :type brother: :class:`AdjacencyIterator`\n" - "\n" - ".. method:: __init__(vertex, restrict_to_selection=True, restrict_to_unvisited=True)\n" - "\n" - " Builds a AdjacencyIterator object.\n" - "\n" " :arg vertex: The vertex which is the next crossing.\n" " :type vertex: :class:`ViewVertex`\n" " :arg restrict_to_selection: Indicates whether to force the chaining\n" diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp index 1703fc2bddb..9c534a3463c 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp @@ -33,55 +33,52 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- -PyDoc_STRVAR(ChainPredicateIterator_doc, - - "Class hierarchy: :class:`freestyle.types.Iterator` >\n" - ":class:`freestyle.types.ViewEdgeIterator` >\n" - ":class:`freestyle.types.ChainingIterator` >\n" - ":class:`ChainPredicateIterator`\n" - "\n" - "A \"generic\" user-controlled ViewEdge iterator. This iterator is in\n" - "particular built from a unary predicate and a binary predicate.\n" - "First, the unary predicate is evaluated for all potential next\n" - "ViewEdges in order to only keep the ones respecting a certain\n" - "constraint. Then, the binary predicate is evaluated on the current\n" - "ViewEdge together with each ViewEdge of the previous selection. The\n" - "first ViewEdge respecting both the unary predicate and the binary\n" - "predicate is kept as the next one. If none of the potential next\n" - "ViewEdge respects these two predicates, None is returned.\n" - "\n" - ".. method:: __init__(upred, bpred, restrict_to_selection=True, " - "restrict_to_unvisited=True, begin=None, " - "orientation=True)\n" - "\n" - " Builds a ChainPredicateIterator from a unary predicate, a binary\n" - " predicate, a starting ViewEdge and its orientation.\n" - "\n" - " :arg upred: The unary predicate that the next ViewEdge must satisfy.\n" - " :type upred: :class:`freestyle.types.UnaryPredicate1D`\n" - " :arg bpred: The binary predicate that the next ViewEdge must\n" - " satisfy together with the actual pointed ViewEdge.\n" - " :type bpred: :class:`freestyle.types.BinaryPredicate1D`\n" - " :arg restrict_to_selection: Indicates whether to force the chaining\n" - " to stay within the set of selected ViewEdges or not.\n" - " :type restrict_to_selection: bool\n" - " :arg restrict_to_unvisited: Indicates whether a ViewEdge that has\n" - " already been chained must be ignored ot not.\n" - " :type restrict_to_unvisited: bool\n" - " :arg begin: The ViewEdge from where to start the iteration.\n" - " :type begin: :class:`freestyle.types.ViewEdge` or None\n" - " :arg orientation: If true, we'll look for the next ViewEdge among\n" - " the ViewEdges that surround the ending ViewVertex of begin. If\n" - " false, we'll search over the ViewEdges surrounding the ending\n" - " ViewVertex of begin.\n" - " :type orientation: bool\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" - "\n" - " :arg brother: A ChainPredicateIterator object.\n" - " :type brother: :class:`ChainPredicateIterator`"); +PyDoc_STRVAR( + ChainPredicateIterator_doc, + + "Class hierarchy: :class:`freestyle.types.Iterator` >\n" + ":class:`freestyle.types.ViewEdgeIterator` >\n" + ":class:`freestyle.types.ChainingIterator` >\n" + ":class:`ChainPredicateIterator`\n" + "\n" + "A \"generic\" user-controlled ViewEdge iterator. This iterator is in\n" + "particular built from a unary predicate and a binary predicate.\n" + "First, the unary predicate is evaluated for all potential next\n" + "ViewEdges in order to only keep the ones respecting a certain\n" + "constraint. Then, the binary predicate is evaluated on the current\n" + "ViewEdge together with each ViewEdge of the previous selection. The\n" + "first ViewEdge respecting both the unary predicate and the binary\n" + "predicate is kept as the next one. If none of the potential next\n" + "ViewEdge respects these two predicates, None is returned.\n" + "\n" + ".. method:: __init__(upred, bpred, restrict_to_selection=True, " + " restrict_to_unvisited=True, begin=None, " + " orientation=True)\n" + " __init__(brother)\n" + "\n" + " Builds a ChainPredicateIterator from a unary predicate, a binary\n" + " predicate, a starting ViewEdge and its orientation or using the copy constructor.\n" + "\n" + " :arg upred: The unary predicate that the next ViewEdge must satisfy.\n" + " :type upred: :class:`freestyle.types.UnaryPredicate1D`\n" + " :arg bpred: The binary predicate that the next ViewEdge must\n" + " satisfy together with the actual pointed ViewEdge.\n" + " :type bpred: :class:`freestyle.types.BinaryPredicate1D`\n" + " :arg restrict_to_selection: Indicates whether to force the chaining\n" + " to stay within the set of selected ViewEdges or not.\n" + " :type restrict_to_selection: bool\n" + " :arg restrict_to_unvisited: Indicates whether a ViewEdge that has\n" + " already been chained must be ignored ot not.\n" + " :type restrict_to_unvisited: bool\n" + " :arg begin: The ViewEdge from where to start the iteration.\n" + " :type begin: :class:`freestyle.types.ViewEdge` or None\n" + " :arg orientation: If true, we'll look for the next ViewEdge among\n" + " the ViewEdges that surround the ending ViewVertex of begin. If\n" + " false, we'll search over the ViewEdges surrounding the ending\n" + " ViewVertex of begin.\n" + " :type orientation: bool\n" + " :arg brother: A ChainPredicateIterator object.\n" + " :type brother: :class:`ChainPredicateIterator`"); static int check_begin(PyObject *obj, void *v) { diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp index d8ad82d667c..9fa84d5f6b8 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp @@ -48,9 +48,10 @@ PyDoc_STRVAR(ChainSilhouetteIterator_doc, "precedence of the silhouette over the crease criterion.\n" "\n" ".. method:: __init__(restrict_to_selection=True, begin=None, orientation=True)\n" + " __init__(brother)\n" "\n" " Builds a ChainSilhouetteIterator from the first ViewEdge used for\n" - " iteration and its orientation.\n" + " iteration and its orientation or the copy constructor.\n" "\n" " :arg restrict_to_selection: Indicates whether to force the chaining\n" " to stay within the set of selected ViewEdges or not.\n" @@ -62,11 +63,6 @@ PyDoc_STRVAR(ChainSilhouetteIterator_doc, " false, we'll search over the ViewEdges surrounding the ending\n" " ViewVertex of begin.\n" " :type orientation: bool\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" - "\n" " :arg brother: A ChainSilhouetteIterator object.\n" " :type brother: :class:`ChainSilhouetteIterator`"); diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp index dbd6e8dd09d..d24e1dc527d 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp @@ -46,11 +46,12 @@ PyDoc_STRVAR( "they will be included in the adjacency iterator (i.e, the adjacent\n" "iterator will only stop on \"valid\" edges).\n" "\n" - ".. method:: __init__(restrict_to_selection=True, restrict_to_unvisited=True, begin=None, " - "orientation=True)\n" + ".. method:: __init__(restrict_to_selection=True, restrict_to_unvisited=True," + " begin=None, orientation=True)\n" + " __init__(brother)\n" "\n" " Builds a Chaining Iterator from the first ViewEdge used for\n" - " iteration and its orientation.\n" + " iteration and its orientation or by using the copy constructor.\n" "\n" " :arg restrict_to_selection: Indicates whether to force the chaining\n" " to stay within the set of selected ViewEdges or not.\n" @@ -63,11 +64,6 @@ PyDoc_STRVAR( " :arg orientation: The direction to follow to explore the graph. If\n" " true, the direction indicated by the first ViewEdge is used.\n" " :type orientation: bool\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" - "\n" " :arg brother: \n" " :type brother: ChainingIterator"); diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp index 6c496b0308b..8eac657316e 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp @@ -39,20 +39,14 @@ PyDoc_STRVAR(CurvePointIterator_doc, "through the .object attribute.\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(step=0.0)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" + " Builds a CurvePointIterator object using either the default constructor,\n" + " copy constructor, or the overloaded constructor.\n" "\n" " :arg brother: A CurvePointIterator object.\n" " :type brother: :class:`CurvePointIterator`\n" - "\n" - ".. method:: __init__(step=0.0)\n" - "\n" - " Builds a CurvePointIterator object.\n" - "\n" " :arg step: A resampling resolution with which the curve is resampled.\n" " If zero, no resampling is done (i.e., the iterator iterates over\n" " initial vertices).\n" diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp index 734ed0117f4..f7afc7695ae 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp @@ -38,17 +38,13 @@ PyDoc_STRVAR(Interface0DIterator_doc, "this iterator is always obtained from a 1D element.\n" "\n" ".. method:: __init__(brother)\n" + " __init__(it)\n" "\n" - " Copy constructor.\n" + " Construct a nested Interface0DIterator using either the copy constructor\n" + " or the constructor that takes an he argument of a Function0D.\n" "\n" " :arg brother: An Interface0DIterator object.\n" " :type brother: :class:`Interface0DIterator`\n" - "\n" - ".. method:: __init__(it)\n" - "\n" - " Construct a nested Interface0DIterator that can be the argument of\n" - " a Function0D.\n" - "\n" " :arg it: An iterator object to be nested.\n" " :type it: :class:`SVertexIterator`, :class:`CurvePointIterator`, or\n" " :class:`StrokeVertexIterator`"); diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp index 4a5927ff6eb..83c504081c1 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp @@ -32,39 +32,33 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- -PyDoc_STRVAR(SVertexIterator_doc, - "Class hierarchy: :class:`Iterator` > :class:`SVertexIterator`\n" - "\n" - "Class representing an iterator over :class:`SVertex` of a\n" - ":class:`ViewEdge`. An instance of an SVertexIterator can be obtained\n" - "from a ViewEdge by calling verticesBegin() or verticesEnd().\n" - "\n" - ".. method:: __init__()\n" - "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" - "\n" - " :arg brother: An SVertexIterator object.\n" - " :type brother: :class:`SVertexIterator`\n" - "\n" - ".. method:: __init__(vertex, begin, previous_edge, next_edge, t)\n" - "\n" - " Build an SVertexIterator that starts iteration from an SVertex\n" - " object v.\n" - "\n" - " :arg vertex: The SVertex from which the iterator starts iteration.\n" - " :type vertex: :class:`SVertex`\n" - " :arg begin: The first SVertex of a ViewEdge.\n" - " :type begin: :class:`SVertex`\n" - " :arg previous_edge: The previous FEdge coming to vertex.\n" - " :type previous_edge: :class:`FEdge`\n" - " :arg next_edge: The next FEdge going out from vertex.\n" - " :type next_edge: :class:`FEdge`\n" - " :arg t: The curvilinear abscissa at vertex.\n" - " :type t: float"); +PyDoc_STRVAR( + SVertexIterator_doc, + "Class hierarchy: :class:`Iterator` > :class:`SVertexIterator`\n" + "\n" + "Class representing an iterator over :class:`SVertex` of a\n" + ":class:`ViewEdge`. An instance of an SVertexIterator can be obtained\n" + "from a ViewEdge by calling verticesBegin() or verticesEnd().\n" + "\n" + ".. method:: __init__()\n" + " __init__(brother)\n" + " __init__(vertex, begin, previous_edge, next_edge, t)" + "\n" + " Build an SVertexIterator using either the default constructor, copy constructor,\n" + " or the overloaded constructor that starts iteration from an SVertex object vertex.\n" + "\n" + " :arg brother: An SVertexIterator object.\n" + " :type brother: :class:`SVertexIterator`\n" + " :arg vertex: The SVertex from which the iterator starts iteration.\n" + " :type vertex: :class:`SVertex`\n" + " :arg begin: The first SVertex of a ViewEdge.\n" + " :type begin: :class:`SVertex`\n" + " :arg previous_edge: The previous FEdge coming to vertex.\n" + " :type previous_edge: :class:`FEdge`\n" + " :arg next_edge: The next FEdge going out from vertex.\n" + " :type next_edge: :class:`FEdge`\n" + " :arg t: The curvilinear abscissa at vertex.\n" + " :type t: float"); static int SVertexIterator_init(BPy_SVertexIterator *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp index cda4031240b..e1b24e768e3 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp @@ -48,12 +48,10 @@ PyDoc_STRVAR(StrokeVertexIterator_doc, "by calling Interface0DIterator(it).\n" "\n" ".. method:: __init__()\n" + " __init__(brother)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" + " Creates a :class:`StrokeVertexIterator` using either the\n" + " default constructor or the copy constructor.\n" "\n" " :arg brother: A StrokeVertexIterator object.\n" " :type brother: :class:`StrokeVertexIterator`"); diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp index 3d0ed5d5a4d..20134057864 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp @@ -40,9 +40,10 @@ PyDoc_STRVAR(ViewEdgeIterator_doc, "on a given ViewEdge.\n" "\n" ".. method:: __init__(begin=None, orientation=True)\n" + " __init__(brother)\n" "\n" " Builds a ViewEdgeIterator from a starting ViewEdge and its\n" - " orientation.\n" + " orientation or the copy constructor.\n" "\n" " :arg begin: The ViewEdge from where to start the iteration.\n" " :type begin: :class:`ViewEdge` or None\n" @@ -51,11 +52,6 @@ PyDoc_STRVAR(ViewEdgeIterator_doc, " false, we'll search over the ViewEdges surrounding the ending\n" " ViewVertex of begin.\n" " :type orientation: bool\n" - "\n" - ".. method:: __init__(brother)\n" - "\n" - " Copy constructor.\n" - "\n" " :arg brother: A ViewEdgeIterator object.\n" " :type brother: :class:`ViewEdgeIterator`"); diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp index fe6210468d1..30b7b3ccde5 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp @@ -39,12 +39,10 @@ PyDoc_STRVAR(orientedViewEdgeIterator_doc, "obtained from a ViewVertex by calling edges_begin() or edges_end().\n" "\n" ".. method:: __init__()\n" + " __init__(iBrother)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(iBrother)\n" - "\n" - " Copy constructor.\n" + " Creates an :class:`orientedViewEdgeIterator` using either the\n" + " default constructor or the copy constructor.\n" "\n" " :arg iBrother: An orientedViewEdgeIterator object.\n" " :type iBrother: :class:`orientedViewEdgeIterator`"); diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp index 88705c41204..b59e27dcea9 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp @@ -160,13 +160,10 @@ static char UnaryFunction1DDouble___doc__[] = ":class:`Interface1D` and return a float value.\n" "\n" ".. method:: __init__()\n" + " __init__(integration_type)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(integration_type)\n" - "\n" - " Builds a unary 1D function using the integration method given as\n" - " argument.\n" + " Builds a unary 1D function using the default constructor\n" + " or the integration method given as an argument.\n" "\n" " :arg integration_type: An integration method.\n" " :type integration_type: :class:`IntegrationType`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp index 3cfc5464296..2f5a59f9c7a 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp @@ -65,13 +65,10 @@ static char UnaryFunction1DEdgeNature___doc__[] = ":class:`Interface1D` and return a :class:`Nature` object.\n" "\n" ".. method:: __init__()\n" + " __init__(integration_type)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(integration_type)\n" - "\n" - " Builds a unary 1D function using the integration method given as\n" - " argument.\n" + " Builds a unary 1D function using the default constructor\n" + " or the integration method given as an argument.\n" "\n" " :arg integration_type: An integration method.\n" " :type integration_type: :class:`IntegrationType`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp index 4fdc68a2e89..e11d21b6c8e 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp @@ -56,13 +56,10 @@ static char UnaryFunction1DFloat___doc__[] = ":class:`Interface1D` and return a float value.\n" "\n" ".. method:: __init__()\n" + " __init__(integration_type)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(integration_type)\n" - "\n" - " Builds a unary 1D function using the integration method given as\n" - " argument.\n" + " Builds a unary 1D function using the default constructor\n" + " or the integration method given as an argument.\n" "\n" " :arg integration_type: An integration method.\n" " :type integration_type: :class:`IntegrationType`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp index 218afa3ff10..e04a5b9d7f4 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp @@ -65,13 +65,10 @@ static char UnaryFunction1DUnsigned___doc__[] = ":class:`Interface1D` and return an int value.\n" "\n" ".. method:: __init__()\n" + " __init__(integration_type)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(integration_type)\n" - "\n" - " Builds a unary 1D function using the integration method given as\n" - " argument.\n" + " Builds a unary 1D function using the default constructor\n" + " or the integration method given as an argument.\n" "\n" " :arg integration_type: An integration method.\n" " :type integration_type: :class:`IntegrationType`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp index 939ccfb8905..f8d75640811 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp @@ -71,13 +71,10 @@ static char UnaryFunction1DVec2f___doc__[] = ":class:`Interface1D` and return a 2D vector.\n" "\n" ".. method:: __init__()\n" + " __init__(integration_type)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(integration_type)\n" - "\n" - " Builds a unary 1D function using the integration method given as\n" - " argument.\n" + " Builds a unary 1D function using the default constructor\n" + " or the integration method given as an argument.\n" "\n" " :arg integration_type: An integration method.\n" " :type integration_type: :class:`IntegrationType`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp index 02b6373cce4..9f71fb3840b 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp @@ -64,13 +64,10 @@ static char UnaryFunction1DVec3f___doc__[] = ":class:`Interface1D` and return a 3D vector.\n" "\n" ".. method:: __init__()\n" + " __init__(integration_type)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(integration_type)\n" - "\n" - " Builds a unary 1D function using the integration method given as\n" - " argument.\n" + " Builds a unary 1D function using the default constructor\n" + " or the integration method given as an argument.\n" "\n" " :arg integration_type: An integration method.\n" " :type integration_type: :class:`IntegrationType`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp index b2020e9f554..cb4982f4532 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp @@ -80,13 +80,10 @@ static char UnaryFunction1DVectorViewShape___doc__[] = "objects.\n" "\n" ".. method:: __init__()\n" + " __init__(integration_type)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(integration_type)\n" - "\n" - " Builds a unary 1D function using the integration method given as\n" - " argument.\n" + " Builds a unary 1D function using the default constructor\n" + " or the integration method given as an argument.\n" "\n" " :arg integration_type: An integration method.\n" " :type integration_type: :class:`IntegrationType`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp index 7b25daa24f9..46564cdaeca 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp @@ -79,13 +79,10 @@ static char UnaryFunction1DVoid___doc__[] = ":class:`Interface1D`.\n" "\n" ".. method:: __init__()\n" + " __init__(integration_type)\n" "\n" - " Default constructor.\n" - "\n" - ".. method:: __init__(integration_type)\n" - "\n" - " Builds a unary 1D function using the integration method given as\n" - " argument.\n" + " Builds a unary 1D function using either a default constructor\n" + " or the integration method given as an argument.\n" "\n" " :arg integration_type: An integration method.\n" " :type integration_type: :class:`IntegrationType`\n"; -- cgit v1.2.3 From 8e060b44da04f4385a36a1a441e2ec45f1fd19f2 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 22 Oct 2020 18:13:30 -0500 Subject: Fix T81818: Outliner mode column crashes with shared object data For objects with shared data, it makes sense to show the mode icon for every object sharing the same data if one of them is in edit mode. This also disables the "extend" functionality in this case, because being in edit mode for multiple objects with the same data isn't supported. Differential Revision: https://developer.blender.org/D9273 --- source/blender/editors/space_outliner/outliner_draw.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 3045529747d..5a789ee0b01 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1935,8 +1935,14 @@ static void outliner_mode_toggle_fn(bContext *C, void *tselem_poin, void *UNUSED return; } + /* Check that the the item is actually an object. */ + BLI_assert(tselem->id != NULL && GS(tselem->id->name) == ID_OB); + + Object *ob = (Object *)tselem->id; + const bool object_data_shared = (ob->data == tvc.obact->data); + wmWindow *win = CTX_wm_window(C); - const bool do_extend = win->eventstate->ctrl != 0; + const bool do_extend = win->eventstate->ctrl != 0 && !object_data_shared; outliner_item_mode_toggle(C, &tvc, te, do_extend); } @@ -1974,11 +1980,15 @@ static void outliner_draw_mode_column_toggle(uiBlock *block, draw_active_icon = false; } + const bool object_data_shared = (ob->data == ob_active->data); + draw_active_icon = draw_active_icon || object_data_shared; + int icon; const char *tip; if (draw_active_icon) { icon = UI_icon_from_object_mode(ob_active->mode); - tip = TIP_("Remove from the current mode"); + tip = object_data_shared ? TIP_("Change the object in the current mode") : + TIP_("Remove from the current mode"); } else { icon = ICON_DOT; -- cgit v1.2.3 From c6281d5dc7c40c6fabef0873b3865eadcb09c63e Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 22 Oct 2020 18:37:52 -0500 Subject: Cleanup: Use DNA deprecated guards around old flags These flags shouldn't be used except in versioning code. --- source/blender/makesdna/DNA_constraint_types.h | 2 ++ source/blender/makesdna/DNA_gpencil_modifier_types.h | 2 ++ source/blender/makesdna/DNA_modifier_types.h | 4 +++- source/blender/makesdna/DNA_shader_fx_types.h | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) (limited to 'source') diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 92ee3f062a6..c95e5376670 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -690,8 +690,10 @@ typedef enum eBConstraint_Types { /* flag 0x20 (1 << 5) was used to indicate that a constraint was evaluated * using a 'local' hack for posebones only. */ typedef enum eBConstraint_Flags { +#ifdef DNA_DEPRECATED_ALLOW /* Expansion for old box constraint layouts. Just for versioning. */ CONSTRAINT_EXPAND_DEPRECATED = (1 << 0), +#endif /* pre-check for illegal object name or bone name */ CONSTRAINT_DISABLE = (1 << 2), /* to indicate which Ipo should be shown, maybe for 3d access later too */ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index 7e2ec8b6c65..3a9f9bd7b66 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -57,7 +57,9 @@ typedef enum GpencilModifierMode { eGpencilModifierMode_Realtime = (1 << 0), eGpencilModifierMode_Render = (1 << 1), eGpencilModifierMode_Editmode = (1 << 2), +#ifdef DNA_DEPRECATED_ALLOW eGpencilModifierMode_Expanded_DEPRECATED = (1 << 3), +#endif eGpencilModifierMode_Virtual = (1 << 4), } GpencilModifierMode; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 29bcc5fe903..0d642e4f3d5 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -106,8 +106,10 @@ typedef enum ModifierMode { eModifierMode_Render = (1 << 1), eModifierMode_Editmode = (1 << 2), eModifierMode_OnCage = (1 << 3), - /* Old modifier box expansion, just for versioning. */ +#ifdef DNA_DEPRECATED_ALLOW + /** Old modifier box expansion, just for versioning. */ eModifierMode_Expanded_DEPRECATED = (1 << 4), +#endif eModifierMode_Virtual = (1 << 5), eModifierMode_ApplyOnSpline = (1 << 6), eModifierMode_DisableTemporary = (1u << 31), diff --git a/source/blender/makesdna/DNA_shader_fx_types.h b/source/blender/makesdna/DNA_shader_fx_types.h index 5bb78edb280..5567d65b6db 100644 --- a/source/blender/makesdna/DNA_shader_fx_types.h +++ b/source/blender/makesdna/DNA_shader_fx_types.h @@ -49,7 +49,9 @@ typedef enum ShaderFxMode { eShaderFxMode_Realtime = (1 << 0), eShaderFxMode_Render = (1 << 1), eShaderFxMode_Editmode = (1 << 2), +#ifdef DNA_DEPRECATED_ALLOW eShaderFxMode_Expanded_DEPRECATED = (1 << 3), +#endif } ShaderFxMode; typedef enum { -- cgit v1.2.3