diff options
133 files changed, 1878 insertions, 934 deletions
diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h index 6ffcf99b48c..afbdf1268ee 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.h +++ b/intern/ghost/intern/GHOST_WindowWayland.h @@ -29,9 +29,9 @@ class GHOST_SystemWayland; +struct output_t; struct window_t; struct wl_surface; -struct output_t; class GHOST_WindowWayland : public GHOST_Window { public: diff --git a/release/scripts/startup/bl_operators/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py index 48a02a4c5c6..8f678896e61 100644 --- a/release/scripts/startup/bl_operators/sequencer.py +++ b/release/scripts/startup/bl_operators/sequencer.py @@ -108,14 +108,13 @@ class SequencerSplitMulticam(Operator): if s.multicam_source == camera or camera >= s.channel: return {'FINISHED'} - if not s.select: - s.select = True - cfra = context.scene.frame_current - bpy.ops.sequencer.split(frame=cfra, type='SOFT', side='RIGHT') - for s in context.scene.sequence_editor.sequences_all: - if s.select and s.type == 'MULTICAM' and s.frame_final_start <= cfra and cfra < s.frame_final_end: - context.scene.sequence_editor.active_strip = s + right_strip = s.split(frame=cfra, split_method='SOFT') + + if right_strip: + s.select = False + right_strip.select = True + context.scene.sequence_editor.active_strip = right_strip context.scene.sequence_editor.active_strip.multicam_source = camera return {'FINISHED'} diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index 7f4328bb25a..d9ad094ac4f 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -646,7 +646,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel): if len(colliding_names) == 0: return - layout.label(text="Name Collisions: {}".format(", ".join(colliding_names)), icon='INFO') + layout.label(text="Name collisions: {}".format(", ".join(colliding_names)), icon='ERROR') classes = ( diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 965c9b35b7c..ff006de5585 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -508,6 +508,7 @@ geometry_node_categories = [ NodeItem("GeometryNodeMeshToCurve"), NodeItem("GeometryNodeCurveToPoints"), NodeItem("GeometryNodeCurveEndpoints"), + NodeItem("GeometryNodeCurveTrim"), NodeItem("GeometryNodeCurveLength"), NodeItem("GeometryNodeCurveReverse"), ]), diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 1f9e304c7a3..e13475fd78c 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -28,7 +28,6 @@ extern "C" { #endif struct AnimationEvalContext; -struct bAction; struct BMEditMesh; struct Bone; struct Depsgraph; @@ -39,6 +38,7 @@ struct Mesh; struct Object; struct PoseTree; struct Scene; +struct bAction; struct bArmature; struct bConstraint; struct bGPDstroke; diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 0ab126a70ae..f4221d57428 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -30,6 +30,7 @@ extern "C" { struct BlendDataReader; struct BlendWriter; +struct ID; struct ListBase; struct MDeformVert; struct MEdge; @@ -37,7 +38,6 @@ struct MLoop; struct MPoly; struct Object; struct bDeformGroup; -struct ID; bool BKE_object_supports_vertex_groups(const struct Object *ob); const struct ListBase *BKE_object_defgroup_list(const struct Object *ob); diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index ce7df62389f..ffd8ac42c63 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -32,8 +32,8 @@ extern "C" { #endif struct BMLoop; -struct BMesh; struct BMPartialUpdate; +struct BMesh; struct BMeshCalcTessellation_Params; struct BoundBox; struct Depsgraph; diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index 77e827bf6f2..42e9ce82278 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -35,12 +35,12 @@ #include "BKE_geometry_set.h" struct Collection; +struct Curve; +struct CurveEval; struct Mesh; struct Object; struct PointCloud; struct Volume; -struct Curve; -struct CurveEval; enum class GeometryOwnershipType { /* The geometry is owned. This implies that it can be changed. */ diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 1f9c3e766aa..92e70b41e7b 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -49,22 +49,22 @@ struct bGPDlayer_Mask; struct bGPDstroke; struct bGPdata; -#define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE)) +#define GPENCIL_SIMPLIFY(scene) (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE) #define GPENCIL_SIMPLIFY_ONPLAY(playing) \ (((playing == true) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY)) || \ ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY) == 0)) #define GPENCIL_SIMPLIFY_FILL(scene, playing) \ - ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \ + ((GPENCIL_SIMPLIFY_ONPLAY(playing) && GPENCIL_SIMPLIFY(scene) && \ (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL))) #define GPENCIL_SIMPLIFY_MODIF(scene) \ ((GPENCIL_SIMPLIFY(scene) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER))) #define GPENCIL_SIMPLIFY_FX(scene, playing) \ - ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \ + ((GPENCIL_SIMPLIFY_ONPLAY(playing) && GPENCIL_SIMPLIFY(scene) && \ (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX))) #define GPENCIL_SIMPLIFY_TINT(scene) \ - ((GPENCIL_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_TINT)) + (GPENCIL_SIMPLIFY(scene) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_TINT)) #define GPENCIL_SIMPLIFY_AA(scene) \ - ((GPENCIL_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_AA)) + (GPENCIL_SIMPLIFY(scene) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_AA)) /* Vertex Color macros. */ #define GPENCIL_USE_VERTEX_COLOR(toolsettings) \ diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index 27076d908e7..c6658ff424a 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -42,8 +42,8 @@ extern "C" { #endif -struct Collection; struct BlendFileReadReport; +struct Collection; struct ID; struct IDOverrideLibrary; struct IDOverrideLibraryProperty; diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 5e977fbc0cd..39024445808 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1274,6 +1274,11 @@ void ntreeGPUMaterialNodes(struct bNodeTree *localtree, #define CMP_CRYPTOMATTE_SRC_RENDER 0 #define CMP_CRYPTOMATTE_SRC_IMAGE 1 +/* Default SMAA configuration values. */ +#define CMP_DEFAULT_SMAA_THRESHOLD 1.0f +#define CMP_DEFAULT_SMAA_CONTRAST_LIMIT 0.2f +#define CMP_DEFAULT_SMAA_CORNER_ROUNDING 0.25f + /* API */ void ntreeCompositExecTree(struct Scene *scene, struct bNodeTree *ntree, @@ -1459,7 +1464,8 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_CURVE_PRIMITIVE_LINE 1068 #define GEO_NODE_CURVE_ENDPOINTS 1069 #define GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL 1070 -#define GEO_NODE_CURVE_SAMPLE 1071 +#define GEO_NODE_CURVE_TRIM 1071 +#define GEO_NODE_CURVE_SAMPLE 1072 /** \} */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 2c25b940578..527996ee46d 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -143,7 +143,7 @@ set(SRC intern/geometry_set_instances.cc intern/gpencil.c intern/gpencil_curve.c - intern/gpencil_geom.c + intern/gpencil_geom.cc intern/gpencil_modifier.c intern/hair.c intern/icons.cc diff --git a/source/blender/blenkernel/intern/action_mirror.c b/source/blender/blenkernel/intern/action_mirror.c index ba041388981..48472dfc9b3 100644 --- a/source/blender/blenkernel/intern/action_mirror.c +++ b/source/blender/blenkernel/intern/action_mirror.c @@ -324,8 +324,9 @@ static void action_flip_pchan(Object *ob_arm, /* The rest pose having an X-axis that is not mapping to a left/right direction (so aligned * with the Y or Z axis) creates issues when flipping the pose. Instead of a negative scale on - * the X-axis, it turns into a 180 degree rotation over the Y-axis. This has only been observed - * with non-flippable bones, hence the check for `pchan_flip`. */ + * the X-axis, it turns into a 180 degree rotation over the Y-axis. + * This has only been observed with bones that can't be flipped, + * hence the check for `pchan_flip`. */ const float unit_x[4] = {1.0f, 0.0f, 0.0f, 0.0f}; const bool is_problematic = pchan_flip == NULL && fabsf(dot_v4v4(pchan->bone->arm_mat[0], unit_x)) <= 1e-6; diff --git a/source/blender/blenkernel/intern/armature_deform.c b/source/blender/blenkernel/intern/armature_deform.c index 5e9259f05bb..5f721b49361 100644 --- a/source/blender/blenkernel/intern/armature_deform.c +++ b/source/blender/blenkernel/intern/armature_deform.c @@ -501,7 +501,7 @@ static void armature_deform_coords_impl(const Object *ob_arm, BLI_assert(0); } - if (ELEM(ob_target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) { + if (BKE_object_supports_vertex_groups(ob_target)) { /* get the def_nr for the overall armature vertex group if present */ armature_def_nr = BKE_object_defgroup_name_index(ob_target, defgrp_name); @@ -529,11 +529,9 @@ static void armature_deform_coords_impl(const Object *ob_arm, dverts_len = gps_target->totpoints; } } - } - /* get a vertex-deform-index to posechannel array */ - if (deformflag & ARM_DEF_VGROUP) { - if (ELEM(ob_target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) { + /* get a vertex-deform-index to posechannel array */ + if (deformflag & ARM_DEF_VGROUP) { /* if we have a Mesh, only use dverts if it has them */ if (em_target) { cd_dvert_offset = CustomData_get_offset(&em_target->bm->vdata, CD_MDEFORMVERT); diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index dbd48005e9e..641c003d456 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -688,7 +688,7 @@ static float fcm_cycles_time( ofs = lastkey[0]; } } - if ((ELEM(0, side, mode))) { + if (ELEM(0, side, mode)) { return evaltime; } diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index 47c8df03375..90a97264c8f 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -565,6 +565,7 @@ static PointCloud *join_pointcloud_position_attribute(Span<GeometryInstanceGroup } PointCloud *new_pointcloud = BKE_pointcloud_new_nomain(totpoint); + MutableSpan new_positions{(float3 *)new_pointcloud->co, new_pointcloud->totpoint}; /* Transform each instance's point locations into the new point cloud. */ int offset = 0; @@ -576,9 +577,7 @@ static PointCloud *join_pointcloud_position_attribute(Span<GeometryInstanceGroup } for (const float4x4 &transform : set_group.transforms) { for (const int i : IndexRange(pointcloud->totpoint)) { - const float3 old_position = pointcloud->co[i]; - const float3 new_position = transform * old_position; - copy_v3_v3(new_pointcloud->co[offset + i], new_position); + new_positions[offset + i] = transform * float3(pointcloud->co[i]); } offset += pointcloud->totpoint; } diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index e13b9d543d7..38397f8f307 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -2730,7 +2730,7 @@ void BKE_gpencil_visible_stroke_advanced_iter(ViewLayer *view_layer, int cfra) { bGPdata *gpd = (bGPdata *)ob->data; - const bool is_multiedit = ((GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) && (!GPENCIL_PLAY_ON(gpd))); + const bool is_multiedit = (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd) && (!GPENCIL_PLAY_ON(gpd))); const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0); const bool is_drawing = (gpd->runtime.sbuffer_used > 0); diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.cc index 4dcd94fdeec..785f63a7ba2 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.cc @@ -21,22 +21,24 @@ * \ingroup bke */ -#include <math.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> +#include <cmath> +#include <cstddef> +#include <cstdio> +#include <cstdlib> +#include <cstring> #include "CLG_log.h" #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_float3.hh" #include "BLI_ghash.h" #include "BLI_hash.h" #include "BLI_heap.h" #include "BLI_math_vector.h" #include "BLI_polyfill_2d.h" +#include "BLI_span.hh" #include "BLT_translation.h" @@ -61,6 +63,9 @@ #include "DEG_depsgraph_query.h" +using blender::float3; +using blender::Span; + /* GP Object - Boundbox Support */ /** *Get min/max coordinate bounds for single stroke. @@ -75,20 +80,26 @@ bool BKE_gpencil_stroke_minmax(const bGPDstroke *gps, float r_min[3], float r_max[3]) { - const bGPDspoint *pt; - int i; - bool changed = false; - - if (ELEM(NULL, gps, r_min, r_max)) { + if (gps == nullptr) { return false; } - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if ((use_select == false) || (pt->flag & GP_SPOINT_SELECT)) { - minmax_v3v3_v3(r_min, r_max, &pt->x); + bool changed = false; + if (use_select) { + for (const bGPDspoint &pt : Span(gps->points, gps->totpoints)) { + if (pt.flag & GP_SPOINT_SELECT) { + minmax_v3v3_v3(r_min, r_max, &pt.x); + changed = true; + } + } + } + else { + for (const bGPDspoint &pt : Span(gps->points, gps->totpoints)) { + minmax_v3v3_v3(r_min, r_max, &pt.x); changed = true; } } + return changed; } @@ -105,14 +116,14 @@ bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3]) INIT_MINMAX(r_min, r_max); - if (gpd == NULL) { + if (gpd == nullptr) { return changed; } LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { bGPDframe *gpf = gpl->actframe; - if (gpf != NULL) { + if (gpf != nullptr) { LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { changed |= BKE_gpencil_stroke_minmax(gps, false, r_min, r_max); } @@ -129,11 +140,11 @@ bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3]) */ void BKE_gpencil_centroid_3d(bGPdata *gpd, float r_centroid[3]) { - float min[3], max[3], tot[3]; - + float3 min; + float3 max; BKE_gpencil_data_minmax(gpd, min, max); - add_v3_v3v3(tot, min, max); + const float3 tot = min + max; mul_v3_v3fl(r_centroid, tot, 0.5f); } @@ -153,20 +164,18 @@ void BKE_gpencil_stroke_boundingbox_calc(bGPDstroke *gps) */ static void boundbox_gpencil(Object *ob) { - BoundBox *bb; - bGPdata *gpd; - float min[3], max[3]; - - if (ob->runtime.bb == NULL) { - ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "GPencil boundbox"); + if (ob->runtime.bb == nullptr) { + ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), "GPencil boundbox"); } - bb = ob->runtime.bb; - gpd = ob->data; + BoundBox *bb = ob->runtime.bb; + bGPdata *gpd = (bGPdata *)ob->data; + float3 min; + float3 max; if (!BKE_gpencil_data_minmax(gpd, min, max)) { - min[0] = min[1] = min[2] = -1.0f; - max[0] = max[1] = max[2] = 1.0f; + min = float3(-1); + max = float3(1); } BKE_boundbox_init_from_minmax(bb, min, max); @@ -181,8 +190,8 @@ static void boundbox_gpencil(Object *ob) */ BoundBox *BKE_gpencil_boundbox_get(Object *ob) { - if (ELEM(NULL, ob, ob->data)) { - return NULL; + if (ELEM(nullptr, ob, ob->data)) { + return nullptr; } bGPdata *gpd = (bGPdata *)ob->data; @@ -196,9 +205,9 @@ BoundBox *BKE_gpencil_boundbox_get(Object *ob) /* Update orig object's boundbox with re-computed evaluated values. This function can be * called with the evaluated object and need update the original object bound box data * to keep both values synchronized. */ - if (!ELEM(ob_orig, NULL, ob)) { - if (ob_orig->runtime.bb == NULL) { - ob_orig->runtime.bb = MEM_callocN(sizeof(BoundBox), "GPencil boundbox"); + if (!ELEM(ob_orig, nullptr, ob)) { + if (ob_orig->runtime.bb == nullptr) { + ob_orig->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), "GPencil boundbox"); } for (int i = 0; i < 8; i++) { copy_v3_v3(ob_orig->runtime.bb->vec[i], ob->runtime.bb->vec[i]); @@ -227,7 +236,7 @@ static int stroke_march_next_point(const bGPDstroke *gps, float step_start[3]; float point[3]; int next_point_index = index_next_pt; - bGPDspoint *pt = NULL; + bGPDspoint *pt = nullptr; if (!(next_point_index < gps->totpoints)) { return -1; @@ -295,7 +304,7 @@ static int stroke_march_next_point_no_interp(const bGPDstroke *gps, float step_start[3]; float point[3]; int next_point_index = index_next_pt; - bGPDspoint *pt = NULL; + bGPDspoint *pt = nullptr; if (!(next_point_index < gps->totpoints)) { return -1; @@ -336,7 +345,7 @@ static int stroke_march_count(const bGPDstroke *gps, const float dist) int point_count = 0; float point[3]; int next_point_index = 1; - bGPDspoint *pt = NULL; + bGPDspoint *pt = nullptr; pt = &gps->points[0]; copy_v3_v3(point, &pt->x); @@ -369,14 +378,14 @@ static void stroke_defvert_create_nr_list(MDeformVert *dv_list, for (j = 0; j < dv->totweight; j++) { bool found = false; dw = &dv->dw[j]; - for (ld = result->first; ld; ld = ld->next) { + for (ld = (LinkData *)result->first; ld; ld = ld->next) { if (ld->data == POINTER_FROM_INT(dw->def_nr)) { found = true; break; } } if (!found) { - ld = MEM_callocN(sizeof(LinkData), "def_nr_item"); + ld = (LinkData *)MEM_callocN(sizeof(LinkData), "def_nr_item"); ld->data = POINTER_FROM_INT(dw->def_nr); BLI_addtail(result, ld); tw++; @@ -391,14 +400,15 @@ static MDeformVert *stroke_defvert_new_count(int count, int totweight, ListBase { int i, j; LinkData *ld; - MDeformVert *dst = MEM_mallocN(count * sizeof(MDeformVert), "new_deformVert"); + MDeformVert *dst = (MDeformVert *)MEM_mallocN(count * sizeof(MDeformVert), "new_deformVert"); for (i = 0; i < count; i++) { - dst[i].dw = MEM_mallocN(sizeof(MDeformWeight) * totweight, "new_deformWeight"); + dst[i].dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * totweight, + "new_deformWeight"); dst[i].totweight = totweight; j = 0; /* re-assign deform groups */ - for (ld = def_nr_list->first; ld; ld = ld->next) { + for (ld = (LinkData *)def_nr_list->first; ld; ld = ld->next) { dst[i].dw[j].def_nr = POINTER_AS_INT(ld->data); j++; } @@ -429,10 +439,10 @@ static void stroke_interpolate_deform_weights( bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist, const bool select) { bGPDspoint *pt = gps->points; - bGPDspoint *pt1 = NULL; - bGPDspoint *pt2 = NULL; + bGPDspoint *pt1 = nullptr; + bGPDspoint *pt2 = nullptr; LinkData *ld; - ListBase def_nr_list = {0}; + ListBase def_nr_list = {nullptr}; if (gps->totpoints < 2 || dist < FLT_EPSILON) { return false; @@ -440,12 +450,13 @@ bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist, /* TODO: Implement feature point preservation. */ int count = stroke_march_count(gps, dist); - bGPDspoint *new_pt = MEM_callocN(sizeof(bGPDspoint) * count, "gp_stroke_points_sampled"); - MDeformVert *new_dv = NULL; + bGPDspoint *new_pt = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * count, + "gp_stroke_points_sampled"); + MDeformVert *new_dv = nullptr; int result_totweight; - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { stroke_defvert_create_nr_list(gps->dvert, gps->totpoints, &def_nr_list, &result_totweight); new_dv = stroke_defvert_new_count(count, result_totweight, &def_nr_list); } @@ -513,7 +524,7 @@ bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist, /* Free original weight data. */ BKE_gpencil_free_stroke_weights(gps); MEM_freeN(gps->dvert); - while ((ld = BLI_pophead(&def_nr_list))) { + while ((ld = (LinkData *)BLI_pophead(&def_nr_list))) { MEM_freeN(ld); } @@ -610,26 +621,27 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const if (new_count == 1) { BKE_gpencil_free_stroke_weights(gps); MEM_freeN(gps->points); - gps->points = NULL; - gps->dvert = NULL; + gps->points = nullptr; + gps->dvert = nullptr; gps->totpoints = 0; return false; } - new_pt = MEM_callocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed"); + new_pt = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed"); for (int i = 0; i < new_count; i++) { memcpy(&new_pt[i], &pt[i + index_from], sizeof(bGPDspoint)); } if (gps->dvert) { - new_dv = MEM_callocN(sizeof(MDeformVert) * new_count, "gp_stroke_dverts_trimmed"); + new_dv = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_count, + "gp_stroke_dverts_trimmed"); for (int i = 0; i < new_count; i++) { dv = &gps->dvert[i + index_from]; new_dv[i].flag = dv->flag; new_dv[i].totweight = dv->totweight; - new_dv[i].dw = MEM_callocN(sizeof(MDeformWeight) * dv->totweight, - "gp_stroke_dverts_dw_trimmed"); + new_dv[i].dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight, + "gp_stroke_dverts_dw_trimmed"); for (int j = 0; j < dv->totweight; j++) { new_dv[i].dw[j].weight = dv->dw[j].weight; new_dv[i].dw[j].def_nr = dv->dw[j].def_nr; @@ -685,14 +697,14 @@ bool BKE_gpencil_stroke_split(bGPdata *gpd, } if (gps->dvert) { - new_dv = MEM_callocN(sizeof(MDeformVert) * new_count, - "gp_stroke_dverts_remaining(MDeformVert)"); + new_dv = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_count, + "gp_stroke_dverts_remaining(MDeformVert)"); for (int i = 0; i < new_count; i++) { dv = &gps->dvert[i + before_index]; new_dv[i].flag = dv->flag; new_dv[i].totweight = dv->totweight; - new_dv[i].dw = MEM_callocN(sizeof(MDeformWeight) * dv->totweight, - "gp_stroke_dverts_dw_remaining(MDeformWeight)"); + new_dv[i].dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight, + "gp_stroke_dverts_dw_remaining(MDeformWeight)"); for (int j = 0; j < dv->totweight; j++) { new_dv[i].dw[j].weight = dv->dw[j].weight; new_dv[i].dw[j].def_nr = dv->dw[j].def_nr; @@ -1301,11 +1313,12 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps) /* allocate memory for temporary areas */ gps->tot_triangles = gps->totpoints - 2; - uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, - "GP Stroke temp triangulation"); - float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, - "GP Stroke temp 2d points"); - float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data"); + uint(*tmp_triangles)[3] = (uint(*)[3])MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, + "GP Stroke temp triangulation"); + float(*points2d)[2] = (float(*)[2])MEM_mallocN(sizeof(*points2d) * gps->totpoints, + "GP Stroke temp 2d points"); + float(*uv)[2] = (float(*)[2])MEM_mallocN(sizeof(*uv) * gps->totpoints, + "GP Stroke temp 2d uv data"); int direction = 0; @@ -1326,8 +1339,8 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps) /* Save triangulation data. */ if (gps->tot_triangles > 0) { MEM_SAFE_FREE(gps->triangles); - gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, - "GP Stroke triangulation"); + gps->triangles = (bGPDtriangle *)MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, + "GP Stroke triangulation"); for (int i = 0; i < gps->tot_triangles; i++) { memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3])); @@ -1344,7 +1357,7 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps) MEM_freeN(gps->triangles); } - gps->triangles = NULL; + gps->triangles = nullptr; } /* clear memory */ @@ -1359,7 +1372,7 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps) */ void BKE_gpencil_stroke_uv_update(bGPDstroke *gps) { - if (gps == NULL || gps->totpoints == 0) { + if (gps == nullptr || gps->totpoints == 0) { return; } @@ -1379,11 +1392,11 @@ void BKE_gpencil_stroke_uv_update(bGPDstroke *gps) */ void BKE_gpencil_stroke_geometry_update(bGPdata *gpd, bGPDstroke *gps) { - if (gps == NULL) { + if (gps == nullptr) { return; } - if (gps->editcurve != NULL) { + if (gps->editcurve != nullptr) { if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) { /* curve geometry was updated: stroke needs recalculation */ if (gps->flag & GP_STROKE_NEEDS_CURVE_UPDATE) { @@ -1519,20 +1532,20 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps) if (intersect) { /* save points */ - bGPDspoint *old_points = MEM_dupallocN(gps->points); - MDeformVert *old_dvert = NULL; - MDeformVert *dvert_src = NULL; + bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points); + MDeformVert *old_dvert = nullptr; + MDeformVert *dvert_src = nullptr; - if (gps->dvert != NULL) { - old_dvert = MEM_dupallocN(gps->dvert); + if (gps->dvert != nullptr) { + old_dvert = (MDeformVert *)MEM_dupallocN(gps->dvert); } /* resize gps */ int newtot = end - start + 1; - gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot); - if (gps->dvert != NULL) { - gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot); + gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * newtot); + if (gps->dvert != nullptr) { + gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot); } for (int i = 0; i < newtot; i++) { @@ -1540,7 +1553,7 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps) bGPDspoint *pt_src = &old_points[idx]; bGPDspoint *pt_new = &gps->points[i]; memcpy(pt_new, pt_src, sizeof(bGPDspoint)); - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert_src = &old_dvert[idx]; MDeformVert *dvert = &gps->dvert[i]; memcpy(dvert, dvert_src, sizeof(MDeformVert)); @@ -1570,8 +1583,8 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps) */ bool BKE_gpencil_stroke_close(bGPDstroke *gps) { - bGPDspoint *pt1 = NULL; - bGPDspoint *pt2 = NULL; + bGPDspoint *pt1 = nullptr; + bGPDspoint *pt2 = nullptr; /* Only can close a stroke with 3 points or more. */ if (gps->totpoints < 3) { @@ -1605,9 +1618,9 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps) /* Resize stroke array. */ int old_tot = gps->totpoints; gps->totpoints += tot_newpoints; - gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints); - if (gps->dvert != NULL) { - gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints); + gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints); + if (gps->dvert != nullptr) { + gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints); } /* Generate new points */ @@ -1629,7 +1642,7 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps) interp_v4_v4v4(pt->vert_color, pt1->vert_color, pt2->vert_color, step); /* Set weights. */ - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { MDeformVert *dvert1 = &gps->dvert[old_tot - 1]; MDeformWeight *dw1 = BKE_defvert_ensure_index(dvert1, 0); float weight_1 = dw1 ? dw1->weight : 0.0f; @@ -1663,7 +1676,7 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps) void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, const short tag) { bGPDspoint *pt; - MDeformVert *dvert = NULL; + MDeformVert *dvert = nullptr; int i; int tot = gps->totpoints; /* number of points in new buffer */ @@ -1693,30 +1706,32 @@ void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, } else { /* just copy all points to keep into a smaller buffer */ - bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot, "new gp stroke points copy"); + bGPDspoint *new_points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * tot, + "new gp stroke points copy"); bGPDspoint *npt = new_points; - MDeformVert *new_dvert = NULL; - MDeformVert *ndvert = NULL; + MDeformVert *new_dvert = nullptr; + MDeformVert *ndvert = nullptr; - if (gps->dvert != NULL) { - new_dvert = MEM_callocN(sizeof(MDeformVert) * tot, "new gp stroke weights copy"); + if (gps->dvert != nullptr) { + new_dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * tot, + "new gp stroke weights copy"); ndvert = new_dvert; } - (gps->dvert != NULL) ? dvert = gps->dvert : NULL; + (gps->dvert != nullptr) ? dvert = gps->dvert : nullptr; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if ((pt->flag & tag) == 0) { *npt = *pt; npt++; - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { *ndvert = *dvert; - ndvert->dw = MEM_dupallocN(dvert->dw); + ndvert->dw = (MDeformWeight *)MEM_dupallocN(dvert->dw); ndvert++; } } - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert++; } } @@ -1789,15 +1804,15 @@ void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3]) */ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float epsilon) { - bGPDspoint *old_points = MEM_dupallocN(gps->points); + bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points); int totpoints = gps->totpoints; - char *marked = NULL; + char *marked = nullptr; char work; int start = 0; int end = gps->totpoints - 1; - marked = MEM_callocN(totpoints, "GP marked array"); + marked = (char *)MEM_callocN(totpoints, "GP marked array"); marked[start] = 1; marked[end] = 1; @@ -1849,11 +1864,11 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e } /* adding points marked */ - MDeformVert *old_dvert = NULL; - MDeformVert *dvert_src = NULL; + MDeformVert *old_dvert = nullptr; + MDeformVert *dvert_src = nullptr; - if (gps->dvert != NULL) { - old_dvert = MEM_dupallocN(gps->dvert); + if (gps->dvert != nullptr) { + old_dvert = (MDeformVert *)MEM_dupallocN(gps->dvert); } /* resize gps */ int j = 0; @@ -1863,7 +1878,7 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e if ((marked[i]) || (i == 0) || (i == totpoints - 1)) { memcpy(pt, pt_src, sizeof(bGPDspoint)); - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert_src = &old_dvert[i]; MDeformVert *dvert = &gps->dvert[j]; memcpy(dvert, dvert_src, sizeof(MDeformVert)); @@ -1874,7 +1889,7 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e j++; } else { - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert_src = &old_dvert[i]; BKE_gpencil_free_point_weights(dvert_src); } @@ -1903,12 +1918,12 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps) } /* save points */ - bGPDspoint *old_points = MEM_dupallocN(gps->points); - MDeformVert *old_dvert = NULL; - MDeformVert *dvert_src = NULL; + bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points); + MDeformVert *old_dvert = nullptr; + MDeformVert *dvert_src = nullptr; - if (gps->dvert != NULL) { - old_dvert = MEM_dupallocN(gps->dvert); + if (gps->dvert != nullptr) { + old_dvert = (MDeformVert *)MEM_dupallocN(gps->dvert); } /* resize gps */ @@ -1918,9 +1933,9 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps) } newtot += 2; - gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot); - if (gps->dvert != NULL) { - gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot); + gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * newtot); + if (gps->dvert != nullptr) { + gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot); } int j = 0; @@ -1930,7 +1945,7 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps) if ((i == 0) || (i == gps->totpoints - 1) || ((i % 2) > 0.0)) { memcpy(pt, pt_src, sizeof(bGPDspoint)); - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert_src = &old_dvert[i]; MDeformVert *dvert = &gps->dvert[j]; memcpy(dvert, dvert_src, sizeof(MDeformVert)); @@ -1941,7 +1956,7 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps) j++; } else { - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert_src = &old_dvert[i]; BKE_gpencil_free_point_weights(dvert_src); } @@ -1966,25 +1981,25 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps) void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int type) { bGPDspoint *temp_points; - MDeformVert *temp_dverts = NULL; - MDeformVert *dvert = NULL; - MDeformVert *dvert_final = NULL; - MDeformVert *dvert_next = NULL; + MDeformVert *temp_dverts = nullptr; + MDeformVert *dvert = nullptr; + MDeformVert *dvert_final = nullptr; + MDeformVert *dvert_next = nullptr; int totnewpoints, oldtotpoints; int i2; for (int s = 0; s < level; s++) { totnewpoints = gps->totpoints - 1; /* duplicate points in a temp area */ - temp_points = MEM_dupallocN(gps->points); + temp_points = (bGPDspoint *)MEM_dupallocN(gps->points); oldtotpoints = gps->totpoints; /* resize the points arrays */ gps->totpoints += totnewpoints; - gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints); - if (gps->dvert != NULL) { - temp_dverts = MEM_dupallocN(gps->dvert); - gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints); + gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints); + if (gps->dvert != nullptr) { + temp_dverts = (MDeformVert *)MEM_dupallocN(gps->dvert); + gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints); } /* move points from last to first to new place */ @@ -2002,7 +2017,7 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int pt_final->runtime.idx_orig = pt->runtime.idx_orig; copy_v4_v4(pt_final->vert_color, pt->vert_color); - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert = &temp_dverts[i]; dvert_final = &gps->dvert[i2]; dvert_final->totweight = dvert->totweight; @@ -2023,17 +2038,17 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int pt_final->strength = interpf(pt->strength, next->strength, 0.5f); CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f); pt_final->time = interpf(pt->time, next->time, 0.5f); - pt_final->runtime.pt_orig = NULL; + pt_final->runtime.pt_orig = nullptr; pt_final->flag = 0; interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f); - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert = &temp_dverts[i]; dvert_next = &temp_dverts[i + 1]; dvert_final = &gps->dvert[i2]; dvert_final->totweight = dvert->totweight; - dvert_final->dw = MEM_dupallocN(dvert->dw); + dvert_final->dw = (MDeformWeight *)MEM_dupallocN(dvert->dw); /* interpolate weight values */ for (int d = 0; d < dvert->totweight; d++) { @@ -2055,7 +2070,7 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int /* Move points to smooth stroke (not simple type). */ if (type != GP_SUBDIV_SIMPLE) { /* duplicate points in a temp area with the new subdivide data */ - temp_points = MEM_dupallocN(gps->points); + temp_points = (bGPDspoint *)MEM_dupallocN(gps->points); /* extreme points are not changed */ for (int i = 0; i < gps->totpoints - 2; i++) { @@ -2093,8 +2108,8 @@ void BKE_gpencil_stroke_merge_distance(bGPdata *gpd, const float threshold, const bool use_unselected) { - bGPDspoint *pt = NULL; - bGPDspoint *pt_next = NULL; + bGPDspoint *pt = nullptr; + bGPDspoint *pt_next = nullptr; float tagged = false; /* Use square distance to speed up loop */ const float th_square = threshold * threshold; @@ -2160,7 +2175,7 @@ void BKE_gpencil_stroke_merge_distance(bGPdata *gpd, BKE_gpencil_stroke_geometry_update(gpd, gps); } -typedef struct GpEdge { +struct GpEdge { uint v1, v2; /* Coordinates. */ float v1_co[3], v2_co[3]; @@ -2169,7 +2184,7 @@ typedef struct GpEdge { /* Direction of the segment. */ float vec[3]; int flag; -} GpEdge; +}; static int gpencil_next_edge( GpEdge *gp_edges, int totedges, GpEdge *gped_init, const float threshold, const bool reverse) @@ -2262,13 +2277,13 @@ static void gpencil_generate_edgeloops(Object *ob, /* Arrays for all edge vertices (forward and backward) that form a edge loop. * This is reused for each edgeloop to create gpencil stroke. */ - uint *stroke = MEM_callocN(sizeof(uint) * me->totedge * 2, __func__); - uint *stroke_fw = MEM_callocN(sizeof(uint) * me->totedge, __func__); - uint *stroke_bw = MEM_callocN(sizeof(uint) * me->totedge, __func__); + uint *stroke = (uint *)MEM_callocN(sizeof(uint) * me->totedge * 2, __func__); + uint *stroke_fw = (uint *)MEM_callocN(sizeof(uint) * me->totedge, __func__); + uint *stroke_bw = (uint *)MEM_callocN(sizeof(uint) * me->totedge, __func__); /* Create array with all edges. */ - GpEdge *gp_edges = MEM_callocN(sizeof(GpEdge) * me->totedge, __func__); - GpEdge *gped = NULL; + GpEdge *gp_edges = (GpEdge *)MEM_callocN(sizeof(GpEdge) * me->totedge, __func__); + GpEdge *gped = nullptr; for (int i = 0; i < me->totedge; i++) { MEdge *ed = &me->medge[i]; gped = &gp_edges[i]; @@ -2321,7 +2336,7 @@ static void gpencil_generate_edgeloops(Object *ob, /* Look backward edges. */ int totbw = gpencil_walk_edge(v_table, gp_edges, me->totedge, stroke_bw, e, angle, true); - BLI_ghash_free(v_table, NULL, NULL); + BLI_ghash_free(v_table, nullptr, nullptr); /* Join both arrays. */ int array_len = 0; @@ -2423,7 +2438,7 @@ static int gpencil_material_find_index_by_name(Object *ob, const char *name) { for (int i = 0; i < ob->totcol; i++) { Material *ma = BKE_object_material_get(ob, i + 1); - if ((ma != NULL) && (ma->gp_style != NULL) && (STREQ(ma->id.name + 2, name))) { + if ((ma != nullptr) && (ma->gp_style != nullptr) && (STREQ(ma->id.name + 2, name))) { return i; } } @@ -2474,7 +2489,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain, const bool use_seams, const bool use_faces) { - if (ELEM(NULL, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) { + if (ELEM(nullptr, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == nullptr)) { return false; } @@ -2511,7 +2526,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain, make_element_name(ob_mesh->id.name + 2, "Fills", 128, element_name); /* Create Layer and Frame. */ bGPDlayer *gpl_fill = BKE_gpencil_layer_named_get(gpd, element_name); - if (gpl_fill == NULL) { + if (gpl_fill == nullptr) { gpl_fill = BKE_gpencil_layer_addnew(gpd, element_name, true, false); } bGPDframe *gpf_fill = BKE_gpencil_layer_frame_get( @@ -2524,11 +2539,11 @@ bool BKE_gpencil_convert_mesh(Main *bmain, int mat_idx = 0; Material *ma = BKE_object_material_get(ob_mesh, mp->mat_nr + 1); make_element_name( - ob_mesh->id.name + 2, (ma != NULL) ? ma->id.name + 2 : "Fill", 64, element_name); + ob_mesh->id.name + 2, (ma != nullptr) ? ma->id.name + 2 : "Fill", 64, element_name); mat_idx = BKE_gpencil_material_find_index_by_name_prefix(ob_gp, element_name); if (mat_idx == -1) { float color[4]; - if (ma != NULL) { + if (ma != nullptr) { copy_v3_v3(color, &ma->r); color[3] = 1.0f; } @@ -2567,7 +2582,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain, /* Create Layer and Frame. */ bGPDlayer *gpl_stroke = BKE_gpencil_layer_named_get(gpd, element_name); - if (gpl_stroke == NULL) { + if (gpl_stroke == nullptr) { gpl_stroke = BKE_gpencil_layer_addnew(gpd, element_name, true, false); } bGPDframe *gpf_stroke = BKE_gpencil_layer_frame_get( @@ -2589,7 +2604,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain, */ void BKE_gpencil_transform(bGPdata *gpd, const float mat[4][4]) { - if (gpd == NULL) { + if (gpd == nullptr) { return; } @@ -2625,7 +2640,7 @@ int BKE_gpencil_stroke_point_count(const bGPdata *gpd) { int total_points = 0; - if (gpd == NULL) { + if (gpd == nullptr) { return 0; } @@ -2650,7 +2665,7 @@ int BKE_gpencil_stroke_point_count(const bGPdata *gpd) /* Used for "move only origins" in object_data_transform.c */ void BKE_gpencil_point_coords_get(bGPdata *gpd, GPencilPointCoordinates *elem_data) { - if (gpd == NULL) { + if (gpd == nullptr) { return; } @@ -2681,7 +2696,7 @@ void BKE_gpencil_point_coords_get(bGPdata *gpd, GPencilPointCoordinates *elem_da /* Used for "move only origins" in object_data_transform.c */ void BKE_gpencil_point_coords_apply(bGPdata *gpd, const GPencilPointCoordinates *elem_data) { - if (gpd == NULL) { + if (gpd == nullptr) { return; } @@ -2717,7 +2732,7 @@ void BKE_gpencil_point_coords_apply_with_mat4(bGPdata *gpd, const GPencilPointCoordinates *elem_data, const float mat[4][4]) { - if (gpd == NULL) { + if (gpd == nullptr) { return; } @@ -2818,24 +2833,24 @@ void BKE_gpencil_stroke_flip(bGPDstroke *gps) * that should be kept when splitting up a stroke. Used in: * gpencil_stroke_delete_tagged_points() */ -typedef struct tGPDeleteIsland { +struct tGPDeleteIsland { int start_idx; int end_idx; -} tGPDeleteIsland; +}; static void gpencil_stroke_join_islands(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps_first, bGPDstroke *gps_last) { - bGPDspoint *pt = NULL; - bGPDspoint *pt_final = NULL; + bGPDspoint *pt = nullptr; + bGPDspoint *pt_final = nullptr; const int totpoints = gps_first->totpoints + gps_last->totpoints; /* create new stroke */ bGPDstroke *join_stroke = BKE_gpencil_stroke_duplicate(gps_first, false, true); - join_stroke->points = MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__); + join_stroke->points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__); join_stroke->totpoints = totpoints; join_stroke->flag &= ~GP_STROKE_CYCLIC; @@ -2868,17 +2883,17 @@ static void gpencil_stroke_join_islands(bGPdata *gpd, } /* Copy over vertex weight data (if available) */ - if ((gps_first->dvert != NULL) || (gps_last->dvert != NULL)) { - join_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * totpoints, __func__); - MDeformVert *dvert_src = NULL; - MDeformVert *dvert_dst = NULL; + if ((gps_first->dvert != nullptr) || (gps_last->dvert != nullptr)) { + join_stroke->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * totpoints, __func__); + MDeformVert *dvert_src = nullptr; + MDeformVert *dvert_dst = nullptr; /* Copy weights (last before). */ e1 = 0; e2 = 0; for (int i = 0; i < totpoints; i++) { dvert_dst = &join_stroke->dvert[i]; - dvert_src = NULL; + dvert_src = nullptr; if (i < gps_last->totpoints) { if (gps_last->dvert) { dvert_src = &gps_last->dvert[e1]; @@ -2893,7 +2908,7 @@ static void gpencil_stroke_join_islands(bGPdata *gpd, } if ((dvert_src) && (dvert_src->dw)) { - dvert_dst->dw = MEM_dupallocN(dvert_src->dw); + dvert_dst->dw = (MDeformWeight *)MEM_dupallocN(dvert_src->dw); } } } @@ -2934,13 +2949,13 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, bool select, int limit) { - tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, - "gp_point_islands"); + tGPDeleteIsland *islands = (tGPDeleteIsland *)MEM_callocN( + sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands"); bool in_island = false; int num_islands = 0; - bGPDstroke *new_stroke = NULL; - bGPDstroke *gps_first = NULL; + bGPDstroke *new_stroke = nullptr; + bGPDstroke *gps_first = nullptr; const bool is_cyclic = (bool)(gps->flag & GP_STROKE_CYCLIC); /* First Pass: Identify start/end of islands */ @@ -2982,7 +2997,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, new_stroke = BKE_gpencil_stroke_duplicate(gps, false, true); /* if cyclic and first stroke, save to join later */ - if ((is_cyclic) && (gps_first == NULL)) { + if ((is_cyclic) && (gps_first == nullptr)) { gps_first = new_stroke; } @@ -2992,17 +3007,17 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, new_stroke->totpoints = island->end_idx - island->start_idx + 1; /* Copy over the relevant point data */ - new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, - "gp delete stroke fragment"); + new_stroke->points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, + "gp delete stroke fragment"); memcpy(new_stroke->points, gps->points + island->start_idx, sizeof(bGPDspoint) * new_stroke->totpoints); /* Copy over vertex weight data (if available) */ - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { /* Copy over the relevant vertex-weight points */ - new_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * new_stroke->totpoints, - "gp delete stroke fragment weight"); + new_stroke->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_stroke->totpoints, + "gp delete stroke fragment weight"); memcpy(new_stroke->dvert, gps->dvert + island->start_idx, sizeof(MDeformVert) * new_stroke->totpoints); @@ -3013,7 +3028,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, MDeformVert *dvert_src = &gps->dvert[e]; MDeformVert *dvert_dst = &new_stroke->dvert[i]; if (dvert_src->dw) { - dvert_dst->dw = MEM_dupallocN(dvert_src->dw); + dvert_dst->dw = (MDeformWeight *)MEM_dupallocN(dvert_src->dw); } e++; } @@ -3047,7 +3062,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, /* Add new stroke to the frame or delete if below limit */ if ((limit > 0) && (new_stroke->totpoints <= limit)) { if (gps_first == new_stroke) { - gps_first = NULL; + gps_first = nullptr; } BKE_gpencil_free_stroke(new_stroke); } @@ -3064,7 +3079,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, } } /* if cyclic, need to join last stroke with first stroke */ - if ((is_cyclic) && (gps_first != NULL) && (gps_first != new_stroke)) { + if ((is_cyclic) && (gps_first != nullptr) && (gps_first != new_stroke)) { gpencil_stroke_join_islands(gpd, gpf, gps_first, new_stroke); } } @@ -3086,13 +3101,13 @@ void BKE_gpencil_curve_delete_tagged_points(bGPdata *gpd, bGPDcurve *gpc, int tag_flags) { - if (gpc == NULL) { + if (gpc == nullptr) { return; } const bool is_cyclic = gps->flag & GP_STROKE_CYCLIC; const int idx_last = gpc->tot_curve_points - 1; - bGPDstroke *gps_first = NULL; - bGPDstroke *gps_last = NULL; + bGPDstroke *gps_first = nullptr; + bGPDstroke *gps_last = nullptr; int idx_start = 0; int idx_end = 0; @@ -3123,11 +3138,11 @@ void BKE_gpencil_curve_delete_tagged_points(bGPdata *gpd, } bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps, false, false); - new_stroke->points = NULL; + new_stroke->points = nullptr; new_stroke->flag &= ~GP_STROKE_CYCLIC; new_stroke->editcurve = BKE_gpencil_stroke_editcurve_new(island_length); - if (gps_first == NULL) { + if (gps_first == nullptr) { gps_first = new_stroke; } @@ -3155,15 +3170,15 @@ void BKE_gpencil_curve_delete_tagged_points(bGPdata *gpd, } /* join first and last stroke if cyclic */ - if (is_cyclic && gps_first != NULL && gps_last != NULL && gps_first != gps_last) { + if (is_cyclic && gps_first != nullptr && gps_last != nullptr && gps_first != gps_last) { bGPDcurve *gpc_first = gps_first->editcurve; bGPDcurve *gpc_last = gps_last->editcurve; int first_tot_points = gpc_first->tot_curve_points; int old_tot_points = gpc_last->tot_curve_points; gpc_last->tot_curve_points = first_tot_points + old_tot_points; - gpc_last->curve_points = MEM_recallocN(gpc_last->curve_points, - sizeof(bGPDcurve_point) * gpc_last->tot_curve_points); + gpc_last->curve_points = (bGPDcurve_point *)MEM_recallocN( + gpc_last->curve_points, sizeof(bGPDcurve_point) * gpc_last->tot_curve_points); /* copy data from first to last */ memcpy(gpc_last->curve_points + old_tot_points, gpc_first->curve_points, @@ -3196,14 +3211,16 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps, { bGPDspoint *newpoint; - gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1)); - if (gps->dvert != NULL) { - gps->dvert = MEM_reallocN(gps->dvert, sizeof(MDeformVert) * (gps->totpoints + 1)); + gps->points = (bGPDspoint *)MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1)); + if (gps->dvert != nullptr) { + gps->dvert = (MDeformVert *)MEM_reallocN(gps->dvert, + sizeof(MDeformVert) * (gps->totpoints + 1)); } else { /* If destination has weight add weight to origin. */ - if (dvert != NULL) { - gps->dvert = MEM_callocN(sizeof(MDeformVert) * (gps->totpoints + 1), __func__); + if (dvert != nullptr) { + gps->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * (gps->totpoints + 1), + __func__); } } @@ -3219,16 +3236,16 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps, newpoint->time = point->time + deltatime; copy_v4_v4(newpoint->vert_color, point->vert_color); - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { MDeformVert *newdvert = &gps->dvert[gps->totpoints - 1]; - if (dvert != NULL) { + if (dvert != nullptr) { newdvert->totweight = dvert->totweight; - newdvert->dw = MEM_dupallocN(dvert->dw); + newdvert->dw = (MDeformWeight *)MEM_dupallocN(dvert->dw); } else { newdvert->totweight = 0; - newdvert->dw = NULL; + newdvert->dw = nullptr; } } } @@ -3246,7 +3263,7 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, float deltatime = 0.0f; /* sanity checks */ - if (ELEM(NULL, gps_a, gps_b)) { + if (ELEM(nullptr, gps_a, gps_b)) { return; } @@ -3308,11 +3325,11 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, point = gps_a->points[gps_a->totpoints - 1]; deltatime = point.time; - gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, 0.0f); + gpencil_stroke_copy_point(gps_a, nullptr, &point, delta, 0.0f, 0.0f, 0.0f); /* 2nd: add one head point to finish invisible area */ point = gps_b->points[0]; - gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, deltatime); + gpencil_stroke_copy_point(gps_a, nullptr, &point, delta, 0.0f, 0.0f, deltatime); } const float ratio = (fit_thickness && gps_a->thickness > 0.0f) ? @@ -3321,7 +3338,7 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, /* 3rd: add all points */ for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) { - MDeformVert *dvert = (gps_b->dvert) ? &gps_b->dvert[i] : NULL; + MDeformVert *dvert = (gps_b->dvert) ? &gps_b->dvert[i] : nullptr; gpencil_stroke_copy_point( gps_a, dvert, pt, delta, pt->pressure * ratio, pt->strength, deltatime); } @@ -3340,16 +3357,16 @@ void BKE_gpencil_stroke_copy_to_keyframes( if (gpf->framenum != cfra) { bGPDframe *gpf_new = BKE_gpencil_layer_frame_find(gpl, cfra); - if (gpf_new == NULL) { + if (gpf_new == nullptr) { gpf_new = BKE_gpencil_frame_addnew(gpl, cfra); } - if (gpf_new == NULL) { + if (gpf_new == nullptr) { continue; } bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(gps, true, true); - if (gps_new == NULL) { + if (gps_new == nullptr) { continue; } @@ -3363,38 +3380,38 @@ void BKE_gpencil_stroke_copy_to_keyframes( } /* Free hash table. */ - BLI_ghash_free(frame_list, NULL, NULL); + BLI_ghash_free(frame_list, nullptr, nullptr); } /* Stroke Uniform Subdivide ------------------------------------- */ -typedef struct tSamplePoint { +struct tSamplePoint { struct tSamplePoint *next, *prev; float x, y, z; float pressure, strength, time; float vertex_color[4]; struct MDeformWeight *dw; int totweight; -} tSamplePoint; +}; -typedef struct tSampleEdge { +struct tSampleEdge { float length_sq; tSamplePoint *from; tSamplePoint *to; -} tSampleEdge; +}; /* Helper: creates a tSamplePoint from a bGPDspoint and (optionally) a MDeformVert. */ static tSamplePoint *new_sample_point_from_gp_point(const bGPDspoint *pt, const MDeformVert *dvert) { - tSamplePoint *new_pt = MEM_callocN(sizeof(tSamplePoint), __func__); + tSamplePoint *new_pt = (tSamplePoint *)MEM_callocN(sizeof(tSamplePoint), __func__); copy_v3_v3(&new_pt->x, &pt->x); new_pt->pressure = pt->pressure; new_pt->strength = pt->strength; new_pt->time = pt->time; copy_v4_v4((float *)&new_pt->vertex_color, (float *)&pt->vert_color); - if (dvert != NULL) { + if (dvert != nullptr) { new_pt->totweight = dvert->totweight; - new_pt->dw = MEM_callocN(sizeof(MDeformWeight) * new_pt->totweight, __func__); + new_pt->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * new_pt->totweight, __func__); for (uint i = 0; i < new_pt->totweight; ++i) { MDeformWeight *dw = &new_pt->dw[i]; MDeformWeight *dw_from = &dvert->dw[i]; @@ -3409,7 +3426,7 @@ static tSamplePoint *new_sample_point_from_gp_point(const bGPDspoint *pt, const * the edge. */ static tSampleEdge *new_sample_edge_from_sample_points(tSamplePoint *from, tSamplePoint *to) { - tSampleEdge *new_edge = MEM_callocN(sizeof(tSampleEdge), __func__); + tSampleEdge *new_edge = (tSampleEdge *)MEM_callocN(sizeof(tSampleEdge), __func__); new_edge->from = from; new_edge->to = to; new_edge->length_sq = len_squared_v3v3(&from->x, &to->x); @@ -3431,27 +3448,27 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, const bool select) { /* Stroke needs at least two points and strictly less points than the target number. */ - if (gps == NULL || gps->totpoints < 2 || gps->totpoints >= target_number) { + if (gps == nullptr || gps->totpoints < 2 || gps->totpoints >= target_number) { return; } const int totpoints = gps->totpoints; - const bool has_dverts = (gps->dvert != NULL); + const bool has_dverts = (gps->dvert != nullptr); const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC); - ListBase points = {NULL, NULL}; + ListBase points = {nullptr, nullptr}; Heap *edges = BLI_heap_new(); /* Add all points into list. */ for (uint32_t i = 0; i < totpoints; ++i) { bGPDspoint *pt = &gps->points[i]; - MDeformVert *dvert = has_dverts ? &gps->dvert[i] : NULL; + MDeformVert *dvert = has_dverts ? &gps->dvert[i] : nullptr; tSamplePoint *sp = new_sample_point_from_gp_point(pt, dvert); BLI_addtail(&points, sp); } /* Iterate over edges and insert them into the heap. */ - for (tSamplePoint *pt = ((tSamplePoint *)points.first)->next; pt != NULL; pt = pt->next) { + for (tSamplePoint *pt = ((tSamplePoint *)points.first)->next; pt != nullptr; pt = pt->next) { tSampleEdge *se = new_sample_edge_from_sample_points(pt->prev, pt); /* BLI_heap is a min-heap, but we need the largest key to be at the top, so we take the * negative of the squared length. */ @@ -3459,8 +3476,8 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, } if (is_cyclic) { - tSamplePoint *sp_first = points.first; - tSamplePoint *sp_last = points.last; + tSamplePoint *sp_first = (tSamplePoint *)points.first; + tSamplePoint *sp_last = (tSamplePoint *)points.last; tSampleEdge *se = new_sample_edge_from_sample_points(sp_last, sp_first); BLI_heap_insert(edges, -(se->length_sq), se); } @@ -3469,12 +3486,12 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, BLI_assert(num_points_needed > 0); while (num_points_needed > 0) { - tSampleEdge *se = BLI_heap_pop_min(edges); + tSampleEdge *se = (tSampleEdge *)BLI_heap_pop_min(edges); tSamplePoint *sp = se->from; tSamplePoint *sp_next = se->to; /* Subdivide the edge. */ - tSamplePoint *new_sp = MEM_callocN(sizeof(tSamplePoint), __func__); + tSamplePoint *new_sp = (tSamplePoint *)MEM_callocN(sizeof(tSamplePoint), __func__); interp_v3_v3v3(&new_sp->x, &sp->x, &sp_next->x, 0.5f); new_sp->pressure = interpf(sp->pressure, sp_next->pressure, 0.5f); new_sp->strength = interpf(sp->strength, sp_next->strength, 0.5f); @@ -3485,7 +3502,8 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, 0.5f); if (sp->dw && sp_next->dw) { new_sp->totweight = MIN2(sp->totweight, sp_next->totweight); - new_sp->dw = MEM_callocN(sizeof(MDeformWeight) * new_sp->totweight, __func__); + new_sp->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * new_sp->totweight, + __func__); for (uint32_t i = 0; i < new_sp->totweight; ++i) { MDeformWeight *dw = &new_sp->dw[i]; MDeformWeight *dw_from = &sp->dw[i]; @@ -3509,13 +3527,13 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, BLI_heap_free(edges, (HeapFreeFP)MEM_freeN); gps->totpoints = target_number; - gps->points = MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints); + gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints); if (has_dverts) { - gps->dvert = MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints); + gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints); } /* Convert list back to stroke point array. */ - tSamplePoint *sp = points.first; + tSamplePoint *sp = (tSamplePoint *)points.first; for (uint32_t i = 0; i < gps->totpoints && sp; ++i, sp = sp->next) { bGPDspoint *pt = &gps->points[i]; MDeformVert *dvert = &gps->dvert[i]; @@ -3528,7 +3546,7 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, if (sp->dw) { dvert->totweight = sp->totweight; - dvert->dw = MEM_callocN(sizeof(MDeformWeight) * dvert->totweight, __func__); + dvert->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dvert->totweight, __func__); for (uint32_t j = 0; j < dvert->totweight; ++j) { MDeformWeight *dw = &dvert->dw[j]; MDeformWeight *dw_from = &sp->dw[j]; @@ -3549,7 +3567,7 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, /* Free the sample points. Important to use the mutable loop here because we are erasing the list * elements. */ LISTBASE_FOREACH_MUTABLE (tSamplePoint *, temp, &points) { - if (temp->dw != NULL) { + if (temp->dw != nullptr) { MEM_freeN(temp->dw); } MEM_SAFE_FREE(temp); @@ -3601,14 +3619,14 @@ void BKE_gpencil_stroke_from_view_space(RegionView3D *rv3d, /* ----------------------------------------------------------------------------- */ /* Stroke to perimeter */ -typedef struct tPerimeterPoint { +struct tPerimeterPoint { struct tPerimeterPoint *next, *prev; float x, y, z; -} tPerimeterPoint; +}; static tPerimeterPoint *new_perimeter_point(const float pt[3]) { - tPerimeterPoint *new_pt = MEM_callocN(sizeof(tPerimeterPoint), __func__); + tPerimeterPoint *new_pt = (tPerimeterPoint *)MEM_callocN(sizeof(tPerimeterPoint), __func__); copy_v3_v3(&new_pt->x, pt); return new_pt; } @@ -3771,14 +3789,14 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd, { /* sanity check */ if (gps->totpoints < 1) { - return NULL; + return nullptr; } float defaultpixsize = 1000.0f / gpd->pixfactor; float stroke_radius = ((gps->thickness + gpl->line_change) / defaultpixsize) / 2.0f; - ListBase *perimeter_right_side = MEM_callocN(sizeof(ListBase), __func__); - ListBase *perimeter_left_side = MEM_callocN(sizeof(ListBase), __func__); + ListBase *perimeter_right_side = (ListBase *)MEM_callocN(sizeof(ListBase), __func__); + ListBase *perimeter_left_side = (ListBase *)MEM_callocN(sizeof(ListBase), __func__); int num_perimeter_points = 0; bGPDspoint *first = &gps->points[0]; @@ -4018,7 +4036,7 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d, const float diff_mat[4][4]) { if (gps->totpoints == 0) { - return NULL; + return nullptr; } bGPDstroke *gps_temp = BKE_gpencil_stroke_duplicate(gps, true, false); const bool cyclic = ((gps_temp->flag & GP_STROKE_CYCLIC) != 0); @@ -4026,8 +4044,8 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d, /* If Cyclic, add a new point. */ if (cyclic && (gps_temp->totpoints > 1)) { gps_temp->totpoints++; - gps_temp->points = MEM_recallocN(gps_temp->points, - sizeof(*gps_temp->points) * gps_temp->totpoints); + gps_temp->points = (bGPDspoint *)MEM_recallocN( + gps_temp->points, sizeof(*gps_temp->points) * gps_temp->totpoints); bGPDspoint *pt_src = &gps_temp->points[0]; bGPDspoint *pt_dst = &gps_temp->points[gps_temp->totpoints - 1]; copy_v3_v3(&pt_dst->x, &pt_src->x); @@ -4043,7 +4061,7 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d, gpd, gpl, gps_temp, subdivisions, &num_perimeter_points); if (num_perimeter_points == 0) { - return NULL; + return nullptr; } /* Create new stroke. */ diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index 0e2219e6c7f..4db527e5b42 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -273,7 +273,7 @@ int BKE_gpencil_time_modifier_cfra(Depsgraph *depsgraph, if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) { const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); - if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) { + if (GPENCIL_MODIFIER_EDIT(md, is_edit) && (!is_render)) { continue; } @@ -838,7 +838,7 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob) if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) { const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); - if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) { + if (GPENCIL_MODIFIER_EDIT(md, is_edit) && (!is_render)) { continue; } diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index af0047680f2..81c161a4a7d 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -937,7 +937,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, ListBase isect_remedgebase = {NULL, NULL}; /* now we have all the splines */ - face_coords = MEM_mallocN((sizeof(float[3])) * sf_vert_tot, "maskrast_face_coords"); + face_coords = MEM_mallocN(sizeof(float[3]) * sf_vert_tot, "maskrast_face_coords"); /* init bounds */ BLI_rctf_init_minmax(&bounds); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 4102703ca7c..b463d903303 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -312,7 +312,7 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) mesh->totselect = 0; } - if ((BLO_read_requires_endian_switch(reader)) && mesh->tface) { + if (BLO_read_requires_endian_switch(reader) && mesh->tface) { TFace *tf = mesh->tface; for (int i = 0; i < mesh->totface; i++, tf++) { BLI_endian_switch_uint32_array(tf->col, 4); diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index c2c7b317171..dbea83ae0ca 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -506,7 +506,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) if (node->storage) { /* could be handlerized at some point, now only 1 exception still */ - if ((ELEM(ntree->type, NTREE_SHADER, NTREE_GEOMETRY)) && + if (ELEM(ntree->type, NTREE_SHADER, NTREE_GEOMETRY) && ELEM(node->type, SH_NODE_CURVE_VEC, SH_NODE_CURVE_RGB)) { BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage); } @@ -3143,7 +3143,7 @@ static void free_localized_node_groups(bNodeTree *ntree) } LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if ((ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) && node->id) { + if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) { bNodeTree *ngroup = (bNodeTree *)node->id; ntreeFreeTree(ngroup); MEM_freeN(ngroup); @@ -3335,7 +3335,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) ltree->id.tag |= LIB_TAG_LOCALIZED; LISTBASE_FOREACH (bNode *, node, <ree->nodes) { - if ((ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) && node->id) { + if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) { node->id = (ID *)ntreeLocalize((bNodeTree *)node->id); } } @@ -5121,6 +5121,7 @@ static void registerGeometryNodes() register_node_type_geo_curve_subdivide(); register_node_type_geo_curve_to_mesh(); register_node_type_geo_curve_to_points(); + register_node_type_geo_curve_trim(); register_node_type_geo_delete_geometry(); register_node_type_geo_edge_split(); register_node_type_geo_input_material(); diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc index 87d8825ad90..9652622d4a1 100644 --- a/source/blender/blenkernel/intern/spline_base.cc +++ b/source/blender/blenkernel/intern/spline_base.cc @@ -410,7 +410,7 @@ Spline::LookupResult Spline::lookup_evaluated_length(const float length) const const float *offset = std::lower_bound(lengths.begin(), lengths.end(), length); const int index = offset - lengths.begin(); - const int next_index = (index == this->size() - 1) ? 0 : index + 1; + const int next_index = (index == this->evaluated_points_size() - 1) ? 0 : index + 1; const float previous_length = (index == 0) ? 0.0f : lengths[index - 1]; const float factor = (length - previous_length) / (lengths[index] - previous_length); diff --git a/source/blender/blenlib/BLI_delaunay_2d.h b/source/blender/blenlib/BLI_delaunay_2d.h index d42bd6af637..5a8ddfb5a92 100644 --- a/source/blender/blenlib/BLI_delaunay_2d.h +++ b/source/blender/blenlib/BLI_delaunay_2d.h @@ -110,6 +110,10 @@ extern "C" { * If zero is supplied for epsilon, an internal value of 1e-8 used * instead, since this code will not work correctly if it is not allowed * to merge "too near" vertices. + * + * Normally the output will contain mappings from outputs to inputs. + * If this is not needed, set need_ids to false and the execution may be much + * faster in some circumstances. */ typedef struct CDT_input { int verts_len; @@ -121,6 +125,7 @@ typedef struct CDT_input { int *faces_start_table; int *faces_len_table; float epsilon; + bool need_ids; } CDT_input; /** @@ -140,6 +145,7 @@ typedef struct CDT_input { * a run-together array and a "start" and "len" extra array, * similar triples are used to represent the output to input * mapping of vertices, edges, and faces. + * These are only set if need_ids is true in the input. * * Those triples are: * - verts_orig, verts_orig_start_table, verts_orig_len_table @@ -236,6 +242,7 @@ template<typename Arith_t> class CDT_input { Array<std::pair<int, int>> edge; Array<Vector<int>> face; Arith_t epsilon{0}; + bool need_ids{true}; }; template<typename Arith_t> class CDT_result { @@ -243,6 +250,7 @@ template<typename Arith_t> class CDT_result { Array<vec2<Arith_t>> vert; Array<std::pair<int, int>> edge; Array<Vector<int>> face; + /* The orig vectors are only popluated if the need_ids input field is true. */ /** For each output vert, which input verts correspond to it? */ Array<Vector<int>> vert_orig; /** diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc index 24a58103a10..362dbdf15c5 100644 --- a/source/blender/blenlib/intern/delaunay_2d.cc +++ b/source/blender/blenlib/intern/delaunay_2d.cc @@ -19,6 +19,7 @@ */ #include <algorithm> +#include <atomic> #include <fstream> #include <iostream> #include <sstream> @@ -29,6 +30,8 @@ #include "BLI_math_boolean.hh" #include "BLI_math_mpq.hh" #include "BLI_mpq2.hh" +#include "BLI_set.hh" +#include "BLI_task.hh" #include "BLI_vector.hh" #include "BLI_delaunay_2d.h" @@ -77,8 +80,8 @@ template<> double math_to_double<double>(const double v) * Define a templated 2D arrangement of vertices, edges, and faces. * The #SymEdge data structure is the basis for a structure that allows * easy traversal to neighboring (by topology) geometric elements. - * Each of #CDTVert, #CDTEdge, and #CDTFace have an input_id linked list, - * whose nodes contain integers that keep track of which input verts, edges, + * Each of #CDTVert, #CDTEdge, and #CDTFace have an input_id set, + * which contain integers that keep track of which input verts, edges, * and faces, respectively, that the element was derived from. * * While this could be cleaned up some, it is usable by other routines in Blender @@ -195,8 +198,8 @@ template<typename T> struct CDTVert { FatCo<T> co; /** Some edge attached to it. */ SymEdge<T> *symedge{nullptr}; - /** List of corresponding vertex input ids. */ - LinkNode *input_ids{nullptr}; + /** Set of corresponding vertex input ids. Not used if don't need_ids. */ + blender::Set<int> input_ids; /** Index into array that #CDTArrangement keeps. */ int index{-1}; /** Index of a CDTVert that this has merged to. -1 if no merge. */ @@ -209,8 +212,10 @@ template<typename T> struct CDTVert { }; template<typename Arith_t> struct CDTEdge { - /** List of input edge ids that this is part of. */ - LinkNode *input_ids{nullptr}; + /** Set of input edge ids that this is part of. + * If don't need_ids, then should contain 0 if it is a constrained edge, + * else empty. */ + blender::Set<int> input_ids; /** The directed edges for this edge. */ SymEdge<Arith_t> symedges[2]{SymEdge<Arith_t>(), SymEdge<Arith_t>()}; @@ -220,8 +225,10 @@ template<typename Arith_t> struct CDTEdge { template<typename Arith_t> struct CDTFace { /** A symedge in face; only used during output, so only valid then. */ SymEdge<Arith_t> *symedge{nullptr}; - /** List of input face ids that this is part of. */ - LinkNode *input_ids{nullptr}; + /** Set of input face ids that this is part of. + * If don't need_ids, then should contain 0 if it is part of a constrained face, + * else empty. */ + blender::Set<int> input_ids; /** Used by algorithms operating on CDT structures. */ int visit_index{0}; /** Marks this face no longer used. */ @@ -334,27 +341,30 @@ template<typename T> class CDT_state { int face_edge_offset; /** How close before coords considered equal. */ T epsilon; + /** Do we need to track ids? */ + bool need_ids; - explicit CDT_state(int num_input_verts, int num_input_edges, int num_input_faces, T epsilon); + explicit CDT_state( + int num_input_verts, int num_input_edges, int num_input_faces, T epsilon, bool need_ids); }; template<typename T> CDTArrangement<T>::~CDTArrangement() { for (int i : this->verts.index_range()) { CDTVert<T> *v = this->verts[i]; - BLI_linklist_free(v->input_ids, nullptr); + v->input_ids.clear(); delete v; this->verts[i] = nullptr; } for (int i : this->edges.index_range()) { CDTEdge<T> *e = this->edges[i]; - BLI_linklist_free(e->input_ids, nullptr); + e->input_ids.clear(); delete e; this->edges[i] = nullptr; } for (int i : this->faces.index_range()) { CDTFace<T> *f = this->faces[i]; - BLI_linklist_free(f->input_ids, nullptr); + f->input_ids.clear(); delete f; this->faces[i] = nullptr; } @@ -495,6 +505,7 @@ template<typename T> void cdt_draw(const std::string &label, const CDTArrangemen constexpr int vert_radius = 3; constexpr bool draw_vert_labels = true; constexpr bool draw_edge_labels = false; + constexpr bool draw_face_labels = false; if (cdt.verts.size() == 0) { return; @@ -559,7 +570,7 @@ template<typename T> void cdt_draw(const std::string &label, const CDTArrangemen const CDTVert<T> *v = e->symedges[1].vert; const vec2<double> &uco = u->co.approx; const vec2<double> &vco = v->co.approx; - int strokew = e->input_ids == nullptr ? thin_line : thick_line; + int strokew = e->input_ids.size() == 0 ? thin_line : thick_line; f << R"(<line fill="none" stroke="black" stroke-width=")" << strokew << "\" x1=\"" << SX(uco[0]) << "\" y1=\"" << SY(uco[1]) << "\" x2=\"" << SX(vco[0]) << "\" y2=\"" << SY(vco[1]) << "\">\n"; @@ -586,6 +597,54 @@ template<typename T> void cdt_draw(const std::string &label, const CDTArrangemen ++i; } + if (draw_face_labels) { + for (const CDTFace<T> *face : cdt.faces) { + if (!face->deleted) { + /* Since may not have prepared output yet, need a slow find of a SymEdge for this face. */ + const SymEdge<T> *se_face_start = nullptr; + for (const CDTEdge<T> *e : cdt.edges) { + if (e->symedges[0].face == face) { + se_face_start = &e->symedges[0]; + break; + } + if (e->symedges[1].face == face) { + se_face_start = &e->symedges[1]; + } + } + if (se_face_start != nullptr) { + /* Find center of face. */ + int face_nverts = 0; + vec2<double> cen(0.0, 0.0); + if (face == cdt.outer_face) { + cen.x = minx; + cen.y = miny; + } + else { + const SymEdge<T> *se = se_face_start; + do { + if (se->face == face) { + cen = cen + se->vert->co.approx; + face_nverts++; + } + } while ((se = se->next) != se_face_start); + if (face_nverts > 0) { + cen = cen / double(face_nverts); + } + } + f << "<text x=\"" << SX(cen[0]) << "\" y=\"" << SY(cen[1]) << "\"" + << " font-size=\"small\">["; + f << trunc_ptr(face); + if (face->input_ids.size() > 0) { + for (int id : face->input_ids) { + f << " " << id; + } + } + f << "]</text>\n"; + } + } + } + } + append = true; # undef SX # undef SY @@ -754,7 +813,6 @@ template<> CDTVert<double>::CDTVert(const vec2<double> &pt) this->co.exact = pt; this->co.approx = pt; this->co.abs_approx = pt; /* Not used, so doesn't matter. */ - this->input_ids = nullptr; this->symedge = nullptr; this->index = -1; this->merge_to_index = -1; @@ -767,7 +825,6 @@ template<> CDTVert<mpq_class>::CDTVert(const vec2<mpq_class> &pt) this->co.exact = pt; this->co.approx = double2(pt.x.get_d(), pt.y.get_d()); this->co.abs_approx = double2(fabs(this->co.approx.x), fabs(this->co.approx.y)); - this->input_ids = nullptr; this->symedge = nullptr; this->index = -1; this->merge_to_index = -1; @@ -824,35 +881,21 @@ template<typename T> void CDTArrangement<T>::reserve(int num_verts, int num_edge } template<typename T> -CDT_state<T>::CDT_state(int num_input_verts, int num_input_edges, int num_input_faces, T epsilon) +CDT_state<T>::CDT_state( + int num_input_verts, int num_input_edges, int num_input_faces, T epsilon, bool need_ids) { this->input_vert_tot = num_input_verts; this->cdt.reserve(num_input_verts, num_input_edges, num_input_faces); this->cdt.outer_face = this->cdt.add_face(); this->epsilon = epsilon; + this->need_ids = need_ids; this->visit_count = 0; } -static bool id_in_list(const LinkNode *id_list, int id) -{ - const LinkNode *ln; - - for (ln = id_list; ln != nullptr; ln = ln->next) { - if (POINTER_AS_INT(ln->link) == id) { - return true; - } - } - return false; -} - /* Is any id in (range_start, range_start+1, ... , range_end) in id_list? */ -static bool id_range_in_list(const LinkNode *id_list, int range_start, int range_end) +static bool id_range_in_list(const blender::Set<int> &id_list, int range_start, int range_end) { - const LinkNode *ln; - int id; - - for (ln = id_list; ln != nullptr; ln = ln->next) { - id = POINTER_AS_INT(ln->link); + for (int id : id_list) { if (id >= range_start && id <= range_end) { return true; } @@ -860,19 +903,15 @@ static bool id_range_in_list(const LinkNode *id_list, int range_start, int range return false; } -static void add_to_input_ids(LinkNode **dst, int input_id) +static void add_to_input_ids(blender::Set<int> &dst, int input_id) { - if (!id_in_list(*dst, input_id)) { - BLI_linklist_prepend(dst, POINTER_FROM_INT(input_id)); - } + dst.add(input_id); } -static void add_list_to_input_ids(LinkNode **dst, const LinkNode *src) +static void add_list_to_input_ids(blender::Set<int> &dst, const blender::Set<int> &src) { - const LinkNode *ln; - - for (ln = src; ln != nullptr; ln = ln->next) { - add_to_input_ids(dst, POINTER_AS_INT(ln->link)); + for (int value : src) { + dst.add(value); } } @@ -883,7 +922,7 @@ template<typename T> inline bool is_border_edge(const CDTEdge<T> *e, const CDT_s template<typename T> inline bool is_constrained_edge(const CDTEdge<T> *e) { - return e->input_ids != nullptr; + return e->input_ids.size() > 0; } template<typename T> inline bool is_deleted_edge(const CDTEdge<T> *e) @@ -979,7 +1018,7 @@ template<typename T> CDTEdge<T> *CDTArrangement<T>::add_diagonal(SymEdge<T> *s1, for (SymEdge<T> *se = s2; se != sdiag; se = se->next) { se->face = fnew; } - add_list_to_input_ids(&fnew->input_ids, fold->input_ids); + add_list_to_input_ids(fnew->input_ids, fold->input_ids); return ediag; } @@ -1058,7 +1097,7 @@ template<typename T> CDTEdge<T> *CDTArrangement<T>::split_edge(SymEdge<T> *se, T if (newsesym->vert->symedge == sesym) { newsesym->vert->symedge = newsesym; } - add_list_to_input_ids(&e->input_ids, se->edge->input_ids); + add_list_to_input_ids(e->input_ids, se->edge->input_ids); return e; } @@ -1880,7 +1919,7 @@ void add_edge_constraint( SymEdge<T> *t = find_symedge_between_verts(v1, v2); if (t != nullptr) { /* Segment already there. */ - add_to_input_ids(&t->edge->input_ids, input_id); + add_to_input_ids(t->edge->input_ids, input_id); if (r_edges != nullptr) { BLI_linklist_append(&edge_list, t->edge); *r_edges = edge_list.list; @@ -2041,7 +2080,7 @@ void add_edge_constraint( BLI_assert(cd_prev->lambda == 0.0); BLI_assert(cd_prev->out->next->vert == cd->vert); edge = cd_prev->out->edge; - add_to_input_ids(&edge->input_ids, input_id); + add_to_input_ids(edge->input_ids, input_id); if (r_edges != nullptr) { BLI_linklist_append(&edge_list, edge); } @@ -2054,7 +2093,7 @@ void add_edge_constraint( else { edge = cdt_state->cdt.add_diagonal(tstart, t); } - add_to_input_ids(&edge->input_ids, input_id); + add_to_input_ids(edge->input_ids, input_id); if (r_edges != nullptr) { BLI_linklist_append(&edge_list, edge); } @@ -2093,7 +2132,8 @@ template<typename T> void add_edge_constraints(CDT_state<T> *cdt_state, const CD } CDTVert<T> *v1 = cdt_state->cdt.get_vert_resolve_merge(iv1); CDTVert<T> *v2 = cdt_state->cdt.get_vert_resolve_merge(iv2); - add_edge_constraint(cdt_state, v1, v2, i, nullptr); + int id = cdt_state->need_ids ? i : 0; + add_edge_constraint(cdt_state, v1, v2, id, nullptr); } cdt_state->face_edge_offset = ne; } @@ -2132,7 +2172,7 @@ void add_face_ids( continue; } face->visit_index = visit; - add_to_input_ids(&face->input_ids, face_id); + add_to_input_ids(face->input_ids, face_id); SymEdge<T> *se_start = se; for (se = se->next; se != se_start; se = se->next) { if (!id_range_in_list(se->edge->input_ids, fedge_start, fedge_end)) { @@ -2206,7 +2246,8 @@ template<typename T> void add_face_constraints(CDT_state<T> *cdt_state, const CD CDTVert<T> *v1 = cdt->get_vert_resolve_merge(iv1); CDTVert<T> *v2 = cdt->get_vert_resolve_merge(iv2); LinkNode *edge_list; - add_edge_constraint(cdt_state, v1, v2, face_edge_id, &edge_list); + int id = cdt_state->need_ids ? face_edge_id : 0; + add_edge_constraint(cdt_state, v1, v2, id, &edge_list); /* Set a new face_symedge0 each time since earlier ones may not * survive later symedge splits. Really, just want the one when * i == flen -1, but this code guards against that one somehow @@ -2224,7 +2265,8 @@ template<typename T> void add_face_constraints(CDT_state<T> *cdt_state, const CD } int fedge_end = fedge_start + flen - 1; if (face_symedge0 != nullptr) { - add_face_ids(cdt_state, face_symedge0, f, fedge_start, fedge_end); + int id = cdt_state->need_ids ? f : 0; + add_face_ids(cdt_state, face_symedge0, id, fedge_start, fedge_end); } fstart += flen; } @@ -2349,7 +2391,7 @@ template<typename T> void remove_non_constraint_edges_leave_valid_bmesh(CDT_stat CDTFace<T> *fleft = se->face; CDTFace<T> *fright = sym(se)->face; if (fleft != cdt->outer_face && fright != cdt->outer_face && - (fleft->input_ids != nullptr || fright->input_ids != nullptr)) { + (fleft->input_ids.size() > 0 || fright->input_ids.size() > 0)) { /* Is there another #SymEdge with same left and right faces? * Or is there a vertex not part of e touching the same left and right faces? */ for (SymEdge<T> *se2 = se->next; dissolve && se2 != se; se2 = se2->next) { @@ -2507,30 +2549,33 @@ template<typename T> void detect_holes(CDT_state<T> *cdt_state) mid.exact[1] = (f->symedge->vert->co.exact[1] + f->symedge->next->vert->co.exact[1] + f->symedge->next->next->vert->co.exact[1]) / 3; - int hits = 0; + std::atomic<int> hits = 0; /* TODO: Use CDT data structure here to greatly reduce search for intersections! */ - for (const CDTEdge<T> *e : cdt->edges) { - if (!is_deleted_edge(e) && is_constrained_edge(e)) { - if (e->symedges[0].face->visit_index == e->symedges[1].face->visit_index) { - continue; /* Don't count hits on edges between faces in same region. */ - } - auto isect = vec2<T>::isect_seg_seg(ray_end.exact, - mid.exact, - e->symedges[0].vert->co.exact, - e->symedges[1].vert->co.exact); - switch (isect.kind) { - case vec2<T>::isect_result::LINE_LINE_CROSS: { - hits++; - break; + threading::parallel_for(cdt->edges.index_range(), 256, [&](IndexRange range) { + for (const int i : range) { + const CDTEdge<T> *e = cdt->edges[i]; + if (!is_deleted_edge(e) && is_constrained_edge(e)) { + if (e->symedges[0].face->visit_index == e->symedges[1].face->visit_index) { + continue; /* Don't count hits on edges between faces in same region. */ + } + auto isect = vec2<T>::isect_seg_seg(ray_end.exact, + mid.exact, + e->symedges[0].vert->co.exact, + e->symedges[1].vert->co.exact); + switch (isect.kind) { + case vec2<T>::isect_result::LINE_LINE_CROSS: { + hits++; + break; + } + case vec2<T>::isect_result::LINE_LINE_EXACT: + case vec2<T>::isect_result::LINE_LINE_NONE: + case vec2<T>::isect_result::LINE_LINE_COLINEAR: + break; } - case vec2<T>::isect_result::LINE_LINE_EXACT: - case vec2<T>::isect_result::LINE_LINE_NONE: - case vec2<T>::isect_result::LINE_LINE_COLINEAR: - break; } } - } - f->hole = (hits % 2) == 0; + }); + f->hole = (hits.load() % 2) == 0; } /* Finally, propagate hole status to all holes of a region. */ @@ -2631,25 +2676,31 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state, for (int i = 0; i < verts_size; ++i) { CDTVert<T> *v = cdt->verts[i]; if (v->merge_to_index != -1) { - if (i < cdt_state->input_vert_tot) { - add_to_input_ids(&cdt->verts[v->merge_to_index]->input_ids, i); + if (cdt_state->need_ids) { + if (i < cdt_state->input_vert_tot) { + add_to_input_ids(cdt->verts[v->merge_to_index]->input_ids, i); + } } vert_to_output_map[i] = vert_to_output_map[v->merge_to_index]; } } } result.vert = Array<vec2<T>>(nv); - result.vert_orig = Array<Vector<int>>(nv); + if (cdt_state->need_ids) { + result.vert_orig = Array<Vector<int>>(nv); + } int i_out = 0; for (int i = 0; i < verts_size; ++i) { CDTVert<T> *v = cdt->verts[i]; if (v->merge_to_index == -1) { result.vert[i_out] = v->co.exact; - if (i < cdt_state->input_vert_tot) { - result.vert_orig[i_out].append(i); - } - for (LinkNode *ln = v->input_ids; ln; ln = ln->next) { - result.vert_orig[i_out].append(POINTER_AS_INT(ln->link)); + if (cdt_state->need_ids) { + if (i < cdt_state->input_vert_tot) { + result.vert_orig[i_out].append(i); + } + for (int vert : v->input_ids) { + result.vert_orig[i_out].append(vert); + } } ++i_out; } @@ -2660,15 +2711,19 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state, return !is_deleted_edge(e); }); result.edge = Array<std::pair<int, int>>(ne); - result.edge_orig = Array<Vector<int>>(ne); + if (cdt_state->need_ids) { + result.edge_orig = Array<Vector<int>>(ne); + } int e_out = 0; for (const CDTEdge<T> *e : cdt->edges) { if (!is_deleted_edge(e)) { int vo1 = vert_to_output_map[e->symedges[0].vert->index]; int vo2 = vert_to_output_map[e->symedges[1].vert->index]; result.edge[e_out] = std::pair<int, int>(vo1, vo2); - for (LinkNode *ln = e->input_ids; ln; ln = ln->next) { - result.edge_orig[e_out].append(POINTER_AS_INT(ln->link)); + if (cdt_state->need_ids) { + for (int edge : e->input_ids) { + result.edge_orig[e_out].append(edge); + } } ++e_out; } @@ -2679,7 +2734,9 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state, return !f->deleted && f != cdt->outer_face; }); result.face = Array<Vector<int>>(nf); - result.face_orig = Array<Vector<int>>(nf); + if (cdt_state->need_ids) { + result.face_orig = Array<Vector<int>>(nf); + } int f_out = 0; for (const CDTFace<T> *f : cdt->faces) { if (!f->deleted && f != cdt->outer_face) { @@ -2690,8 +2747,10 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state, result.face[f_out].append(vert_to_output_map[se->vert->index]); se = se->next; } while (se != se_start); - for (LinkNode *ln = f->input_ids; ln; ln = ln->next) { - result.face_orig[f_out].append(POINTER_AS_INT(ln->link)); + if (cdt_state->need_ids) { + for (int face : f->input_ids) { + result.face_orig[f_out].append(face); + } } ++f_out; } @@ -2716,7 +2775,7 @@ CDT_result<T> delaunay_calc(const CDT_input<T> &input, CDT_output_type output_ty int nv = input.vert.size(); int ne = input.edge.size(); int nf = input.face.size(); - CDT_state<T> cdt_state(nv, ne, nf, input.epsilon); + CDT_state<T> cdt_state(nv, ne, nf, input.epsilon, input.need_ids); add_input_verts(&cdt_state, input); initial_triangulation(&cdt_state.cdt); add_edge_constraints(&cdt_state, input); @@ -2772,6 +2831,7 @@ extern "C" ::CDT_result *BLI_delaunay_2d_cdt_calc(const ::CDT_input *input, } } in.epsilon = static_cast<double>(input->epsilon); + in.need_ids = input->need_ids; blender::meshintersect::CDT_result<double> res = blender::meshintersect::delaunay_2d_calc( in, output_type); @@ -2784,74 +2844,99 @@ extern "C" ::CDT_result *BLI_delaunay_2d_cdt_calc(const ::CDT_input *input, int tot_e_orig = 0; int tot_f_orig = 0; int tot_f_lens = 0; - for (int v = 0; v < nv; ++v) { - tot_v_orig += res.vert_orig[v].size(); - } - for (int e = 0; e < ne; ++e) { - tot_e_orig += res.edge_orig[e].size(); - } - for (int f = 0; f < nf; ++f) { - tot_f_orig += res.face_orig[f].size(); - tot_f_lens += res.face[f].size(); + if (input->need_ids) { + for (int v = 0; v < nv; ++v) { + tot_v_orig += res.vert_orig[v].size(); + } + for (int e = 0; e < ne; ++e) { + tot_e_orig += res.edge_orig[e].size(); + } + for (int f = 0; f < nf; ++f) { + tot_f_orig += res.face_orig[f].size(); + tot_f_lens += res.face[f].size(); + } } output->vert_coords = static_cast<decltype(output->vert_coords)>( MEM_malloc_arrayN(nv, sizeof(output->vert_coords[0]), __func__)); - output->verts_orig = static_cast<int *>(MEM_malloc_arrayN(tot_v_orig, sizeof(int), __func__)); - output->verts_orig_start_table = static_cast<int *>( - MEM_malloc_arrayN(nv, sizeof(int), __func__)); - output->verts_orig_len_table = static_cast<int *>(MEM_malloc_arrayN(nv, sizeof(int), __func__)); output->edges = static_cast<decltype(output->edges)>( MEM_malloc_arrayN(ne, sizeof(output->edges[0]), __func__)); - output->edges_orig = static_cast<int *>(MEM_malloc_arrayN(tot_e_orig, sizeof(int), __func__)); - output->edges_orig_start_table = static_cast<int *>( - MEM_malloc_arrayN(ne, sizeof(int), __func__)); - output->edges_orig_len_table = static_cast<int *>(MEM_malloc_arrayN(ne, sizeof(int), __func__)); output->faces = static_cast<int *>(MEM_malloc_arrayN(tot_f_lens, sizeof(int), __func__)); output->faces_start_table = static_cast<int *>(MEM_malloc_arrayN(nf, sizeof(int), __func__)); output->faces_len_table = static_cast<int *>(MEM_malloc_arrayN(nf, sizeof(int), __func__)); - output->faces_orig = static_cast<int *>(MEM_malloc_arrayN(tot_f_orig, sizeof(int), __func__)); - output->faces_orig_start_table = static_cast<int *>( - MEM_malloc_arrayN(nf, sizeof(int), __func__)); - output->faces_orig_len_table = static_cast<int *>(MEM_malloc_arrayN(nf, sizeof(int), __func__)); + if (input->need_ids) { + output->verts_orig = static_cast<int *>(MEM_malloc_arrayN(tot_v_orig, sizeof(int), __func__)); + output->verts_orig_start_table = static_cast<int *>( + MEM_malloc_arrayN(nv, sizeof(int), __func__)); + output->verts_orig_len_table = static_cast<int *>( + MEM_malloc_arrayN(nv, sizeof(int), __func__)); + output->edges_orig = static_cast<int *>(MEM_malloc_arrayN(tot_e_orig, sizeof(int), __func__)); + output->edges_orig_start_table = static_cast<int *>( + MEM_malloc_arrayN(ne, sizeof(int), __func__)); + output->edges_orig_len_table = static_cast<int *>( + MEM_malloc_arrayN(ne, sizeof(int), __func__)); + output->faces_orig = static_cast<int *>(MEM_malloc_arrayN(tot_f_orig, sizeof(int), __func__)); + output->faces_orig_start_table = static_cast<int *>( + MEM_malloc_arrayN(nf, sizeof(int), __func__)); + output->faces_orig_len_table = static_cast<int *>( + MEM_malloc_arrayN(nf, sizeof(int), __func__)); + } + else { + output->verts_orig = NULL; + output->verts_orig_start_table = NULL; + output->verts_orig_len_table = NULL; + output->edges_orig = NULL; + output->edges_orig_start_table = NULL; + output->edges_orig_len_table = NULL; + output->faces_orig = NULL; + output->faces_orig_start_table = NULL; + output->faces_orig_len_table = NULL; + } int v_orig_index = 0; for (int v = 0; v < nv; ++v) { output->vert_coords[v][0] = static_cast<float>(res.vert[v][0]); output->vert_coords[v][1] = static_cast<float>(res.vert[v][1]); - int this_start = v_orig_index; - output->verts_orig_start_table[v] = this_start; - for (int j : res.vert_orig[v].index_range()) { - output->verts_orig[v_orig_index++] = res.vert_orig[v][j]; + if (input->need_ids) { + int this_start = v_orig_index; + output->verts_orig_start_table[v] = this_start; + for (int j : res.vert_orig[v].index_range()) { + output->verts_orig[v_orig_index++] = res.vert_orig[v][j]; + } + output->verts_orig_len_table[v] = v_orig_index - this_start; } - output->verts_orig_len_table[v] = v_orig_index - this_start; } int e_orig_index = 0; for (int e = 0; e < ne; ++e) { output->edges[e][0] = res.edge[e].first; output->edges[e][1] = res.edge[e].second; - int this_start = e_orig_index; - output->edges_orig_start_table[e] = this_start; - for (int j : res.edge_orig[e].index_range()) { - output->edges_orig[e_orig_index++] = res.edge_orig[e][j]; + if (input->need_ids) { + int this_start = e_orig_index; + output->edges_orig_start_table[e] = this_start; + for (int j : res.edge_orig[e].index_range()) { + output->edges_orig[e_orig_index++] = res.edge_orig[e][j]; + } + output->edges_orig_len_table[e] = e_orig_index - this_start; } - output->edges_orig_len_table[e] = e_orig_index - this_start; } int f_orig_index = 0; int f_index = 0; for (int f = 0; f < nf; ++f) { + output->faces_start_table[f] = f_index; int flen = res.face[f].size(); output->faces_len_table[f] = flen; for (int j = 0; j < flen; ++j) { output->faces[f_index++] = res.face[f][j]; } - int this_start = f_orig_index; - output->faces_orig_start_table[f] = this_start; - for (int k : res.face_orig[f].index_range()) { - output->faces_orig[f_orig_index++] = res.face_orig[f][k]; + if (input->need_ids) { + int this_start = f_orig_index; + output->faces_orig_start_table[f] = this_start; + for (int k : res.face_orig[f].index_range()) { + output->faces_orig[f_orig_index++] = res.face_orig[f][k]; + } + output->faces_orig_len_table[f] = f_orig_index - this_start; } - output->faces_orig_len_table[f] = f_orig_index - this_start; } return output; } @@ -2863,14 +2948,16 @@ extern "C" void BLI_delaunay_2d_cdt_free(::CDT_result *result) MEM_freeN(result->faces); MEM_freeN(result->faces_start_table); MEM_freeN(result->faces_len_table); - MEM_freeN(result->verts_orig); - MEM_freeN(result->verts_orig_start_table); - MEM_freeN(result->verts_orig_len_table); - MEM_freeN(result->edges_orig); - MEM_freeN(result->edges_orig_start_table); - MEM_freeN(result->edges_orig_len_table); - MEM_freeN(result->faces_orig); - MEM_freeN(result->faces_orig_start_table); - MEM_freeN(result->faces_orig_len_table); + if (result->verts_orig) { + MEM_freeN(result->verts_orig); + MEM_freeN(result->verts_orig_start_table); + MEM_freeN(result->verts_orig_len_table); + MEM_freeN(result->edges_orig); + MEM_freeN(result->edges_orig_start_table); + MEM_freeN(result->edges_orig_len_table); + MEM_freeN(result->faces_orig); + MEM_freeN(result->faces_orig_start_table); + MEM_freeN(result->faces_orig_len_table); + } MEM_freeN(result); } diff --git a/source/blender/blenlib/intern/mesh_intersect.cc b/source/blender/blenlib/intern/mesh_intersect.cc index f91dd762e70..400b3f94a3f 100644 --- a/source/blender/blenlib/intern/mesh_intersect.cc +++ b/source/blender/blenlib/intern/mesh_intersect.cc @@ -1875,6 +1875,16 @@ static void do_cdt(CDT_data &cd) } } +/* Find an original edge index that goes with the edge that the CDT output edge + * that goes between verts i0 and i1 (in the CDT output vert indexing scheme). + * There may be more than one: if so, prefer one that was originally a face edge. + * The input to CDT for a triangle with some intersecting segments from other triangles + * will have both edges and a face constraint for the main triangle (this is redundant + * but allows us to discover which face edge goes with which output edges). + * If there is any face edge, return one of those as the original. + * If there is no face edge but there is another edge in the input problem, then that + * edge must have come from intersection with another triangle, so set *r_is_intersect + * to true in that case. */ static int get_cdt_edge_orig( int i0, int i1, const CDT_data &cd, const IMesh &in_tm, bool *r_is_intersect) { @@ -1900,35 +1910,50 @@ static int get_cdt_edge_orig( } /* Pick an arbitrary orig, but not one equal to NO_INDEX, if we can help it. */ - /* TODO: if edge has origs from more than on part of the nary input, + /* TODO: if edge has origs from more than one part of the nary input, * then want to set *r_is_intersect to true. */ + int face_eorig = NO_INDEX; + bool have_non_face_eorig = false; for (int orig_index : cd.cdt_out.edge_orig[e]) { /* orig_index encodes the triangle and pos within the triangle of the input edge. */ if (orig_index >= foff) { - int in_face_index = (orig_index / foff) - 1; - int pos = orig_index % foff; - /* We need to retrieve the edge orig field from the Face used to populate the - * in_face_index'th face of the CDT, at the pos'th position of the face. */ - int in_tm_face_index = cd.input_face[in_face_index]; - BLI_assert(in_tm_face_index < in_tm.face_size()); - const Face *facep = in_tm.face(in_tm_face_index); - BLI_assert(pos < facep->size()); - bool is_rev = cd.is_reversed[in_face_index]; - int eorig = is_rev ? facep->edge_orig[2 - pos] : facep->edge_orig[pos]; - if (eorig != NO_INDEX) { - return eorig; + if (face_eorig == NO_INDEX) { + int in_face_index = (orig_index / foff) - 1; + int pos = orig_index % foff; + /* We need to retrieve the edge orig field from the Face used to populate the + * in_face_index'th face of the CDT, at the pos'th position of the face. */ + int in_tm_face_index = cd.input_face[in_face_index]; + BLI_assert(in_tm_face_index < in_tm.face_size()); + const Face *facep = in_tm.face(in_tm_face_index); + BLI_assert(pos < facep->size()); + bool is_rev = cd.is_reversed[in_face_index]; + int eorig = is_rev ? facep->edge_orig[2 - pos] : facep->edge_orig[pos]; + if (eorig != NO_INDEX) { + face_eorig = eorig; + } } } else { - /* This edge came from an edge input to the CDT problem, - * so it is an intersect edge. */ - *r_is_intersect = true; - /* TODO: maybe there is an orig index: - * This happens if an input edge was formed by an input face having - * an edge that is co-planar with the cluster, while the face as a whole is not. */ - return NO_INDEX; + if (!have_non_face_eorig) { + have_non_face_eorig = true; + } + if (face_eorig != NO_INDEX && have_non_face_eorig) { + /* Only need at most one orig for each type. */ + break; + } } } + if (face_eorig != NO_INDEX) { + return face_eorig; + } + else if (have_non_face_eorig) { + /* This must have been an input to the CDT problem that was an intersection edge. */ + /* TODO: maybe there is an orig index: + * This happens if an input edge was formed by an input face having + * an edge that is co-planar with the cluster, while the face as a whole is not. */ + *r_is_intersect = true; + return NO_INDEX; + } return NO_INDEX; } diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index 87330cf4899..66d0b44cfb3 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -184,7 +184,7 @@ size_t BLI_system_memory_max_in_megabytes(void) /* Maximum addressable bytes on this platform. * * NOTE: Due to the shift arithmetic this is a half of the memory. */ - const size_t limit_bytes_half = (((size_t)1) << ((sizeof(size_t[8])) - 1)); + const size_t limit_bytes_half = (((size_t)1) << (sizeof(size_t[8]) - 1)); /* Convert it to megabytes and return. */ return (limit_bytes_half >> 20) * 2; } diff --git a/source/blender/blenlib/intern/task_iterator.c b/source/blender/blenlib/intern/task_iterator.c index 33af4894b48..06087869685 100644 --- a/source/blender/blenlib/intern/task_iterator.c +++ b/source/blender/blenlib/intern/task_iterator.c @@ -409,11 +409,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, TaskParallelMempoolFunc func, const TaskParallelSettings *settings) { - TaskPool *task_pool; - ParallelMempoolState state; - int i, num_threads, num_tasks; - - if (BLI_mempool_len(mempool) == 0) { + if (UNLIKELY(BLI_mempool_len(mempool) == 0)) { return; } @@ -429,7 +425,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, userdata_chunk_local = MALLOCA(userdata_chunk_size); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); if (settings->func_init != NULL) { - settings->func_init(state.userdata, userdata_chunk_local); + settings->func_init(userdata, userdata_chunk_local); } tls.userdata_chunk = userdata_chunk_local; } @@ -451,14 +447,15 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, return; } - task_pool = BLI_task_pool_create(&state, TASK_PRIORITY_HIGH); - num_threads = BLI_task_scheduler_num_threads(); + ParallelMempoolState state; + TaskPool *task_pool = BLI_task_pool_create(&state, TASK_PRIORITY_HIGH); + const int num_threads = BLI_task_scheduler_num_threads(); /* The idea here is to prevent creating task for each of the loop iterations * and instead have tasks which are evenly distributed across CPU cores and * pull next item to be crunched using the threaded-aware BLI_mempool_iter. */ - num_tasks = num_threads + 2; + const int num_tasks = num_threads + 2; state.userdata = userdata; state.func = func; @@ -470,7 +467,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, ParallelMempoolTaskData *mempool_iterator_data = mempool_iter_threadsafe_create( mempool, (size_t)num_tasks); - for (i = 0; i < num_tasks; i++) { + for (int i = 0; i < num_tasks; i++) { if (use_userdata_chunk) { userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); @@ -489,7 +486,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, if (use_userdata_chunk) { if ((settings->func_free != NULL) || (settings->func_reduce != NULL)) { - for (i = 0; i < num_tasks; i++) { + for (int i = 0; i < num_tasks; i++) { if (settings->func_reduce) { settings->func_reduce( userdata, userdata_chunk, mempool_iterator_data[i].tls.userdata_chunk); diff --git a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc index 08a3818e18f..bc6b7e9fe4e 100644 --- a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc +++ b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc @@ -241,7 +241,7 @@ template<typename T> std::ostream &operator<<(std::ostream &os, const CDT_result for (int i : r.edge.index_range()) { os << "e" << i << " = (" << r.edge[i].first << ", " << r.edge[i].second << ")\n"; os << " orig: "; - for (int j : r.edge_orig[i].size()) { + for (int j : r.edge_orig[i].index_range()) { os << r.edge_orig[i][j] << " "; } os << "\n"; @@ -797,6 +797,55 @@ template<typename T> void crosssegs_test() } } +template<typename T> void cutacrosstri_test() +{ + /* Right triangle with horizontal segment exactly crossing in the middle. */ + const char *spec = R"(5 1 1 + 0.0 0.0 + 1.0 0.0 + 0.0 1.0 + 0.0 0.5 + 0.5 0.5 + 3 4 + 0 1 2 + )"; + + CDT_input<T> in = fill_input_from_string<T>(spec); + CDT_result<T> out = delaunay_2d_calc(in, CDT_FULL); + EXPECT_EQ(out.vert.size(), 5); + EXPECT_EQ(out.edge.size(), 7); + EXPECT_EQ(out.face.size(), 3); + int v0_out = get_orig_index(out.vert_orig, 0); + int v1_out = get_orig_index(out.vert_orig, 1); + int v2_out = get_orig_index(out.vert_orig, 2); + int v3_out = get_orig_index(out.vert_orig, 3); + int v4_out = get_orig_index(out.vert_orig, 4); + EXPECT_TRUE(v0_out != -1 && v1_out != -1 && v2_out != -1 && v3_out != -1 && v4_out != -1); + if (out.face.size() == 3) { + int e0_out = get_orig_index(out.edge_orig, 0); + EXPECT_NE(e0_out, -1); + int fe0_out = get_output_edge_index(out, v0_out, v1_out); + EXPECT_NE(fe0_out, -1); + int fe1a_out = get_output_edge_index(out, v1_out, v4_out); + EXPECT_NE(fe1a_out, -1); + int fe1b_out = get_output_edge_index(out, v4_out, v2_out); + EXPECT_NE(fe1b_out, -1); + if (fe1a_out != 0 && fe1b_out != 0) { + EXPECT_EQ(e0_out, get_orig_index(out.edge_orig, 0)); + EXPECT_TRUE(out.edge_orig[fe1a_out].size() == 1 && out.edge_orig[fe1a_out][0] == 11); + EXPECT_TRUE(out.edge_orig[fe1b_out].size() == 1 && out.edge_orig[fe1b_out][0] == 11); + } + int e_diag = get_output_edge_index(out, v0_out, v4_out); + EXPECT_NE(e_diag, -1); + if (e_diag != -1) { + EXPECT_EQ(out.edge_orig[e_diag].size(), 0); + } + } + if (DO_DRAW) { + graph_draw<T>("CutAcrossTri", out.vert, out.edge, out.face); + } +} + template<typename T> void diamondcross_test() { /* Diamond with constraint edge from top to bottom. Some dup verts. */ @@ -1470,6 +1519,11 @@ TEST(delaunay_d, CrossSegs) crosssegs_test<double>(); } +TEST(delaunay_d, CutAcrossTri) +{ + cutacrosstri_test<double>(); +} + TEST(delaunay_d, DiamondCross) { diamondcross_test<double>(); @@ -1610,6 +1664,11 @@ TEST(delaunay_m, CrossSegs) crosssegs_test<mpq_class>(); } +TEST(delaunay_m, CutAcrossTri) +{ + cutacrosstri_test<mpq_class>(); +} + TEST(delaunay_m, DiamondCross) { diamondcross_test<mpq_class>(); @@ -1704,7 +1763,8 @@ TEST(delaunay_d, CintTwoFace) #if DO_TEXT_TESTS template<typename T> -void text_test(int num_arc_points, int num_lets_per_line, int num_lines, CDT_output_type otype) +void text_test( + int num_arc_points, int num_lets_per_line, int num_lines, CDT_output_type otype, bool need_ids) { constexpr bool print_timing = true; /* @@ -1843,12 +1903,18 @@ void text_test(int num_arc_points, int num_lets_per_line, int num_lines, CDT_out } } in.epsilon = b_before_arcs_in.epsilon; + in.need_ids = need_ids; double tstart = PIL_check_seconds_timer(); CDT_result<T> out = delaunay_2d_calc(in, otype); double tend = PIL_check_seconds_timer(); if (print_timing) { std::cout << "time = " << tend - tstart << "\n"; } + if (!need_ids) { + EXPECT_EQ(out.vert_orig.size(), 0); + EXPECT_EQ(out.edge_orig.size(), 0); + EXPECT_EQ(out.face_orig.size(), 0); + } if (DO_DRAW) { std::string label = "Text arcpts=" + std::to_string(num_arc_points); if (num_lets_per_line > 1) { @@ -1863,19 +1929,46 @@ void text_test(int num_arc_points, int num_lets_per_line, int num_lines, CDT_out TEST(delaunay_d, TextB10) { - text_test<double>(10, 1, 1, CDT_INSIDE_WITH_HOLES); + text_test<double>(10, 1, 1, CDT_INSIDE_WITH_HOLES, true); } TEST(delaunay_d, TextB200) { - text_test<double>(200, 1, 1, CDT_INSIDE_WITH_HOLES); + text_test<double>(200, 1, 1, CDT_INSIDE_WITH_HOLES, true); } TEST(delaunay_d, TextB10_10_10) { - text_test<double>(10, 10, 10, CDT_INSIDE_WITH_HOLES); + text_test<double>(10, 10, 10, CDT_INSIDE_WITH_HOLES, true); +} + +TEST(delaunay_d, TextB10_10_10_noids) +{ + text_test<double>(10, 10, 10, CDT_INSIDE_WITH_HOLES, false); } +# ifdef WITH_GMP +TEST(delaunay_m, TextB10) +{ + text_test<mpq_class>(10, 1, 1, CDT_INSIDE_WITH_HOLES, true); +} + +TEST(delaunay_m, TextB200) +{ + text_test<mpq_class>(200, 1, 1, CDT_INSIDE_WITH_HOLES, true); +} + +TEST(delaunay_m, TextB10_10_10) +{ + text_test<mpq_class>(10, 10, 10, CDT_INSIDE_WITH_HOLES, true); +} + +TEST(delaunay_m, TextB10_10_10_noids) +{ + text_test<mpq_class>(10, 10, 10, CDT_INSIDE_WITH_HOLES, false); +} +# endif + #endif #if DO_RANDOM_TESTS diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index d36c622c572..07a324181af 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -99,9 +99,15 @@ static void move_vertex_group_names_to_object_data(Main *bmain) if (ELEM(object->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) { ListBase *new_defbase = BKE_object_defgroup_list_mutable(object); - /* Clear the list in case the it was already assigned from another object. */ - BLI_freelistN(new_defbase); - *new_defbase = object->defbase; + /* Choose the longest vertex group name list among all linked duplicates. */ + if (BLI_listbase_count(&object->defbase) < BLI_listbase_count(new_defbase)) { + BLI_freelistN(&object->defbase); + } + else { + /* Clear the list in case the it was already assigned from another object. */ + BLI_freelistN(new_defbase); + *new_defbase = object->defbase; + } } } } @@ -551,5 +557,24 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) */ { /* Keep this block, even when empty. */ + + /* Convert Surface Deform to sparse-capable bind structure. */ + if (!DNA_struct_elem_find( + fd->filesdna, "SurfaceDeformModifierData", "int", "num_mesh_verts")) { + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { + if (md->type == eModifierType_SurfaceDeform) { + SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; + if (smd->num_bind_verts && smd->verts) { + smd->num_mesh_verts = smd->num_bind_verts; + + for (unsigned int i = 0; i < smd->num_bind_verts; i++) { + smd->verts[i].vertex_idx = i; + } + } + } + } + } + } } } diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index ee51a03d9fb..6f7b2cbc79f 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -800,7 +800,7 @@ short BM_edge_flag_to_mflag(BMEdge *e) ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) | ((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) | - ((BM_edge_is_wire(e)) ? ME_LOOSEEDGE : 0) | /* not typical */ + (BM_edge_is_wire(e) ? ME_LOOSEEDGE : 0) | /* not typical */ ME_EDGERENDER); } char BM_face_flag_to_mflag(BMFace *f) diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 456275cf157..bd0504b038a 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -24,8 +24,8 @@ struct BMAllocTemplate; struct BMLoopNorEditDataArray; -struct MLoopNorSpaceArray; struct BMPartialUpdate; +struct MLoopNorSpaceArray; void BM_mesh_elem_toolflags_ensure(BMesh *bm); void BM_mesh_elem_toolflags_clear(BMesh *bm); diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index 2c32cd39002..5be7f4a5f3b 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -20,8 +20,8 @@ * \ingroup bmesh */ -struct Heap; struct BMPartialUpdate; +struct Heap; #include "BLI_compiler_attrs.h" diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c index 99e50b35d97..86a7d8153f0 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c @@ -337,7 +337,7 @@ static bool bm_face_split_edgenet_find_loop_walk(BMVert *v_init, /* in rare cases there may be edges with a single connecting vertex */ if (e_next != e_first) { do { - if ((BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) && + if (BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET) && (bm_edge_flagged_radial_count(e_next) < 2)) { BMVert *v_next; diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index 40f09d7e719..e66afcd88d9 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -842,7 +842,7 @@ static void *bmw_IslandManifoldWalker_step(BMWalker *walker) /* utility function to see if an edge is a part of an ngon boundary */ static bool bm_edge_is_single(BMEdge *e) { - return ((BM_edge_is_boundary(e)) && (e->l->f->len > 4) && + return (BM_edge_is_boundary(e) && (e->l->f->len > 4) && (BM_edge_is_boundary(e->l->next->e) || BM_edge_is_boundary(e->l->prev->e))); } diff --git a/source/blender/bmesh/operators/bmo_connect_concave.c b/source/blender/bmesh/operators/bmo_connect_concave.c index bc1111676a3..15ed930afd8 100644 --- a/source/blender/bmesh/operators/bmo_connect_concave.c +++ b/source/blender/bmesh/operators/bmo_connect_concave.c @@ -51,10 +51,10 @@ static int bm_edge_length_cmp(const void *a_, const void *b_) const BMEdge *e_a = *(const void **)a_; const BMEdge *e_b = *(const void **)b_; - int e_a_concave = ((BM_elem_flag_test(e_a->v1, BM_ELEM_TAG)) && - (BM_elem_flag_test(e_a->v2, BM_ELEM_TAG))); - int e_b_concave = ((BM_elem_flag_test(e_b->v1, BM_ELEM_TAG)) && - (BM_elem_flag_test(e_b->v2, BM_ELEM_TAG))); + int e_a_concave = (BM_elem_flag_test(e_a->v1, BM_ELEM_TAG) && + BM_elem_flag_test(e_a->v2, BM_ELEM_TAG)); + int e_b_concave = (BM_elem_flag_test(e_b->v1, BM_ELEM_TAG) && + BM_elem_flag_test(e_b->v2, BM_ELEM_TAG)); /* merge edges between concave edges last since these * are most likely to remain and be the main dividers */ diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c index 8e4b0732feb..7f70c452af3 100644 --- a/source/blender/bmesh/operators/bmo_edgenet.c +++ b/source/blender/bmesh/operators/bmo_edgenet.c @@ -93,7 +93,7 @@ static BMEdge *edge_next(BMesh *bm, BMEdge *e) for (i = 0; i < 2; i++) { BM_ITER_ELEM (e2, &iter, i ? e->v2 : e->v1, BM_EDGES_OF_VERT) { - if ((BMO_edge_flag_test(bm, e2, EDGE_MARK)) && + if (BMO_edge_flag_test(bm, e2, EDGE_MARK) && (BMO_edge_flag_test(bm, e2, EDGE_VIS) == false) && (e2 != e)) { return e2; } diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c index 2e09b21c9cc..6734cc60cad 100644 --- a/source/blender/bmesh/operators/bmo_fill_grid.c +++ b/source/blender/bmesh/operators/bmo_fill_grid.c @@ -645,20 +645,20 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op) bm_edgeloop_flag_set(estore_a, BM_ELEM_HIDDEN, true); bm_edgeloop_flag_set(estore_b, BM_ELEM_HIDDEN, true); - if ((BM_mesh_edgeloops_find_path( - bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_first)) && - (BM_mesh_edgeloops_find_path( - bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_last))) { + if (BM_mesh_edgeloops_find_path( + bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_first) && + BM_mesh_edgeloops_find_path( + bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_last)) { estore_rail_a = eloops_rail.first; estore_rail_b = eloops_rail.last; } else { BM_mesh_edgeloops_free(&eloops_rail); - if ((BM_mesh_edgeloops_find_path( - bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_last)) && - (BM_mesh_edgeloops_find_path( - bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_first))) { + if (BM_mesh_edgeloops_find_path( + bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_last) && + BM_mesh_edgeloops_find_path( + bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_first)) { estore_rail_a = eloops_rail.first; estore_rail_b = eloops_rail.last; BM_edgeloop_flip(bm, estore_b); diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c index d015b715a69..6a80f360f59 100644 --- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c +++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c @@ -860,12 +860,12 @@ static bool bm_edgering_pair_order_is_flipped(BMesh *UNUSED(bm), /* step around any fan-faces on both sides */ do { v_iter_a_step = v_iter_a_step->next; - } while (v_iter_a_step && ((BM_edge_exists(v_iter_a_step->data, v_iter_b_first->data)) || - (BM_edge_exists(v_iter_a_step->data, v_iter_b_first->next->data)))); + } while (v_iter_a_step && (BM_edge_exists(v_iter_a_step->data, v_iter_b_first->data) || + BM_edge_exists(v_iter_a_step->data, v_iter_b_first->next->data))); do { v_iter_b_step = v_iter_b_step->next; - } while (v_iter_b_step && ((BM_edge_exists(v_iter_b_step->data, v_iter_a_first->data)) || - (BM_edge_exists(v_iter_b_step->data, v_iter_a_first->next->data)))); + } while (v_iter_b_step && (BM_edge_exists(v_iter_b_step->data, v_iter_a_first->data) || + BM_edge_exists(v_iter_b_step->data, v_iter_a_first->next->data))); v_iter_a_step = v_iter_a_step ? v_iter_a_step->prev : lb_a->last; v_iter_b_step = v_iter_b_step ? v_iter_b_step->prev : lb_b->last; diff --git a/source/blender/compositor/nodes/COM_IDMaskNode.cc b/source/blender/compositor/nodes/COM_IDMaskNode.cc index 9798dabd035..b51e79f2dea 100644 --- a/source/blender/compositor/nodes/COM_IDMaskNode.cc +++ b/source/blender/compositor/nodes/COM_IDMaskNode.cc @@ -17,9 +17,9 @@ */ #include "COM_IDMaskNode.h" -#include "COM_AntiAliasOperation.h" #include "COM_ExecutionSystem.h" #include "COM_IDMaskOperation.h" +#include "COM_SMAAOperation.h" namespace blender::compositor { @@ -42,11 +42,27 @@ void IDMaskNode::convertToOperations(NodeConverter &converter, converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0)); } else { - AntiAliasOperation *antiAliasOperation = new AntiAliasOperation(); - converter.addOperation(antiAliasOperation); + SMAAEdgeDetectionOperation *operation1 = nullptr; - converter.addLink(operation->getOutputSocket(), antiAliasOperation->getInputSocket(0)); - converter.mapOutputSocket(getOutputSocket(0), antiAliasOperation->getOutputSocket(0)); + operation1 = new SMAAEdgeDetectionOperation(); + converter.addOperation(operation1); + + converter.addLink(operation->getOutputSocket(0), operation1->getInputSocket(0)); + + /* Blending Weight Calculation Pixel Shader (Second Pass). */ + SMAABlendingWeightCalculationOperation *operation2 = + new SMAABlendingWeightCalculationOperation(); + converter.addOperation(operation2); + + converter.addLink(operation1->getOutputSocket(), operation2->getInputSocket(0)); + + /* Neighborhood Blending Pixel Shader (Third Pass). */ + SMAANeighborhoodBlendingOperation *operation3 = new SMAANeighborhoodBlendingOperation(); + converter.addOperation(operation3); + + converter.addLink(operation->getOutputSocket(0), operation3->getInputSocket(0)); + converter.addLink(operation2->getOutputSocket(), operation3->getInputSocket(1)); + converter.mapOutputSocket(getOutputSocket(0), operation3->getOutputSocket()); } } diff --git a/source/blender/compositor/operations/COM_SMAAOperation.cc b/source/blender/compositor/operations/COM_SMAAOperation.cc index c3647a39909..3c753591ced 100644 --- a/source/blender/compositor/operations/COM_SMAAOperation.cc +++ b/source/blender/compositor/operations/COM_SMAAOperation.cc @@ -21,6 +21,7 @@ #include "COM_SMAAOperation.h" #include "BLI_math.h" #include "COM_SMAAAreaTexture.h" +#include "BKE_node.h" extern "C" { #include "IMB_colormanagement.h" @@ -166,8 +167,8 @@ SMAAEdgeDetectionOperation::SMAAEdgeDetectionOperation() this->flags.complex = true; this->m_imageReader = nullptr; this->m_valueReader = nullptr; - this->m_threshold = 0.1f; - this->m_contrast_limit = 2.0f; + this->setThreshold(CMP_DEFAULT_SMAA_THRESHOLD); + this->setLocalContrastAdaptationFactor(CMP_DEFAULT_SMAA_CONTRAST_LIMIT); } void SMAAEdgeDetectionOperation::initExecution() @@ -297,7 +298,7 @@ SMAABlendingWeightCalculationOperation::SMAABlendingWeightCalculationOperation() this->addOutputSocket(DataType::Color); this->flags.complex = true; this->m_imageReader = nullptr; - this->m_corner_rounding = 25; + this->setCornerRounding(CMP_DEFAULT_SMAA_CORNER_ROUNDING); } void *SMAABlendingWeightCalculationOperation::initializeTileData(rcti *rect) diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index 42c9cccceed..c029d203574 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -33,6 +33,7 @@ struct Depsgraph; /* ------------------------------------------------ */ struct CacheFile; +struct Collection; struct CustomData_MeshMasks; struct ID; struct Main; @@ -40,7 +41,6 @@ struct Object; struct Scene; struct Simulation; struct bNodeTree; -struct Collection; #include "BLI_sys_types.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 415145c8fa1..c63b3d825a0 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -1098,9 +1098,15 @@ void DepsgraphRelationBuilder::build_object_pointcache(Object *object) } else { flag = FLAG_GEOMETRY; - OperationKey geometry_key( - &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); - add_relation(point_cache_key, geometry_key, "Point Cache -> Geometry"); + OperationKey geometry_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + add_relation(point_cache_key, geometry_key, "Point Cache -> Geometry Eval"); + if (object->data) { + /* Geometry may change, so rebuild the Drawing Cache. */ + OperationKey object_data_batch_all_key( + (ID *)object->data, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_ALL); + add_relation( + point_cache_key, object_data_batch_all_key, "Point Cache -> Batch Update All"); + } } BLI_assert(flag != -1); /* Tag that we did handle that component. */ diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 34b33e9a6c0..063126ff864 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -168,7 +168,6 @@ void depsgraph_tag_to_component_opcode(const ID *id, break; case ID_RECALC_GEOMETRY: depsgraph_geometry_tag_to_component(id, component_type); - *operation_code = OperationCode::GEOMETRY_EVAL_INIT; break; case ID_RECALC_GEOMETRY_DEFORM: depsgraph_geometry_tag_to_component(id, component_type); diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index ff3af9b28d1..f5b95ac97ff 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -91,7 +91,7 @@ typedef struct BoundSphere { typedef char DRWViewportEmptyList; #define DRW_VIEWPORT_LIST_SIZE(list) \ - (sizeof(list) == sizeof(DRWViewportEmptyList) ? 0 : ((sizeof(list)) / sizeof(void *))) + (sizeof(list) == sizeof(DRWViewportEmptyList) ? 0 : (sizeof(list) / sizeof(void *))) /* Unused members must be either pass list or 'char *' when not used. */ #define DRW_VIEWPORT_DATA_SIZE(ty) \ diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 344150014ed..6d71b01b7e0 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -76,27 +76,23 @@ struct ExtractorRunData { class ExtractorRunDatas : public Vector<ExtractorRunData> { public: - void filter_into(ExtractorRunDatas &result, eMRIterType iter_type) const + void filter_into(ExtractorRunDatas &result, eMRIterType iter_type, const bool is_mesh) const { for (const ExtractorRunData &data : *this) { const MeshExtract *extractor = data.extractor; - if ((iter_type & MR_ITER_LOOPTRI) && extractor->iter_looptri_bm) { - BLI_assert(extractor->iter_looptri_mesh); + if ((iter_type & MR_ITER_LOOPTRI) && *(&extractor->iter_looptri_bm + is_mesh)) { result.append(data); continue; } - if ((iter_type & MR_ITER_POLY) && extractor->iter_poly_bm) { - BLI_assert(extractor->iter_poly_mesh); + if ((iter_type & MR_ITER_POLY) && *(&extractor->iter_poly_bm + is_mesh)) { result.append(data); continue; } - if ((iter_type & MR_ITER_LEDGE) && extractor->iter_ledge_bm) { - BLI_assert(extractor->iter_ledge_mesh); + if ((iter_type & MR_ITER_LEDGE) && *(&extractor->iter_ledge_bm + is_mesh)) { result.append(data); continue; } - if ((iter_type & MR_ITER_LVERT) && extractor->iter_lvert_bm) { - BLI_assert(extractor->iter_lvert_mesh); + if ((iter_type & MR_ITER_LVERT) && *(&extractor->iter_lvert_bm + is_mesh)) { result.append(data); continue; } @@ -427,7 +423,7 @@ BLI_INLINE void extract_task_range_run_iter(const MeshRenderData *mr, return; } - extractors->filter_into(range_data.extractors, iter_type); + extractors->filter_into(range_data.extractors, iter_type, is_mesh); BLI_task_parallel_range(0, stop, &range_data, func, settings); } diff --git a/source/blender/editors/asset/asset_edit.cc b/source/blender/editors/asset/asset_edit.cc index 0937af0dbf1..f4860737193 100644 --- a/source/blender/editors/asset/asset_edit.cc +++ b/source/blender/editors/asset/asset_edit.cc @@ -82,13 +82,13 @@ bool ED_asset_can_make_single_from_context(const bContext *C) } /* TODO better place? */ -/* TODO What about the setter and the itemf? */ +/* TODO What about the setter and the `itemf` callback? */ #include "BKE_preferences.h" #include "DNA_asset_types.h" #include "DNA_userdef_types.h" int ED_asset_library_reference_to_enum_value(const AssetLibraryReference *library) { - /* Simple case: Predefined repo, just set the value. */ + /* Simple case: Predefined repository, just set the value. */ if (library->type < ASSET_LIBRARY_CUSTOM) { return library->type; } @@ -109,7 +109,7 @@ AssetLibraryReference ED_asset_library_reference_from_enum_value(int value) { AssetLibraryReference library; - /* Simple case: Predefined repo, just set the value. */ + /* Simple case: Predefined repository, just set the value. */ if (value < ASSET_LIBRARY_CUSTOM) { library.type = value; library.custom_library_index = -1; diff --git a/source/blender/editors/asset/asset_list.cc b/source/blender/editors/asset/asset_list.cc index 1ea948d97d4..dd1c5f360a0 100644 --- a/source/blender/editors/asset/asset_list.cc +++ b/source/blender/editors/asset/asset_list.cc @@ -60,7 +60,7 @@ class AssetLibraryReferenceWrapper { const AssetLibraryReference reference_; public: - /* Intentionally not `explicit`, allow implicit conversion for convienience. Might have to be + /* Intentionally not `explicit`, allow implicit conversion for convenience. Might have to be * NOLINT */ AssetLibraryReferenceWrapper(const AssetLibraryReference &reference); ~AssetLibraryReferenceWrapper() = default; @@ -301,7 +301,7 @@ void AssetList::clear(bContext *C) filelist_freelib(files); filelist_clear(files); - WM_main_add_notifier(NC_ASSET | ND_ASSET_LIST, NULL); + WM_main_add_notifier(NC_ASSET | ND_ASSET_LIST, nullptr); } /** @@ -348,7 +348,7 @@ void AssetList::tagMainDataDirty() const void AssetList::remapID(ID * /*id_old*/, ID * /*id_new*/) const { - /* Trigger full refetch of the file list if main data was changed, don't even attempt remap + /* Trigger full re-fetch of the file list if main data was changed, don't even attempt remap * pointers. We could give file list types a id-remap callback, but it's probably not worth it. * Refreshing local file lists is relatively cheap. */ tagMainDataDirty(); @@ -605,7 +605,7 @@ int ED_assetlist_size(const AssetLibraryReference *library_reference) } /** - * Tag all asset lists in the storage that show main data as needing an update (refetch). + * Tag all asset lists in the storage that show main data as needing an update (re-fetch). * * This only tags the data. If the asset list is visible on screen, the space is still responsible * for ensuring the necessary redraw. It can use #ED_assetlist_listen() to check if the asset-list diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 0062e363cdf..8640ffa67cf 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -278,7 +278,7 @@ static void gpencil_stroke_pair_table(bContext *C, tGPDinterpolate_layer *tgpil) { bGPdata *gpd = tgpi->gpd; - const bool only_selected = ((GPENCIL_EDIT_MODE(gpd)) && + const bool only_selected = (GPENCIL_EDIT_MODE(gpd) && ((tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) != 0)); const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); @@ -291,8 +291,7 @@ static void gpencil_stroke_pair_table(bContext *C, LISTBASE_FOREACH (bGPDstroke *, gps_from, &tgpil->prevFrame->strokes) { bGPDstroke *gps_to = NULL; /* only selected */ - if ((GPENCIL_EDIT_MODE(gpd)) && (only_selected) && - ((gps_from->flag & GP_STROKE_SELECT) == 0)) { + if (GPENCIL_EDIT_MODE(gpd) && (only_selected) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { continue; } /* skip strokes that are invalid for current view */ @@ -712,7 +711,7 @@ static bool gpencil_interpolate_set_init_values(bContext *C, wmOperator *op, tGP tgpi->flag, (RNA_enum_get(op->ptr, "layers") == 1), GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS); SET_FLAG_FROM_TEST( tgpi->flag, - ((GPENCIL_EDIT_MODE(tgpi->gpd)) && (RNA_boolean_get(op->ptr, "interpolate_selected_only"))), + (GPENCIL_EDIT_MODE(tgpi->gpd) && (RNA_boolean_get(op->ptr, "interpolate_selected_only"))), GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED); tgpi->flipmode = RNA_enum_get(op->ptr, "flip"); @@ -1249,7 +1248,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) const int step = RNA_int_get(op->ptr, "step"); const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); const bool all_layers = (bool)(RNA_enum_get(op->ptr, "layers") == 1); - const bool only_selected = ((GPENCIL_EDIT_MODE(gpd)) && + const bool only_selected = (GPENCIL_EDIT_MODE(gpd) && (RNA_boolean_get(op->ptr, "interpolate_selected_only") != 0)); eGP_InterpolateFlipMode flipmode = RNA_enum_get(op->ptr, "flip"); @@ -1309,7 +1308,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (bGPDstroke *, gps_from, &prevFrame->strokes) { bGPDstroke *gps_to = NULL; /* Only selected. */ - if ((GPENCIL_EDIT_MODE(gpd)) && (only_selected) && + if (GPENCIL_EDIT_MODE(gpd) && (only_selected) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 78eaab01b1a..cf49aefe2ea 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -1316,8 +1316,7 @@ static void gpencil_primitive_interaction_end(bContext *C, BrushGpencilSettings *brush_settings = brush->gpencil_settings; const int def_nr = tgpi->gpd->vertex_group_active_index - 1; - const ListBase *defbase = BKE_object_defgroup_list(tgpi->ob); - const bool have_weight = (bool)BLI_findlink(defbase, def_nr); + const bool have_weight = BLI_findlink(&tgpi->gpd->vertex_group_names, def_nr) != NULL; /* return to normal cursor and header status */ ED_workspace_status_text(C, NULL); diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index 462462cf341..14caf0c08a7 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -1352,7 +1352,7 @@ static void gpencil_sculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso * - This is useful when animating as it saves that "uh-oh" moment when you realize you've * spent too much time editing the wrong frame. */ - if ((IS_AUTOKEY_ON(scene)) && (gpf->framenum != cfra)) { + if (IS_AUTOKEY_ON(scene) && (gpf->framenum != cfra)) { BKE_gpencil_frame_addcopy(gpl, cfra); /* Need tag to recalculate evaluated data to avoid crashes. */ DEG_id_tag_update(&gso->gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); @@ -1377,7 +1377,7 @@ static float gpencil_sculpt_rotation_eval_get(tGP_BrushEditData *gso, int idx_eval) { /* If multiframe or no modifiers, return 0. */ - if ((GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd)) || (!gso->is_transformed)) { + if (GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd) || (!gso->is_transformed)) { return 0.0f; } @@ -1513,8 +1513,7 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso, } pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; /* If masked and the point is not selected, skip it. */ - if ((GPENCIL_ANY_SCULPT_MASK(gso->mask)) && - ((pt_active->flag & GP_SPOINT_SELECT) == 0)) { + if (GPENCIL_ANY_SCULPT_MASK(gso->mask) && ((pt_active->flag & GP_SPOINT_SELECT) == 0)) { continue; } index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i; diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index 16605b6c634..633e371cbd1 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -919,7 +919,7 @@ static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, pt_active = pt->runtime.pt_orig; if (pt_active != NULL) { /* If masked and the point is not selected, skip it. */ - if ((GPENCIL_ANY_VERTEX_MASK(gso->mask)) && + if (GPENCIL_ANY_VERTEX_MASK(gso->mask) && ((pt_active->flag & GP_SPOINT_SELECT) == 0)) { continue; } diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 5cf2a9c9dd0..50e53acb376 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -34,9 +34,9 @@ struct ListBase; struct ARegion; struct ARegionType; +struct FModifier; struct Main; struct NlaStrip; -struct FModifier; struct PanelType; struct ReportList; struct ScrArea; diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index eaa54f66928..868235c36e5 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -31,7 +31,6 @@ extern "C" { #endif -struct bAction; struct Base; struct Bone; struct Depsgraph; @@ -46,6 +45,7 @@ struct Scene; struct UndoType; struct View3D; struct ViewLayer; +struct bAction; struct bArmature; struct bContext; struct bPoseChannel; @@ -255,8 +255,8 @@ struct PoseBackup *ED_pose_backup_create_selected_bones( struct PoseBackup *ED_pose_backup_create_all_bones( const struct Object *ob, const struct bAction *action) ATTR_WARN_UNUSED_RESULT; bool ED_pose_backup_is_selection_relevant(const struct PoseBackup *pose_backup); -void ED_pose_backup_restore(const struct PoseBackup *pose_backup); -void ED_pose_backup_free(struct PoseBackup *pose_backup); +void ED_pose_backup_restore(const struct PoseBackup *pbd); +void ED_pose_backup_free(struct PoseBackup *pbd); #ifdef __cplusplus } diff --git a/source/blender/editors/include/ED_asset.h b/source/blender/editors/include/ED_asset.h index d33085f1cc4..0058c0615c3 100644 --- a/source/blender/editors/include/ED_asset.h +++ b/source/blender/editors/include/ED_asset.h @@ -28,9 +28,9 @@ extern "C" { struct AssetFilterSettings; struct AssetLibraryReference; -struct bContext; struct Main; struct ReportList; +struct bContext; struct wmNotifier; typedef struct AssetTempIDConsumer AssetTempIDConsumer; diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 058d4fa91a3..6e4002fcc0a 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -31,6 +31,7 @@ struct ID; struct Main; struct Scene; struct ScrArea; +struct SpaceNode; struct Tex; struct View2D; struct bContext; @@ -40,7 +41,6 @@ struct bNodeSocketType; struct bNodeTree; struct bNodeTreeType; struct bNodeType; -struct SpaceNode; typedef enum { NODE_TOP = 1, diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h index 6d0172e724a..5318c653b6d 100644 --- a/source/blender/editors/include/ED_particle.h +++ b/source/blender/editors/include/ED_particle.h @@ -34,9 +34,9 @@ struct ParticleSystem; struct Scene; struct UndoType; struct ViewLayer; -struct wmGenericUserData; struct bContext; struct rcti; +struct wmGenericUserData; /* particle edit mode */ void PE_free_ptcache_edit(struct PTCacheEdit *edit); diff --git a/source/blender/editors/include/ED_spreadsheet.h b/source/blender/editors/include/ED_spreadsheet.h index ff77135a51c..dfa8aa7bfbc 100644 --- a/source/blender/editors/include/ED_spreadsheet.h +++ b/source/blender/editors/include/ED_spreadsheet.h @@ -16,14 +16,14 @@ #pragma once -struct SpreadsheetContext; -struct SpaceSpreadsheet; -struct SpaceNode; struct ID; -struct bNode; struct Main; -struct bContext; struct Object; +struct SpaceNode; +struct SpaceSpreadsheet; +struct SpreadsheetContext; +struct bContext; +struct bNode; #ifdef __cplusplus extern "C" { diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index d5316df0e0c..ddde4f5a9dc 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2453,7 +2453,7 @@ bool ui_but_is_rna_valid(uiBut *but) */ bool ui_but_supports_cycling(const uiBut *but) { - return ((ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_LISTBOX)) || + return (ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_LISTBOX) || (but->type == UI_BTYPE_MENU && ui_but_menu_step_poll(but)) || (but->type == UI_BTYPE_COLOR && ((uiButColor *)but)->is_pallete_color) || (but->menu_step_func != NULL)); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 858955271b2..4f8bb6342f7 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -770,7 +770,7 @@ static uiAfterFunc *ui_afterfunc_new(void) * \param context_but: A button from which to get the context from (`uiBut.context`) for the * operator execution. * - * \note Ownership over \a properties is moved here. The after-func owns it now. + * \note Ownership over \a properties is moved here. The #uiAfterFunc owns it now. * \note Can only call while handling buttons. */ static void ui_handle_afterfunc_add_operator_ex(wmOperatorType *ot, @@ -1157,7 +1157,7 @@ static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleBu } /** - * \note Ownership of \a properties is moved here. The after-func owns it now. + * \note Ownership of \a properties is moved here. The #uiAfterFunc owns it now. * * \param context_but: The button to use context from when calling or polling the operator. * @@ -9458,10 +9458,10 @@ static int ui_list_handle_click_drag(bContext *C, activate = true; } } - /* KM_CLICK is only sent after an uncaught release event, so the forground button gets all + /* #KM_CLICK is only sent after an uncaught release event, so the foreground button gets all * regular events (including mouse presses to start dragging) and this part only kicks in if it * hasn't handled the release event. Note that if there's no overlaid button, the row selects - * on the press event already via regular UI_BTYPE_LISTROW handling. */ + * on the press event already via regular #UI_BTYPE_LISTROW handling. */ else if ((event->type == LEFTMOUSE) && (event->val == KM_CLICK)) { activate = true; } diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index 13436b6c6c8..c863b1f8bdf 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -688,13 +688,13 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region) if (data->items.more) { ui_searchbox_butrect(&rect, data, data->items.maxitem - 1); GPU_blend(GPU_BLEND_ALPHA); - UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN); + UI_icon_draw(BLI_rcti_size_x(&rect) / 2, rect.ymin - 9, ICON_TRIA_DOWN); GPU_blend(GPU_BLEND_NONE); } if (data->items.offset) { ui_searchbox_butrect(&rect, data, 0); GPU_blend(GPU_BLEND_ALPHA); - UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP); + UI_icon_draw(BLI_rcti_size_x(&rect) / 2, rect.ymax - 7, ICON_TRIA_UP); GPU_blend(GPU_BLEND_NONE); } } @@ -990,13 +990,13 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe if (data->items.more) { ui_searchbox_butrect(&rect, data, data->items.maxitem - 1); GPU_blend(GPU_BLEND_ALPHA); - UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN); + UI_icon_draw(BLI_rcti_size_x(&rect) / 2, rect.ymin - 9, ICON_TRIA_DOWN); GPU_blend(GPU_BLEND_NONE); } if (data->items.offset) { ui_searchbox_butrect(&rect, data, 0); GPU_blend(GPU_BLEND_ALPHA); - UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP); + UI_icon_draw(BLI_rcti_size_x(&rect) / 2, rect.ymax - 7, ICON_TRIA_UP); GPU_blend(GPU_BLEND_NONE); } } diff --git a/source/blender/editors/interface/interface_template_asset_view.cc b/source/blender/editors/interface/interface_template_asset_view.cc index 2860abb32a1..5a05813f947 100644 --- a/source/blender/editors/interface/interface_template_asset_view.cc +++ b/source/blender/editors/interface/interface_template_asset_view.cc @@ -53,7 +53,7 @@ static void asset_view_item_but_drag_set(uiBut *but, AssetHandle *asset_handle) { ID *id = asset_handle->file_data->id; - if (id != NULL) { + if (id != nullptr) { UI_but_drag_set_id(but, id); return; } @@ -257,14 +257,14 @@ void uiTemplateAssetView(uiLayout *layout, if (activate_opname) { PointerRNA *ptr = UI_list_custom_activate_operator_set( - list, activate_opname, r_activate_op_properties != NULL); + list, activate_opname, r_activate_op_properties != nullptr); if (r_activate_op_properties && ptr) { *r_activate_op_properties = *ptr; } } if (drag_opname) { PointerRNA *ptr = UI_list_custom_drag_operator_set( - list, drag_opname, r_drag_op_properties != NULL); + list, drag_opname, r_drag_op_properties != nullptr); if (r_drag_op_properties && ptr) { *r_drag_op_properties = *ptr; } diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index aa6dff3952a..93a790b53d0 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -852,7 +852,7 @@ static bool ui_view2d_cur_ensure_rect_in_view(View2D *v2d, const rctf *rect) void UI_but_ensure_in_view(const bContext *C, ARegion *region, const uiBut *but) { View2D *v2d = ®ion->v2d; - /* Unitialized view or region that doesn't use View2D. */ + /* Uninitialized view or region that doesn't use View2D. */ if ((v2d->flag & V2D_IS_INIT) == 0) { return; } diff --git a/source/blender/editors/io/io_gpencil.h b/source/blender/editors/io/io_gpencil.h index b347be00412..428b09f0e9c 100644 --- a/source/blender/editors/io/io_gpencil.h +++ b/source/blender/editors/io/io_gpencil.h @@ -25,8 +25,8 @@ */ struct ARegion; -struct bContext; struct View3D; +struct bContext; struct wmOperatorType; void WM_OT_gpencil_import_svg(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 2109fe2a822..6251fb799c5 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -123,9 +123,14 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C, RNA_enum_items_add_value( &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ALL_SRC); - if (data_type == DT_TYPE_MDEFORMVERT) { - Object *ob_src = CTX_data_active_object(C); + Object *ob_src = CTX_data_active_object(C); + if (ob_src == NULL) { + RNA_enum_item_end(&item, &totitem); + *r_free = true; + return item; + } + if (data_type == DT_TYPE_MDEFORMVERT && BKE_object_supports_vertex_groups(ob_src)) { if (BKE_object_pose_armature_get(ob_src)) { RNA_enum_items_add_value( &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT); @@ -133,67 +138,57 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C, &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM); } - if (ob_src) { - const bDeformGroup *dg; - int i; + const bDeformGroup *dg; + int i; - RNA_enum_item_add_separator(&item, &totitem); + RNA_enum_item_add_separator(&item, &totitem); - const ListBase *defbase = BKE_object_defgroup_list(ob_src); - for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) { - tmp_item.value = i; - tmp_item.identifier = tmp_item.name = dg->name; - RNA_enum_item_add(&item, &totitem, &tmp_item); - } + const ListBase *defbase = BKE_object_defgroup_list(ob_src); + for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) { + tmp_item.value = i; + tmp_item.identifier = tmp_item.name = dg->name; + RNA_enum_item_add(&item, &totitem, &tmp_item); } } else if (data_type == DT_TYPE_SHAPEKEY) { /* TODO */ } else if (data_type == DT_TYPE_UV) { - Object *ob_src = CTX_data_active_object(C); - - if (ob_src) { - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src); - CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH; - cddata_masks.lmask |= CD_MASK_MLOOPUV; - Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks); - int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV); + CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH; + cddata_masks.lmask |= CD_MASK_MLOOPUV; + Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks); + int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV); - RNA_enum_item_add_separator(&item, &totitem); + RNA_enum_item_add_separator(&item, &totitem); - for (int i = 0; i < num_data; i++) { - tmp_item.value = i; - tmp_item.identifier = tmp_item.name = CustomData_get_layer_name( - &me_eval->ldata, CD_MLOOPUV, i); - RNA_enum_item_add(&item, &totitem, &tmp_item); - } + for (int i = 0; i < num_data; i++) { + tmp_item.value = i; + tmp_item.identifier = tmp_item.name = CustomData_get_layer_name( + &me_eval->ldata, CD_MLOOPUV, i); + RNA_enum_item_add(&item, &totitem, &tmp_item); } } else if (data_type == DT_TYPE_VCOL) { - Object *ob_src = CTX_data_active_object(C); - - if (ob_src) { - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src); - CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH; - cddata_masks.lmask |= CD_MASK_MLOOPCOL; - Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks); - int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL); + CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH; + cddata_masks.lmask |= CD_MASK_MLOOPCOL; + Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks); + int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL); - RNA_enum_item_add_separator(&item, &totitem); + RNA_enum_item_add_separator(&item, &totitem); - for (int i = 0; i < num_data; i++) { - tmp_item.value = i; - tmp_item.identifier = tmp_item.name = CustomData_get_layer_name( - &me_eval->ldata, CD_MLOOPCOL, i); - RNA_enum_item_add(&item, &totitem, &tmp_item); - } + for (int i = 0; i < num_data; i++) { + tmp_item.value = i; + tmp_item.identifier = tmp_item.name = CustomData_get_layer_name( + &me_eval->ldata, CD_MLOOPCOL, i); + RNA_enum_item_add(&item, &totitem, &tmp_item); } } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 4ea599fd30e..f64f95c5322 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -3892,7 +3892,7 @@ static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op) int fail = 0; CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { - if (obact != ob) { + if (obact != ob && BKE_object_supports_vertex_groups(ob)) { if (ED_vgroup_array_copy(ob, obact)) { DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); DEG_relations_tag_update(CTX_data_main(C)); @@ -3909,8 +3909,8 @@ static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op) if ((changed_tot == 0 && fail == 0) || fail) { BKE_reportf(op->reports, RPT_ERROR, - "Copy vertex groups to selected: %d done, %d failed (object data must have " - "matching indices)", + "Copy vertex groups to selected: %d done, %d failed (object data must support " + "vertex groups and have matching indices)", changed_tot, fail); } diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 9abf15d2198..5aa63ac56d8 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -861,9 +861,9 @@ static void action_preview_render_cleanup(IconPreview *preview, struct PoseBacku DEG_id_tag_update(&preview->active_object->id, ID_RECALC_GEOMETRY); } -/* Render a pose. It is assumed that the pose has already been applied and that the scene camera is - * capturing the pose. In other words, this function just renders from the scene camera without - * evaluating the Action stored in preview->id. */ +/* Render a pose from the scene camera. It is assumed that the scene camera is + * capturing the pose. The pose is applied temporarily to the current object + * before rendering. */ static void action_preview_render(IconPreview *preview, IconPreviewSize *preview_sized) { char err_out[256] = ""; @@ -1308,8 +1308,9 @@ static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect) scaledy = (float)h; } - ex = (short)scaledx; - ey = (short)scaledy; + /* Scaling down must never assign zero width/height, see: T89868. */ + ex = MAX2(1, (short)scaledx); + ey = MAX2(1, (short)scaledy); dx = (w - ex) / 2; dy = (h - ey) / 2; diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index ffa6f6ac962..23b90171a1d 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -784,11 +784,10 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s, bool do_random = false; bool do_partial_update = false; - bool update_color = ((brush->flag & BRUSH_USE_GRADIENT) && - ((ELEM(brush->gradient_stroke_mode, - BRUSH_GRADIENT_SPACING_REPEAT, - BRUSH_GRADIENT_SPACING_CLAMP)) || - (cache->last_pressure != pressure))); + bool update_color = ((brush->flag & BRUSH_USE_GRADIENT) && (ELEM(brush->gradient_stroke_mode, + BRUSH_GRADIENT_SPACING_REPEAT, + BRUSH_GRADIENT_SPACING_CLAMP) || + (cache->last_pressure != pressure))); float tex_rotation = -brush->mtex.rot; float mask_rotation = -brush->mask_mtex.rot; diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h index 7564fa4b930..9cb363ff0c9 100644 --- a/source/blender/editors/space_buttons/buttons_intern.h +++ b/source/blender/editors/space_buttons/buttons_intern.h @@ -34,8 +34,8 @@ struct Tex; struct bContext; struct bContextDataResult; struct bNode; -struct bNodeTree; struct bNodeSocket; +struct bNodeTree; struct wmOperatorType; struct SpaceProperties_Runtime { diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 1421be41124..a853efb1ace 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -859,7 +859,7 @@ static int graphkeys_box_select_exec(bContext *C, wmOperator *op) * as frame-range one is often used for tweaking timing when "blocking", * while channels is not that useful. */ - if ((BLI_rcti_size_x(&rect)) >= (BLI_rcti_size_y(&rect))) { + if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect)) { mode = BEZT_OK_FRAMERANGE; } else { diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 50b0ea75052..4779a82948d 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -1013,14 +1013,14 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_ma uiLayoutRow(col, true), imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE); /* only display depth setting if multiple depths can be used */ - if ((ELEM(depth_ok, - R_IMF_CHAN_DEPTH_1, - R_IMF_CHAN_DEPTH_8, - R_IMF_CHAN_DEPTH_10, - R_IMF_CHAN_DEPTH_12, - R_IMF_CHAN_DEPTH_16, - R_IMF_CHAN_DEPTH_24, - R_IMF_CHAN_DEPTH_32)) == 0) { + if (ELEM(depth_ok, + R_IMF_CHAN_DEPTH_1, + R_IMF_CHAN_DEPTH_8, + R_IMF_CHAN_DEPTH_10, + R_IMF_CHAN_DEPTH_12, + R_IMF_CHAN_DEPTH_16, + R_IMF_CHAN_DEPTH_24, + R_IMF_CHAN_DEPTH_32) == 0) { uiItemR(uiLayoutRow(col, true), imfptr, "color_depth", UI_ITEM_R_EXPAND, NULL, ICON_NONE); } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 6b9821745c7..dad354ba8ee 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1995,7 +1995,7 @@ static bool image_save_as_draw_check_prop(PointerRNA *ptr, return !(STREQ(prop_id, "filepath") || STREQ(prop_id, "directory") || STREQ(prop_id, "filename") || /* when saving a copy, relative path has no effect */ - ((STREQ(prop_id, "relative_path")) && RNA_boolean_get(ptr, "copy"))); + (STREQ(prop_id, "relative_path") && RNA_boolean_get(ptr, "copy"))); } static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh index c9b73aabf96..680da9b6794 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh @@ -22,8 +22,8 @@ #include "BLI_float2.hh" #include "BLI_float3.hh" -struct Object; struct Collection; +struct Object; namespace blender::ed::spreadsheet { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh index d9e6d882c2a..19906d73e7f 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh @@ -23,9 +23,9 @@ #include "spreadsheet_dataset_layout.hh" struct ARegion; -struct uiBlock; struct View2D; struct bContext; +struct uiBlock; namespace blender::ed::spreadsheet { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_draw.hh b/source/blender/editors/space_spreadsheet/spreadsheet_draw.hh index 647587ec8b0..9accd1d3d09 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_draw.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_draw.hh @@ -18,9 +18,9 @@ #include "BLI_vector.hh" -struct uiBlock; -struct bContext; struct ARegion; +struct bContext; +struct uiBlock; namespace blender::ed::spreadsheet { diff --git a/source/blender/editors/space_text/text_format_lua.c b/source/blender/editors/space_text/text_format_lua.c index 16eb66624ce..0cd2d9baa0b 100644 --- a/source/blender/editors/space_text/text_format_lua.c +++ b/source/blender/editors/space_text/text_format_lua.c @@ -165,9 +165,9 @@ static char txtfmt_lua_format_identifier(const char *str) /* Keep aligned args for readability. */ /* clang-format off */ - if ((txtfmt_lua_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL; - } else if ((txtfmt_lua_find_keyword(str)) != -1) { fmt = FMT_TYPE_KEYWORD; - } else { fmt = FMT_TYPE_DEFAULT; + if (txtfmt_lua_find_specialvar(str) != -1) { fmt = FMT_TYPE_SPECIAL; + } else if (txtfmt_lua_find_keyword(str) != -1) { fmt = FMT_TYPE_KEYWORD; + } else { fmt = FMT_TYPE_DEFAULT; } /* clang-format on */ diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c index 1a024779a83..97d9ec546ca 100644 --- a/source/blender/editors/space_text/text_format_osl.c +++ b/source/blender/editors/space_text/text_format_osl.c @@ -189,11 +189,11 @@ static char txtfmt_osl_format_identifier(const char *str) /* Keep aligned args for readability. */ /* clang-format off */ - if ((txtfmt_osl_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL; - } else if ((txtfmt_osl_find_builtinfunc(str)) != -1) { fmt = FMT_TYPE_KEYWORD; - } else if ((txtfmt_osl_find_reserved(str)) != -1) { fmt = FMT_TYPE_RESERVED; - } else if ((txtfmt_osl_find_preprocessor(str)) != -1) { fmt = FMT_TYPE_DIRECTIVE; - } else { fmt = FMT_TYPE_DEFAULT; + if (txtfmt_osl_find_specialvar(str) != -1) { fmt = FMT_TYPE_SPECIAL; + } else if (txtfmt_osl_find_builtinfunc(str) != -1) { fmt = FMT_TYPE_KEYWORD; + } else if (txtfmt_osl_find_reserved(str) != -1) { fmt = FMT_TYPE_RESERVED; + } else if (txtfmt_osl_find_preprocessor(str) != -1) { fmt = FMT_TYPE_DIRECTIVE; + } else { fmt = FMT_TYPE_DEFAULT; } /* clang-format on */ diff --git a/source/blender/editors/space_text/text_format_pov.c b/source/blender/editors/space_text/text_format_pov.c index 1200dda7533..ea3d0ec1478 100644 --- a/source/blender/editors/space_text/text_format_pov.c +++ b/source/blender/editors/space_text/text_format_pov.c @@ -762,11 +762,11 @@ static char txtfmt_pov_format_identifier(const char *str) /* Keep aligned args for readability. */ /* clang-format off */ - if ((txtfmt_pov_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL; - } else if ((txtfmt_pov_find_keyword(str)) != -1) { fmt = FMT_TYPE_KEYWORD; - } else if ((txtfmt_pov_find_reserved_keywords(str)) != -1) { fmt = FMT_TYPE_RESERVED; - } else if ((txtfmt_pov_find_reserved_builtins(str)) != -1) { fmt = FMT_TYPE_DIRECTIVE; - } else { fmt = FMT_TYPE_DEFAULT; + if (txtfmt_pov_find_specialvar(str) != -1) { fmt = FMT_TYPE_SPECIAL; + } else if (txtfmt_pov_find_keyword(str) != -1) { fmt = FMT_TYPE_KEYWORD; + } else if (txtfmt_pov_find_reserved_keywords(str) != -1) { fmt = FMT_TYPE_RESERVED; + } else if (txtfmt_pov_find_reserved_builtins(str) != -1) { fmt = FMT_TYPE_DIRECTIVE; + } else { fmt = FMT_TYPE_DEFAULT; } /* clang-format on */ diff --git a/source/blender/editors/space_text/text_format_pov_ini.c b/source/blender/editors/space_text/text_format_pov_ini.c index 1c6a93d2d7a..259ad02a6b7 100644 --- a/source/blender/editors/space_text/text_format_pov_ini.c +++ b/source/blender/editors/space_text/text_format_pov_ini.c @@ -347,10 +347,10 @@ static int txtfmt_ini_find_bool(const char *string) static char txtfmt_pov_ini_format_identifier(const char *str) { char fmt; - if ((txtfmt_ini_find_keyword(str)) != -1) { + if (txtfmt_ini_find_keyword(str) != -1) { fmt = FMT_TYPE_KEYWORD; } - else if ((txtfmt_ini_find_reserved(str)) != -1) { + else if (txtfmt_ini_find_reserved(str) != -1) { fmt = FMT_TYPE_RESERVED; } else { diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c index 2717c0bf5b0..e2a01a8d85d 100644 --- a/source/blender/editors/space_text/text_format_py.c +++ b/source/blender/editors/space_text/text_format_py.c @@ -315,10 +315,10 @@ static char txtfmt_py_format_identifier(const char *str) /* Keep aligned args for readability. */ /* clang-format off */ - if ((txtfmt_py_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL; - } else if ((txtfmt_py_find_builtinfunc(str)) != -1) { fmt = FMT_TYPE_KEYWORD; - } else if ((txtfmt_py_find_decorator(str)) != -1) { fmt = FMT_TYPE_RESERVED; - } else { fmt = FMT_TYPE_DEFAULT; + if (txtfmt_py_find_specialvar(str) != -1) { fmt = FMT_TYPE_SPECIAL; + } else if (txtfmt_py_find_builtinfunc(str) != -1) { fmt = FMT_TYPE_KEYWORD; + } else if (txtfmt_py_find_decorator(str) != -1) { fmt = FMT_TYPE_RESERVED; + } else { fmt = FMT_TYPE_DEFAULT; } /* clang-format on */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index d34cc6f424f..efcf7d587e1 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -78,7 +78,7 @@ static void initSnapSpatial(TransInfo *t, float r_snap[2]); bool transdata_check_local_islands(TransInfo *t, short around) { - return ((around == V3D_AROUND_LOCAL_ORIGINS) && ((ELEM(t->obedit_type, OB_MESH, OB_GPENCIL)))); + return ((around == V3D_AROUND_LOCAL_ORIGINS) && (ELEM(t->obedit_type, OB_MESH, OB_GPENCIL))); } /* ************************** SPACE DEPENDENT CODE **************************** */ diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index a6f5aba5a1d..17512c79d03 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -262,8 +262,16 @@ static void free_transform_custom_data(TransCustomData *custom_data) /* Canceled, need to update the strips display. */ static void seq_transform_cancel(TransInfo *t, SeqCollection *transformed_strips) { + ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene, false)); + Sequence *seq; SEQ_ITERATOR_FOREACH (seq, transformed_strips) { + /* Handle pre-existing overlapping strips even when operator is canceled. + * This is necessary for SEQUENCER_OT_duplicate_move macro for example. */ + if (SEQ_transform_test_overlap(seqbase, seq)) { + SEQ_transform_seqbase_shuffle(seqbase, seq, t->scene); + } + SEQ_time_update_sequence_bounds(t->scene, seq); } } diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index 0368252f54b..3e0029156c1 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -695,7 +695,7 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op) CTX_wm_region_set(C, region_win); } - if ((WM_operator_repeat_check(C, op)) && (WM_operator_poll(C, op->type)) && + if (WM_operator_repeat_check(C, op) && WM_operator_poll(C, op->type) && /* NOTE: undo/redo can't run if there are jobs active, * check for screen jobs only so jobs like material/texture/world preview * (which copy their data), won't stop redo, see T29579], diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 28853bcdedf..535a0e00347 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -1928,6 +1928,11 @@ static StitchState *stitch_init(bContext *C, state->obedit = obedit; state->em = em; + /* Workaround for sync-select & face-select mode which implies all selected faces are detached, + * for stitch this isn't useful behavior, see T86924. */ + const int selectmode_orig = scene->toolsettings->selectmode; + scene->toolsettings->selectmode = SCE_SELECT_VERTEX; + /* in uv synch selection, all uv's are visible */ if (ts->uv_flag & UV_SYNC_SELECTION) { state->element_map = BM_uv_element_map_create(state->em->bm, scene, false, false, true, true); @@ -1935,6 +1940,9 @@ static StitchState *stitch_init(bContext *C, else { state->element_map = BM_uv_element_map_create(state->em->bm, scene, true, false, true, true); } + + scene->toolsettings->selectmode = selectmode_orig; + if (!state->element_map) { state_delete(state); return NULL; @@ -1989,7 +1997,7 @@ static StitchState *stitch_init(bContext *C, /* Now, on to generate our uv connectivity data */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!(ts->uv_flag & UV_SYNC_SELECTION) && - ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))) { + (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))) { continue; } @@ -2172,8 +2180,8 @@ static StitchState *stitch_init(bContext *C, "uv_stitch_selection_stack"); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!(ts->uv_flag & UV_SYNC_SELECTION) && ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || - !BM_elem_flag_test(efa, BM_ELEM_SELECT))) { + if (!(ts->uv_flag & UV_SYNC_SELECTION) && + (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))) { continue; } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 0e9669d0f60..3d5dabda23d 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -315,7 +315,7 @@ static ParamHandle *construct_param_handle(const Scene *scene, BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { - if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || + if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || (options->only_selected_faces && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) { continue; } @@ -404,7 +404,7 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene, BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { - if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || + if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || (options->only_selected_faces && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) { continue; } diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp index cd0059f3c21..afb23690a84 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp @@ -2285,7 +2285,7 @@ struct less_SVertex2D { Vec3r A = x->point2D(); Vec3r B = y->point2D(); for (unsigned int i = 0; i < 3; i++) { - if ((fabs(A[i] - B[i])) < epsilon) { + if (fabs(A[i] - B[i]) < epsilon) { continue; } if (A[i] < B[i]) { diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h index 247b0b3f57b..1d4370ed3a9 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h +++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h @@ -575,9 +575,9 @@ BLI_INLINE int lineart_LineIntersectTest2d( } struct Depsgraph; -struct Scene; -struct LineartRenderBuffer; struct LineartGpencilModifierData; +struct LineartRenderBuffer; +struct Scene; void MOD_lineart_destroy_render_data(struct LineartGpencilModifierData *lmd); @@ -602,8 +602,8 @@ LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartRenderBuffer *r LineartBoundingArea *MOD_lineart_get_bounding_area(LineartRenderBuffer *rb, double x, double y); -struct bGPDlayer; struct bGPDframe; +struct bGPDlayer; void MOD_lineart_gpencil_generate(LineartCache *cache, struct Depsgraph *depsgraph, diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index 9899d889c56..82fd85f5c65 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -3442,9 +3442,9 @@ static bool lineart_bounding_area_triangle_intersect(LineartRenderBuffer *fb, return true; } - if ((lineart_bounding_area_edge_intersect(fb, FBC1, FBC2, ba)) || - (lineart_bounding_area_edge_intersect(fb, FBC2, FBC3, ba)) || - (lineart_bounding_area_edge_intersect(fb, FBC3, FBC1, ba))) { + if (lineart_bounding_area_edge_intersect(fb, FBC1, FBC2, ba) || + lineart_bounding_area_edge_intersect(fb, FBC2, FBC3, ba) || + lineart_bounding_area_edge_intersect(fb, FBC3, FBC1, ba)) { return true; } diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h b/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h index 9d109320f09..70ff4a373dd 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h @@ -33,10 +33,10 @@ #include <math.h> #include <string.h> -struct LineartStaticMemPool; -struct LineartStaticMemPoolNode; struct LineartEdge; struct LineartRenderBuffer; +struct LineartStaticMemPool; +struct LineartStaticMemPoolNode; void *lineart_list_append_pointer_pool(ListBase *h, struct LineartStaticMemPool *smp, void *data); void *lineart_list_append_pointer_pool_sized(ListBase *h, diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc index 1293cc0953d..4bb13d01c2d 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.cc +++ b/source/blender/gpu/intern/gpu_framebuffer.cc @@ -609,7 +609,13 @@ GPUOffScreen *GPU_offscreen_create( } if ((depth && !ofs->depth) || !ofs->color) { - BLI_snprintf(err_out, 256, "GPUTexture: Texture allocation failed."); + const char error[] = "GPUTexture: Texture allocation failed."; + if (err_out) { + BLI_snprintf(err_out, 256, error); + } + else { + fprintf(stderr, error); + } GPU_offscreen_free(ofs); return nullptr; } diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index 7646cce2a3e..585cb296bac 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -88,7 +88,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType name = outnode->name; input = outnode->inputs.first; - if ((STR_ELEM(name, "set_value", "set_rgb", "set_rgba")) && (input->type == type)) { + if (STR_ELEM(name, "set_value", "set_rgb", "set_rgba") && (input->type == type)) { input = MEM_dupallocN(outnode->inputs.first); if (input->link) { input->link->users++; diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index f90c37e5c50..42b85da1f93 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -90,7 +90,7 @@ void GLBackend::platform_init() device |= GPU_DEVICE_INTEL_UHD; } } - else if ((strstr(renderer, "Mesa DRI R")) || + else if (strstr(renderer, "Mesa DRI R") || (strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) || (strstr(renderer, "AMD") && strstr(vendor, "X.Org")) || (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) || diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 2cfce7b1ba0..d527aca184c 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -69,8 +69,8 @@ extern "C" { * \attention defined in ??? */ struct ImBuf; -struct rcti; struct rctf; +struct rcti; /** * diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index 4a964c64917..79c2583f983 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -1195,22 +1195,9 @@ static ImBuf *scaleupx(struct ImBuf *ibuf, int newx) { uchar *rect, *_newrect = NULL, *newrect; float *rectf, *_newrectf = NULL, *newrectf; - float sample, add; - float val_a, nval_a, diff_a; - float val_b, nval_b, diff_b; - float val_g, nval_g, diff_g; - float val_r, nval_r, diff_r; - float val_af, nval_af, diff_af; - float val_bf, nval_bf, diff_bf; - float val_gf, nval_gf, diff_gf; - float val_rf, nval_rf, diff_rf; int x, y; bool do_rect = false, do_float = false; - val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; - val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; - val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; - val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; if (ibuf == NULL) { return NULL; } @@ -1236,119 +1223,158 @@ static ImBuf *scaleupx(struct ImBuf *ibuf, int newx) } } - add = (ibuf->x - 1.001) / (newx - 1.0); - rect = (uchar *)ibuf->rect; rectf = (float *)ibuf->rect_float; newrect = _newrect; newrectf = _newrectf; - for (y = ibuf->y; y > 0; y--) { - - sample = 0; - + /* Special case, copy all columns, needed since the scaling logic assumes there is at least + * two rows to interpolate between causing out of bounds read for 1px images, see T70356. */ + if (UNLIKELY(ibuf->x == 1)) { if (do_rect) { - val_a = rect[0]; - nval_a = rect[4]; - diff_a = nval_a - val_a; - val_a += 0.5f; - - val_b = rect[1]; - nval_b = rect[5]; - diff_b = nval_b - val_b; - val_b += 0.5f; - - val_g = rect[2]; - nval_g = rect[6]; - diff_g = nval_g - val_g; - val_g += 0.5f; - - val_r = rect[3]; - nval_r = rect[7]; - diff_r = nval_r - val_r; - val_r += 0.5f; - - rect += 8; + for (y = ibuf->y; y > 0; y--) { + for (x = newx; x > 0; x--) { + memcpy(newrect, rect, sizeof(char[4])); + newrect += 4; + } + rect += 4; + } } if (do_float) { - val_af = rectf[0]; - nval_af = rectf[4]; - diff_af = nval_af - val_af; + for (y = ibuf->y; y > 0; y--) { + for (x = newx; x > 0; x--) { + memcpy(newrectf, rectf, sizeof(float[4])); + newrectf += 4; + } + rectf += 4; + } + } + } + else { + const float add = (ibuf->x - 1.001) / (newx - 1.0); + float sample; - val_bf = rectf[1]; - nval_bf = rectf[5]; - diff_bf = nval_bf - val_bf; + float val_a, nval_a, diff_a; + float val_b, nval_b, diff_b; + float val_g, nval_g, diff_g; + float val_r, nval_r, diff_r; + float val_af, nval_af, diff_af; + float val_bf, nval_bf, diff_bf; + float val_gf, nval_gf, diff_gf; + float val_rf, nval_rf, diff_rf; - val_gf = rectf[2]; - nval_gf = rectf[6]; - diff_gf = nval_gf - val_gf; + val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; + val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; + val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; + val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; - val_rf = rectf[3]; - nval_rf = rectf[7]; - diff_rf = nval_rf - val_rf; + for (y = ibuf->y; y > 0; y--) { - rectf += 8; - } - for (x = newx; x > 0; x--) { - if (sample >= 1.0f) { - sample -= 1.0f; + sample = 0; - if (do_rect) { - val_a = nval_a; - nval_a = rect[0]; - diff_a = nval_a - val_a; - val_a += 0.5f; - - val_b = nval_b; - nval_b = rect[1]; - diff_b = nval_b - val_b; - val_b += 0.5f; - - val_g = nval_g; - nval_g = rect[2]; - diff_g = nval_g - val_g; - val_g += 0.5f; - - val_r = nval_r; - nval_r = rect[3]; - diff_r = nval_r - val_r; - val_r += 0.5f; - rect += 4; - } - if (do_float) { - val_af = nval_af; - nval_af = rectf[0]; - diff_af = nval_af - val_af; + if (do_rect) { + val_a = rect[0]; + nval_a = rect[4]; + diff_a = nval_a - val_a; + val_a += 0.5f; + + val_b = rect[1]; + nval_b = rect[5]; + diff_b = nval_b - val_b; + val_b += 0.5f; + + val_g = rect[2]; + nval_g = rect[6]; + diff_g = nval_g - val_g; + val_g += 0.5f; + + val_r = rect[3]; + nval_r = rect[7]; + diff_r = nval_r - val_r; + val_r += 0.5f; + + rect += 8; + } + if (do_float) { + val_af = rectf[0]; + nval_af = rectf[4]; + diff_af = nval_af - val_af; - val_bf = nval_bf; - nval_bf = rectf[1]; - diff_bf = nval_bf - val_bf; + val_bf = rectf[1]; + nval_bf = rectf[5]; + diff_bf = nval_bf - val_bf; - val_gf = nval_gf; - nval_gf = rectf[2]; - diff_gf = nval_gf - val_gf; + val_gf = rectf[2]; + nval_gf = rectf[6]; + diff_gf = nval_gf - val_gf; - val_rf = nval_rf; - nval_rf = rectf[3]; - diff_rf = nval_rf - val_rf; - rectf += 4; - } - } - if (do_rect) { - newrect[0] = val_a + sample * diff_a; - newrect[1] = val_b + sample * diff_b; - newrect[2] = val_g + sample * diff_g; - newrect[3] = val_r + sample * diff_r; - newrect += 4; + val_rf = rectf[3]; + nval_rf = rectf[7]; + diff_rf = nval_rf - val_rf; + + rectf += 8; } - if (do_float) { - newrectf[0] = val_af + sample * diff_af; - newrectf[1] = val_bf + sample * diff_bf; - newrectf[2] = val_gf + sample * diff_gf; - newrectf[3] = val_rf + sample * diff_rf; - newrectf += 4; + for (x = newx; x > 0; x--) { + if (sample >= 1.0f) { + sample -= 1.0f; + + if (do_rect) { + val_a = nval_a; + nval_a = rect[0]; + diff_a = nval_a - val_a; + val_a += 0.5f; + + val_b = nval_b; + nval_b = rect[1]; + diff_b = nval_b - val_b; + val_b += 0.5f; + + val_g = nval_g; + nval_g = rect[2]; + diff_g = nval_g - val_g; + val_g += 0.5f; + + val_r = nval_r; + nval_r = rect[3]; + diff_r = nval_r - val_r; + val_r += 0.5f; + rect += 4; + } + if (do_float) { + val_af = nval_af; + nval_af = rectf[0]; + diff_af = nval_af - val_af; + + val_bf = nval_bf; + nval_bf = rectf[1]; + diff_bf = nval_bf - val_bf; + + val_gf = nval_gf; + nval_gf = rectf[2]; + diff_gf = nval_gf - val_gf; + + val_rf = nval_rf; + nval_rf = rectf[3]; + diff_rf = nval_rf - val_rf; + rectf += 4; + } + } + if (do_rect) { + newrect[0] = val_a + sample * diff_a; + newrect[1] = val_b + sample * diff_b; + newrect[2] = val_g + sample * diff_g; + newrect[3] = val_r + sample * diff_r; + newrect += 4; + } + if (do_float) { + newrectf[0] = val_af + sample * diff_af; + newrectf[1] = val_bf + sample * diff_bf; + newrectf[2] = val_gf + sample * diff_gf; + newrectf[3] = val_rf + sample * diff_rf; + newrectf += 4; + } + sample += add; } - sample += add; } } @@ -1371,22 +1397,9 @@ static ImBuf *scaleupy(struct ImBuf *ibuf, int newy) { uchar *rect, *_newrect = NULL, *newrect; float *rectf, *_newrectf = NULL, *newrectf; - float sample, add; - float val_a, nval_a, diff_a; - float val_b, nval_b, diff_b; - float val_g, nval_g, diff_g; - float val_r, nval_r, diff_r; - float val_af, nval_af, diff_af; - float val_bf, nval_bf, diff_bf; - float val_gf, nval_gf, diff_gf; - float val_rf, nval_rf, diff_rf; int x, y, skipx; bool do_rect = false, do_float = false; - val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; - val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; - val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; - val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; if (ibuf == NULL) { return NULL; } @@ -1412,126 +1425,159 @@ static ImBuf *scaleupy(struct ImBuf *ibuf, int newy) } } - add = (ibuf->y - 1.001) / (newy - 1.0); - skipx = 4 * ibuf->x; - rect = (uchar *)ibuf->rect; rectf = (float *)ibuf->rect_float; newrect = _newrect; newrectf = _newrectf; - for (x = ibuf->x; x > 0; x--) { + skipx = 4 * ibuf->x; - sample = 0; + /* Special case, copy all rows, needed since the scaling logic assumes there is at least + * two rows to interpolate between causing out of bounds read for 1px images, see T70356. */ + if (UNLIKELY(ibuf->y == 1)) { if (do_rect) { - rect = ((uchar *)ibuf->rect) + 4 * (x - 1); - newrect = _newrect + 4 * (x - 1); - - val_a = rect[0]; - nval_a = rect[skipx]; - diff_a = nval_a - val_a; - val_a += 0.5f; - - val_b = rect[1]; - nval_b = rect[skipx + 1]; - diff_b = nval_b - val_b; - val_b += 0.5f; - - val_g = rect[2]; - nval_g = rect[skipx + 2]; - diff_g = nval_g - val_g; - val_g += 0.5f; - - val_r = rect[3]; - nval_r = rect[skipx + 3]; - diff_r = nval_r - val_r; - val_r += 0.5f; - - rect += 2 * skipx; + for (y = newy; y > 0; y--) { + memcpy(newrect, rect, sizeof(char) * skipx); + newrect += skipx; + } } if (do_float) { - rectf = ibuf->rect_float + 4 * (x - 1); - newrectf = _newrectf + 4 * (x - 1); - - val_af = rectf[0]; - nval_af = rectf[skipx]; - diff_af = nval_af - val_af; + for (y = newy; y > 0; y--) { + memcpy(newrectf, rectf, sizeof(float) * skipx); + newrectf += skipx; + } + } + } + else { + const float add = (ibuf->y - 1.001) / (newy - 1.0); + float sample; + + float val_a, nval_a, diff_a; + float val_b, nval_b, diff_b; + float val_g, nval_g, diff_g; + float val_r, nval_r, diff_r; + float val_af, nval_af, diff_af; + float val_bf, nval_bf, diff_bf; + float val_gf, nval_gf, diff_gf; + float val_rf, nval_rf, diff_rf; + + val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; + val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; + val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; + val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; + + for (x = ibuf->x; x > 0; x--) { + sample = 0; + if (do_rect) { + rect = ((uchar *)ibuf->rect) + 4 * (x - 1); + newrect = _newrect + 4 * (x - 1); + + val_a = rect[0]; + nval_a = rect[skipx]; + diff_a = nval_a - val_a; + val_a += 0.5f; + + val_b = rect[1]; + nval_b = rect[skipx + 1]; + diff_b = nval_b - val_b; + val_b += 0.5f; + + val_g = rect[2]; + nval_g = rect[skipx + 2]; + diff_g = nval_g - val_g; + val_g += 0.5f; + + val_r = rect[3]; + nval_r = rect[skipx + 3]; + diff_r = nval_r - val_r; + val_r += 0.5f; + + rect += 2 * skipx; + } + if (do_float) { + rectf = ibuf->rect_float + 4 * (x - 1); + newrectf = _newrectf + 4 * (x - 1); - val_bf = rectf[1]; - nval_bf = rectf[skipx + 1]; - diff_bf = nval_bf - val_bf; + val_af = rectf[0]; + nval_af = rectf[skipx]; + diff_af = nval_af - val_af; - val_gf = rectf[2]; - nval_gf = rectf[skipx + 2]; - diff_gf = nval_gf - val_gf; + val_bf = rectf[1]; + nval_bf = rectf[skipx + 1]; + diff_bf = nval_bf - val_bf; - val_rf = rectf[3]; - nval_rf = rectf[skipx + 3]; - diff_rf = nval_rf - val_rf; + val_gf = rectf[2]; + nval_gf = rectf[skipx + 2]; + diff_gf = nval_gf - val_gf; - rectf += 2 * skipx; - } + val_rf = rectf[3]; + nval_rf = rectf[skipx + 3]; + diff_rf = nval_rf - val_rf; - for (y = newy; y > 0; y--) { - if (sample >= 1.0f) { - sample -= 1.0f; + rectf += 2 * skipx; + } + for (y = newy; y > 0; y--) { + if (sample >= 1.0f) { + sample -= 1.0f; + + if (do_rect) { + val_a = nval_a; + nval_a = rect[0]; + diff_a = nval_a - val_a; + val_a += 0.5f; + + val_b = nval_b; + nval_b = rect[1]; + diff_b = nval_b - val_b; + val_b += 0.5f; + + val_g = nval_g; + nval_g = rect[2]; + diff_g = nval_g - val_g; + val_g += 0.5f; + + val_r = nval_r; + nval_r = rect[3]; + diff_r = nval_r - val_r; + val_r += 0.5f; + rect += skipx; + } + if (do_float) { + val_af = nval_af; + nval_af = rectf[0]; + diff_af = nval_af - val_af; + + val_bf = nval_bf; + nval_bf = rectf[1]; + diff_bf = nval_bf - val_bf; + + val_gf = nval_gf; + nval_gf = rectf[2]; + diff_gf = nval_gf - val_gf; + + val_rf = nval_rf; + nval_rf = rectf[3]; + diff_rf = nval_rf - val_rf; + rectf += skipx; + } + } if (do_rect) { - val_a = nval_a; - nval_a = rect[0]; - diff_a = nval_a - val_a; - val_a += 0.5f; - - val_b = nval_b; - nval_b = rect[1]; - diff_b = nval_b - val_b; - val_b += 0.5f; - - val_g = nval_g; - nval_g = rect[2]; - diff_g = nval_g - val_g; - val_g += 0.5f; - - val_r = nval_r; - nval_r = rect[3]; - diff_r = nval_r - val_r; - val_r += 0.5f; - rect += skipx; + newrect[0] = val_a + sample * diff_a; + newrect[1] = val_b + sample * diff_b; + newrect[2] = val_g + sample * diff_g; + newrect[3] = val_r + sample * diff_r; + newrect += skipx; } if (do_float) { - val_af = nval_af; - nval_af = rectf[0]; - diff_af = nval_af - val_af; - - val_bf = nval_bf; - nval_bf = rectf[1]; - diff_bf = nval_bf - val_bf; - - val_gf = nval_gf; - nval_gf = rectf[2]; - diff_gf = nval_gf - val_gf; - - val_rf = nval_rf; - nval_rf = rectf[3]; - diff_rf = nval_rf - val_rf; - rectf += skipx; + newrectf[0] = val_af + sample * diff_af; + newrectf[1] = val_bf + sample * diff_bf; + newrectf[2] = val_gf + sample * diff_gf; + newrectf[3] = val_rf + sample * diff_rf; + newrectf += skipx; } + sample += add; } - if (do_rect) { - newrect[0] = val_a + sample * diff_a; - newrect[1] = val_b + sample * diff_b; - newrect[2] = val_g + sample * diff_g; - newrect[3] = val_r + sample * diff_r; - newrect += skipx; - } - if (do_float) { - newrectf[0] = val_af + sample * diff_af; - newrectf[1] = val_bf + sample * diff_bf; - newrectf[2] = val_gf + sample * diff_gf; - newrectf[3] = val_rf + sample * diff_rf; - newrectf += skipx; - } - sample += add; } } @@ -1620,6 +1666,8 @@ static void scalefast_Z_ImBuf(ImBuf *ibuf, int newx, int newy) */ bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy) { + BLI_assert_msg(newx > 0 && newy > 0, "Images must be at least 1 on both dimensions!"); + if (ibuf == NULL) { return false; } @@ -1666,6 +1714,8 @@ struct imbufRGBA { */ bool IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy) { + BLI_assert_msg(newx > 0 && newy > 0, "Images must be at least 1 on both dimensions!"); + unsigned int *rect, *_newrect, *newrect; struct imbufRGBA *rectf, *_newrectf, *newrectf; int x, y; @@ -1838,6 +1888,8 @@ static void *do_scale_thread(void *data_v) void IMB_scaleImBuf_threaded(ImBuf *ibuf, unsigned int newx, unsigned int newy) { + BLI_assert_msg(newx > 0 && newy > 0, "Images must be at least 1 on both dimensions!"); + ScaleTreadInitData init_data = {NULL}; /* prepare initialization data */ diff --git a/source/blender/io/gpencil/gpencil_io.h b/source/blender/io/gpencil/gpencil_io.h index 24b13479359..fab867b38b3 100644 --- a/source/blender/io/gpencil/gpencil_io.h +++ b/source/blender/io/gpencil/gpencil_io.h @@ -27,9 +27,9 @@ extern "C" { #endif struct ARegion; -struct bContext; struct Object; struct View3D; +struct bContext; typedef struct GpencilIOParams { bContext *C; diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.hh b/source/blender/io/gpencil/intern/gpencil_io_base.hh index c8d85d08f7b..02758883f19 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_base.hh +++ b/source/blender/io/gpencil/intern/gpencil_io_base.hh @@ -37,9 +37,9 @@ struct Object; struct RegionView3D; struct Scene; -struct bGPdata; struct bGPDlayer; struct bGPDstroke; +struct bGPdata; using blender::Vector; diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh b/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh index 0e9271dd2c6..99e8b1ed4fd 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh +++ b/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh @@ -24,10 +24,10 @@ #include "gpencil_io_import_base.hh" struct GpencilIOParams; -struct NSVGshape; struct NSVGpath; -struct bGPdata; +struct NSVGshape; struct bGPDframe; +struct bGPdata; #define SVG_IMPORTER_NAME "SVG Import for Grease Pencil" #define SVG_IMPORTER_VERSION "v1.0" diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 3732de6c0ec..520fc6c1b00 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -35,6 +35,7 @@ extern "C" { #define MAXTEXTBOX 256 /* used in readfile.c and editfont.c */ struct AnimData; +struct CurveEval; struct CurveProfile; struct EditFont; struct GHash; @@ -43,7 +44,6 @@ struct Key; struct Material; struct Object; struct VFont; -struct CurveEval; /* These two Lines with # tell makesdna this struct can be excluded. */ # diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 0952c45e81f..380d8ad1249 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -33,8 +33,8 @@ extern "C" { struct AnimData; struct Curve; -struct MDeformVert; struct Curve; +struct MDeformVert; #define GP_DEFAULT_PIX_FACTOR 1.0f #define GP_DEFAULT_GRID_LINES 4 diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index f6dac88051b..1b3dbd148df 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -647,7 +647,8 @@ .target = NULL, \ .verts = NULL, \ .falloff = 4.0f, \ - .numverts = 0, \ + .num_mesh_verts = 0, \ + .num_bind_verts = 0, \ .numpoly = 0, \ .flags = 0, \ .mat = _DNA_DEFAULT_UNIT_M4, \ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 1c765d19ce2..401b49f2ee8 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -2180,7 +2180,7 @@ typedef struct SDefBind { typedef struct SDefVert { SDefBind *binds; unsigned int numbinds; - char _pad[4]; + unsigned int vertex_idx; } SDefVert; typedef struct SurfaceDeformModifierData { @@ -2192,11 +2192,10 @@ typedef struct SurfaceDeformModifierData { /** Vertex bind data. */ SDefVert *verts; float falloff; - unsigned int numverts, numpoly; + unsigned int num_mesh_verts, num_bind_verts, numpoly; int flags; float mat[4][4]; float strength; - char _pad[4]; char defgrp_name[64]; } SurfaceDeformModifierData; @@ -2204,10 +2203,9 @@ typedef struct SurfaceDeformModifierData { enum { /* This indicates "do bind on next modifier evaluation" as well as "is bound". */ MOD_SDEF_BIND = (1 << 0), - MOD_SDEF_INVERT_VGROUP = (1 << 1) - - /* MOD_SDEF_USES_LOOPTRI = (1 << 1), */ /* UNUSED */ - /* MOD_SDEF_HAS_CONCAVE = (1 << 2), */ /* UNUSED */ + MOD_SDEF_INVERT_VGROUP = (1 << 1), + /* Only store bind data for nonzero vgroup weights at the time of bind. */ + MOD_SDEF_SPARSE_BIND = (1 << 2), }; /* Surface Deform vertex bind modes */ diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 1f75006bd07..e325a22a74d 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -37,6 +37,8 @@ struct Collection; struct ID; struct Image; struct ListBase; +struct Material; +struct Tex; struct bGPdata; struct bNodeInstanceHash; struct bNodeLink; @@ -44,8 +46,6 @@ struct bNodePreview; struct bNodeTreeExec; struct bNodeType; struct uiBlock; -struct Tex; -struct Material; #define NODE_MAXSTR 64 @@ -1390,6 +1390,11 @@ typedef struct NodeGeometryCurveSubdivide { uint8_t cuts_type; } NodeGeometryCurveSubdivide; +typedef struct NodeGeometryCurveTrim { + /* GeometryNodeCurveInterpolateMode. */ + uint8_t mode; +} NodeGeometryCurveTrim; + typedef struct NodeGeometryCurveToPoints { /* GeometryNodeCurveResampleMode. */ uint8_t mode; @@ -1954,6 +1959,11 @@ typedef enum GeometryNodeCurveSampleMode { GEO_NODE_CURVE_SAMPLE_LENGTH = 1, } GeometryNodeCurveSampleMode; +typedef enum GeometryNodeCurveInterpolateMode { + GEO_NODE_CURVE_INTERPOLATE_FACTOR = 0, + GEO_NODE_CURVE_INTERPOLATE_LENGTH = 1, +} GeometryNodeCurveInterpolateMode; + typedef enum GeometryNodeAttributeTransferMapMode { GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED = 0, GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST = 1, diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 7032bc23b2c..5bd9cc7a999 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -279,7 +279,7 @@ typedef struct uiListDyn { int resize; int resize_prev; - /* Allocated custom data. Free'ed together with the uiList (and when re-assigning). */ + /** Allocated custom data. Freed together with the #uiList (and when re-assigning). */ void *customdata; /* Filtering data. */ diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 1bd4c9233e3..55dc51e0632 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -43,9 +43,9 @@ extern "C" { struct Ipo; struct MovieClip; struct Scene; +struct SequenceLookup; struct VFont; struct bSound; -struct SequenceLookup; /* strlens; 256= FILE_MAXFILE, 768= FILE_MAXDIR */ diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h index 735be0c10bf..d363e40e4f0 100644 --- a/source/blender/makesdna/intern/dna_rename_defs.h +++ b/source/blender/makesdna/intern/dna_rename_defs.h @@ -136,4 +136,5 @@ DNA_STRUCT_RENAME_ELEM(wmWindow, global_area_map, global_areas) DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, line_types, edge_types) DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_flags, mask_switches) DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_mask, material_mask_bits) +DNA_STRUCT_RENAME_ELEM(SurfaceDeformModifierData, numverts, num_bind_verts) DNA_STRUCT_RENAME_ELEM(MaterialLineArt, transparency_mask, material_mask_bits) diff --git a/source/blender/makesrna/intern/rna_asset.c b/source/blender/makesrna/intern/rna_asset.c index 497f4f37ea3..0020d90ba1a 100644 --- a/source/blender/makesrna/intern/rna_asset.c +++ b/source/blender/makesrna/intern/rna_asset.c @@ -137,7 +137,7 @@ static void rna_AssetHandle_get_full_library_path( bContext *C, FileDirEntry *asset_file, AssetLibraryReference *library, - char r_result[FILE_MAX_LIBEXTRA]) + char r_result[/*FILE_MAX_LIBEXTRA*/]) { AssetHandle asset = {.file_data = asset_file}; ED_asset_handle_get_full_library_path(C, library, &asset, r_result); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index e64eaf8c363..5fddb0f18a5 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -6884,6 +6884,15 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "use_sparse_bind", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SDEF_SPARSE_BIND); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text( + prop, + "Sparse Bind", + "Only record binding data for vertices matching the vertex group at the time of bind"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, -100, 100); RNA_def_property_ui_range(prop, -100, 100, 10, 2); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 198ee107231..ce2c777b782 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -10065,6 +10065,32 @@ static void def_geo_curve_to_points(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_curve_trim(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem mode_items[] = { + {GEO_NODE_CURVE_INTERPOLATE_FACTOR, + "FACTOR", + 0, + "Factor", + "Find the endpoint positions using a factor of each spline's length"}, + {GEO_NODE_CURVE_INTERPOLATE_LENGTH, + "LENGTH", + 0, + "Length", + "Find the endpoint positions using a length from the start of each spline"}, + {0, NULL, 0, NULL, NULL}, + }; + + RNA_def_struct_sdna_from(srna, "NodeGeometryCurveTrim", "storage"); + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", "How to find endpoint positions for the trimmed spline"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + static void def_geo_attribute_transfer(StructRNA *srna) { static EnumPropertyItem mapping_items[] = { diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index e110459eeea..ed681291e29 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1997,16 +1997,25 @@ static void rna_Object_boundbox_get(PointerRNA *ptr, float *values) } } +static bool check_object_vgroup_support_and_warn(const Object *ob, + const char *op_name, + ReportList *reports) +{ + if (!BKE_object_supports_vertex_groups(ob)) { + const char *ob_type_name = "Unknown"; + RNA_enum_name_from_value(rna_enum_object_type_items, ob->type, &ob_type_name); + BKE_reportf(reports, RPT_ERROR, "%s is not supported for '%s' objects", op_name, ob_type_name); + return false; + } + return true; +} + static bDeformGroup *rna_Object_vgroup_new(Object *ob, Main *bmain, ReportList *reports, const char *name) { - if (!OB_TYPE_SUPPORT_VGROUP(ob->type)) { - const char *ob_type_name = "Unknown"; - RNA_enum_name_from_value(rna_enum_object_type_items, ob->type, &ob_type_name); - BKE_reportf( - reports, RPT_ERROR, "VertexGroups.new(): is not supported for '%s' objects", ob_type_name); + if (!check_object_vgroup_support_and_warn(ob, "VertexGroups.new()", reports)) { return NULL; } @@ -2023,6 +2032,10 @@ static void rna_Object_vgroup_remove(Object *ob, ReportList *reports, PointerRNA *defgroup_ptr) { + if (!check_object_vgroup_support_and_warn(ob, "VertexGroups.remove()", reports)) { + return; + } + bDeformGroup *defgroup = defgroup_ptr->data; ListBase *defbase = BKE_object_defgroup_list_mutable(ob); @@ -2042,8 +2055,12 @@ static void rna_Object_vgroup_remove(Object *ob, WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob); } -static void rna_Object_vgroup_clear(Object *ob, Main *bmain) +static void rna_Object_vgroup_clear(Object *ob, Main *bmain, ReportList *reports) { + if (!check_object_vgroup_support_and_warn(ob, "VertexGroups.clear()", reports)) { + return; + } + BKE_object_defgroup_remove_all(ob); DEG_relations_tag_update(bmain); @@ -2777,7 +2794,7 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); func = RNA_def_function(srna, "clear", "rna_Object_vgroup_clear"); - RNA_def_function_flag(func, FUNC_USE_MAIN); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Delete all vertex groups from object"); } diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 8aab0c079a3..057f49c0319 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -30,6 +30,8 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "SEQ_edit.h" + #include "rna_internal.h" #ifdef RNA_RUNTIME @@ -99,6 +101,24 @@ static void rna_Sequences_move_strip_to_meta( WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); } +static Sequence *rna_Sequence_split( + ID *id, Sequence *seq, Main *bmain, int frame, int split_method) +{ + Scene *scene = (Scene *)id; + Editing *ed = SEQ_editing_get(scene, false); + ListBase *seqbase = SEQ_get_seqbase_by_seq(&ed->seqbase, seq); + + Sequence *r_seq = SEQ_edit_strip_split(bmain, scene, seqbase, seq, frame, split_method); + + /* Update depsgraph. */ + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); + + WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); + + return r_seq; +} + static Sequence *rna_Sequences_new_clip(ID *id, ListBase *seqbase, Main *bmain, @@ -635,6 +655,12 @@ void RNA_api_sequence_strip(StructRNA *srna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem seq_split_method_items[] = { + {SEQ_SPLIT_SOFT, "SOFT", 0, "Soft", ""}, + {SEQ_SPLIT_HARD, "HARD", 0, "Hard", ""}, + {0, NULL, 0, NULL, NULL}, + }; + func = RNA_def_function(srna, "update", "rna_Sequence_update_rnafunc"); RNA_def_function_flag(func, FUNC_USE_SELF_ID); RNA_def_function_ui_description(func, "Update the strip dimensions"); @@ -676,6 +702,18 @@ void RNA_api_sequence_strip(StructRNA *srna) "Invalidate cached images for strip and all dependent strips"); parm = RNA_def_enum(func, "type", seq_cahce_type_items, 0, "Type", "Cache Type"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + + func = RNA_def_function(srna, "split", "rna_Sequence_split"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); + RNA_def_function_ui_description(func, "Split Sequence"); + parm = RNA_def_int( + func, "frame", 0, INT_MIN, INT_MAX, "", "Frame where to split the strip", INT_MIN, INT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_enum(func, "split_method", seq_split_method_items, 0, "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + /* Retirn type. */ + parm = RNA_def_pointer(func, "sequence", "Sequence", "", "Right side Sequence"); + RNA_def_function_return(func, parm); } void RNA_api_sequence_elements(BlenderRNA *brna, PropertyRNA *cprop) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 0019f315bbe..f2d2b190d87 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2699,7 +2699,7 @@ static const EnumPropertyItem *rna_FileBrowser_FileSelectEntry_id_type_itemf( { const FileDirEntry *entry = ptr->data; if (entry->blentype == 0) { - const static EnumPropertyItem none_items[] = { + static const EnumPropertyItem none_items[] = { {0, "NONE", 0, "None", ""}, }; return none_items; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index fd1c0b7951a..d29a90a1886 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -1100,7 +1100,7 @@ int rna_show_statusbar_vram_editable(struct PointerRNA *UNUSED(ptr), const char static size_t max_memory_in_megabytes(void) { /* Maximum addressable bytes on this platform. */ - const size_t limit_bytes = (((size_t)1) << ((sizeof(size_t[8])) - 1)); + const size_t limit_bytes = (((size_t)1) << (sizeof(size_t[8]) - 1)); /* Convert it to megabytes and return. */ return (limit_bytes >> 20); } diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index dd011a293ee..ec6de8f8387 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -94,6 +94,11 @@ typedef struct SDefBindCalcData { float imat[4][4]; const float falloff; int success; + /** Vertex group lookup data. */ + const MDeformVert *const dvert; + int const defgrp_index; + bool const invert_vgroup; + bool const sparse_bind; } SDefBindCalcData; /** @@ -218,7 +223,7 @@ static void freeData(ModifierData *md) SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; if (smd->verts) { - for (int i = 0; i < smd->numverts; i++) { + for (int i = 0; i < smd->num_bind_verts; i++) { if (smd->verts[i].binds) { for (int j = 0; j < smd->verts[i].numbinds; j++) { MEM_SAFE_FREE(smd->verts[i].binds[j].vert_inds); @@ -243,7 +248,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla if (smd->verts) { tsmd->verts = MEM_dupallocN(smd->verts); - for (int i = 0; i < smd->numverts; i++) { + for (int i = 0; i < smd->num_bind_verts; i++) { if (smd->verts[i].binds) { tsmd->verts[i].binds = MEM_dupallocN(smd->verts[i].binds); @@ -963,12 +968,32 @@ static void bindVert(void *__restrict userdata, SDefBindPoly *bpoly; SDefBind *sdbind; + sdvert->vertex_idx = index; + if (data->success != MOD_SDEF_BIND_RESULT_SUCCESS) { sdvert->binds = NULL; sdvert->numbinds = 0; return; } + if (data->sparse_bind) { + float weight = 0.0f; + + if (data->dvert && data->defgrp_index != -1) { + weight = BKE_defvert_find_weight(&data->dvert[index], data->defgrp_index); + } + + if (data->invert_vgroup) { + weight = 1.0f - weight; + } + + if (weight <= 0) { + sdvert->binds = NULL; + sdvert->numbinds = 0; + return; + } + } + copy_v3_v3(point_co, data->vertexCos[index]); bwdata = computeBindWeights(data, point_co); @@ -1135,6 +1160,21 @@ static void bindVert(void *__restrict userdata, freeBindData(bwdata); } +/* Remove vertices without bind data from the bind array. */ +static void compactSparseBinds(SurfaceDeformModifierData *smd) +{ + smd->num_bind_verts = 0; + + for (uint i = 0; i < smd->num_mesh_verts; i++) { + if (smd->verts[i].numbinds > 0) { + smd->verts[smd->num_bind_verts++] = smd->verts[i]; + } + } + + smd->verts = MEM_reallocN_id( + smd->verts, sizeof(*smd->verts) * smd->num_bind_verts, "SDefBindVerts (sparse)"); +} + static bool surfacedeformBind(Object *ob, SurfaceDeformModifierData *smd_orig, SurfaceDeformModifierData *smd_eval, @@ -1142,7 +1182,8 @@ static bool surfacedeformBind(Object *ob, uint numverts, uint tnumpoly, uint tnumverts, - Mesh *target) + Mesh *target, + Mesh *mesh) { BVHTreeFromMesh treeData = {NULL}; const MVert *mvert = target->mvert; @@ -1205,9 +1246,15 @@ static bool surfacedeformBind(Object *ob, return false; } - smd_orig->numverts = numverts; + smd_orig->num_mesh_verts = numverts; smd_orig->numpoly = tnumpoly; + int defgrp_index; + MDeformVert *dvert; + MOD_get_vgroup(ob, mesh, smd_orig->defgrp_name, &dvert, &defgrp_index); + const bool invert_vgroup = (smd_orig->flags & MOD_SDEF_INVERT_VGROUP) != 0; + const bool sparse_bind = (smd_orig->flags & MOD_SDEF_SPARSE_BIND) != 0; + SDefBindCalcData data = { .treeData = &treeData, .vert_edges = vert_edges, @@ -1221,6 +1268,10 @@ static bool surfacedeformBind(Object *ob, .vertexCos = vertexCos, .falloff = smd_orig->falloff, .success = MOD_SDEF_BIND_RESULT_SUCCESS, + .dvert = dvert, + .defgrp_index = defgrp_index, + .invert_vgroup = invert_vgroup, + .sparse_bind = sparse_bind, }; if (data.targetCos == NULL) { @@ -1242,6 +1293,13 @@ static bool surfacedeformBind(Object *ob, MEM_freeN(data.targetCos); + if (sparse_bind) { + compactSparseBinds(smd_orig); + } + else { + smd_orig->num_bind_verts = numverts; + } + if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) { BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeData((ModifierData *)smd_orig); @@ -1267,6 +1325,11 @@ static bool surfacedeformBind(Object *ob, BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains invalid polygons"); freeData((ModifierData *)smd_orig); } + else if (smd_orig->num_bind_verts == 0 || !smd_orig->verts) { + data.success = MOD_SDEF_BIND_RESULT_GENERIC_ERR; + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "No vertices were bound"); + freeData((ModifierData *)smd_orig); + } freeAdjacencyMap(vert_edges, adj_array, edge_polys); free_bvhtree_from_mesh(&treeData); @@ -1281,14 +1344,15 @@ static void deformVert(void *__restrict userdata, const SDefDeformData *const data = (SDefDeformData *)userdata; const SDefBind *sdbind = data->bind_verts[index].binds; const int num_binds = data->bind_verts[index].numbinds; - float *const vertexCos = data->vertexCos[index]; + const unsigned int vertex_idx = data->bind_verts[index].vertex_idx; + float *const vertexCos = data->vertexCos[vertex_idx]; float norm[3], temp[3], offset[3]; /* Retrieve the value of the weight vertex group if specified. */ float weight = 1.0f; if (data->dvert && data->defgrp_index != -1) { - weight = BKE_defvert_find_weight(&data->dvert[index], data->defgrp_index); + weight = BKE_defvert_find_weight(&data->dvert[vertex_idx], data->defgrp_index); if (data->invert_vgroup) { weight = 1.0f - weight; @@ -1423,7 +1487,8 @@ static void surfacedeformModifier_do(ModifierData *md, /* Avoid converting edit-mesh data, binding is an exception. */ BKE_mesh_wrapper_ensure_mdata(target); - if (!surfacedeformBind(ob, smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target)) { + if (!surfacedeformBind( + ob, smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target, mesh)) { smd->flags &= ~MOD_SDEF_BIND; } /* Early abort, this is binding 'call', no need to perform whole evaluation. */ @@ -1431,8 +1496,9 @@ static void surfacedeformModifier_do(ModifierData *md, } /* Poly count checks */ - if (smd->numverts != numverts) { - BKE_modifier_set_error(ob, md, "Vertices changed from %u to %u", smd->numverts, numverts); + if (smd->num_mesh_verts != numverts) { + BKE_modifier_set_error( + ob, md, "Vertices changed from %u to %u", smd->num_mesh_verts, numverts); return; } if (smd->numpoly != tnumpoly) { @@ -1468,8 +1534,8 @@ static void surfacedeformModifier_do(ModifierData *md, TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (numverts > 10000); - BLI_task_parallel_range(0, numverts, &data, deformVert, &settings); + settings.use_threading = (smd->num_bind_verts > 10000); + BLI_task_parallel_range(0, smd->num_bind_verts, &data, deformVert, &settings); MEM_freeN(data.targetCos); } @@ -1554,6 +1620,11 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL); + col = uiLayoutColumn(layout, false); + uiLayoutSetEnabled(col, !is_bound); + uiLayoutSetActive(col, !is_bound && RNA_string_length(ptr, "vertex_group") != 0); + uiItemR(col, ptr, "use_sparse_bind", 0, NULL, ICON_NONE); + uiItemS(layout); col = uiLayoutColumn(layout, false); @@ -1576,10 +1647,10 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md) { const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md; - BLO_write_struct_array(writer, SDefVert, smd->numverts, smd->verts); + BLO_write_struct_array(writer, SDefVert, smd->num_bind_verts, smd->verts); if (smd->verts) { - for (int i = 0; i < smd->numverts; i++) { + for (int i = 0; i < smd->num_bind_verts; i++) { BLO_write_struct_array(writer, SDefBind, smd->verts[i].numbinds, smd->verts[i].binds); if (smd->verts[i].binds) { @@ -1607,7 +1678,7 @@ static void blendRead(BlendDataReader *reader, ModifierData *md) BLO_read_data_address(reader, &smd->verts); if (smd->verts) { - for (int i = 0; i < smd->numverts; i++) { + for (int i = 0; i < smd->num_bind_verts; i++) { BLO_read_data_address(reader, &smd->verts[i].binds); if (smd->verts[i].binds) { diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index e9ce823967e..974cbf95af0 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -179,6 +179,7 @@ set(SRC geometry/nodes/node_geo_curve_subdivide.cc geometry/nodes/node_geo_curve_to_mesh.cc geometry/nodes/node_geo_curve_to_points.cc + geometry/nodes/node_geo_curve_trim.cc geometry/nodes/node_geo_delete_geometry.cc geometry/nodes/node_geo_edge_split.cc geometry/nodes/node_geo_input_material.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 73e711eb401..b8d8f120e91 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -66,6 +66,7 @@ void register_node_type_geo_curve_reverse(void); void register_node_type_geo_curve_subdivide(void); void register_node_type_geo_curve_to_mesh(void); void register_node_type_geo_curve_to_points(void); +void register_node_type_geo_curve_trim(void); void register_node_type_geo_delete_geometry(void); void register_node_type_geo_edge_split(void); void register_node_type_geo_input_material(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index c24763baa1e..dd158cdaf75 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -303,6 +303,7 @@ DefNode(GeometryNode, GEO_NODE_CURVE_RESAMPLE, def_geo_curve_resample, "CURVE_RE DefNode(GeometryNode, GEO_NODE_CURVE_SAMPLE, def_geo_curve_sample, "CURVE_SAMPLE", CurveSample, "Curve Sample", "") DefNode(GeometryNode, GEO_NODE_CURVE_SUBDIVIDE, def_geo_curve_subdivide, "CURVE_SUBDIVIDE", CurveSubdivide, "Curve Subdivide", "") DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, "Curve to Mesh", "") +DefNode(GeometryNode, GEO_NODE_CURVE_TRIM, def_geo_curve_trim, "CURVE_TRIM", CurveTrim, "Curve Trim", "") DefNode(GeometryNode, GEO_NODE_CURVE_REVERSE, 0, "CURVE_REVERSE", CurveReverse, "Curve Reverse", "") DefNode(GeometryNode, GEO_NODE_CURVE_TO_POINTS, def_geo_curve_to_points, "CURVE_TO_POINTS", CurveToPoints, "Curve to Points", "") DefNode(GeometryNode, GEO_NODE_CURVE_ENDPOINTS, 0, "CURVE_ENDPOINTS", CurveEndpoints, "Curve Endpoints", "") diff --git a/source/blender/nodes/composite/nodes/node_composite_antialiasing.c b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c index 7437496d878..fa276e9a794 100644 --- a/source/blender/nodes/composite/nodes/node_composite_antialiasing.c +++ b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c @@ -42,9 +42,9 @@ static void node_composit_init_antialiasing(bNodeTree *UNUSED(ntree), bNode *nod { NodeAntiAliasingData *data = MEM_callocN(sizeof(NodeAntiAliasingData), "node antialiasing data"); - data->threshold = 1.0f; - data->contrast_limit = 0.2f; - data->corner_rounding = 0.25f; + data->threshold = CMP_DEFAULT_SMAA_THRESHOLD; + data->contrast_limit = CMP_DEFAULT_SMAA_CONTRAST_LIMIT; + data->corner_rounding = CMP_DEFAULT_SMAA_CORNER_ROUNDING; node->storage = data; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc new file mode 100644 index 00000000000..f7aecf72303 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc @@ -0,0 +1,408 @@ +/* + * 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. + */ + +#include "BKE_spline.hh" +#include "BLI_task.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_geometry_util.hh" + +using blender::attribute_math::mix2; + +static bNodeSocketTemplate geo_node_curve_trim_in[] = { + {SOCK_GEOMETRY, N_("Curve")}, + {SOCK_FLOAT, N_("Start"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + {SOCK_FLOAT, N_("End"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, + {SOCK_FLOAT, N_("Start"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10000.0f, PROP_DISTANCE}, + {SOCK_FLOAT, N_("End"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 10000.0f, PROP_DISTANCE}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_curve_trim_out[] = { + {SOCK_GEOMETRY, N_("Curve")}, + {-1, ""}, +}; + +static void geo_node_curve_trim_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); +} + +static void geo_node_curve_trim_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometryCurveTrim *data = (NodeGeometryCurveTrim *)MEM_callocN(sizeof(NodeGeometryCurveTrim), + __func__); + + data->mode = GEO_NODE_CURVE_INTERPOLATE_FACTOR; + node->storage = data; +} + +static void geo_node_curve_trim_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + const NodeGeometryCurveTrim &node_storage = *(NodeGeometryCurveTrim *)node->storage; + const GeometryNodeCurveInterpolateMode mode = (GeometryNodeCurveInterpolateMode) + node_storage.mode; + + bNodeSocket *start_fac = ((bNodeSocket *)node->inputs.first)->next; + bNodeSocket *end_fac = start_fac->next; + bNodeSocket *start_len = end_fac->next; + bNodeSocket *end_len = start_len->next; + + nodeSetSocketAvailability(start_fac, mode == GEO_NODE_CURVE_INTERPOLATE_FACTOR); + nodeSetSocketAvailability(end_fac, mode == GEO_NODE_CURVE_INTERPOLATE_FACTOR); + nodeSetSocketAvailability(start_len, mode == GEO_NODE_CURVE_INTERPOLATE_LENGTH); + nodeSetSocketAvailability(end_len, mode == GEO_NODE_CURVE_INTERPOLATE_LENGTH); +} + +namespace blender::nodes { + +struct TrimLocation { + /* Control point index at the start side of the trim location. */ + int left_index; + /* Control point intex at the end of the trim location's segment. */ + int right_index; + /* The factor between the left and right indices. */ + float factor; +}; + +template<typename T> +static void shift_slice_to_start(MutableSpan<T> data, const int start_index, const int size) +{ + BLI_assert(start_index + size - 1 <= data.size()); + memmove(data.data(), &data[start_index], sizeof(T) * size); +} + +/* Shift slice to start of span and modifies start and end data. */ +template<typename T> +static void linear_trim_data(const TrimLocation &start, + const TrimLocation &end, + MutableSpan<T> data) +{ + const int size = end.right_index - start.left_index + 1; + + if (start.left_index > 0) { + shift_slice_to_start<T>(data, start.left_index, size); + } + + const T start_data = mix2<T>(start.factor, data.first(), data[1]); + const T end_data = mix2<T>(end.factor, data[size - 2], data[size - 1]); + + data.first() = start_data; + data[size - 1] = end_data; +} + +/* Identical operation as #linear_trim_data, but opy data to a new MutableSpan rather than + * modifying the original data. */ +template<typename T> +static void linear_trim_to_output_data(const TrimLocation &start, + const TrimLocation &end, + Span<T> src, + MutableSpan<T> dst) +{ + const int size = end.right_index - start.left_index + 1; + + const T start_data = mix2<T>(start.factor, src[start.left_index], src[start.right_index]); + const T end_data = mix2<T>(end.factor, src[end.left_index], src[end.right_index]); + + dst.copy_from(src.slice(start.left_index, size)); + dst.first() = start_data; + dst.last() = end_data; +} + +/* Look up the control points to the left and right of factor, and get the factor between them. */ +static TrimLocation lookup_control_point_position(const Spline::LookupResult &lookup, + Span<int> control_point_offsets) +{ + const int *left_offset = std::lower_bound( + control_point_offsets.begin(), control_point_offsets.end(), lookup.evaluated_index); + const int index = left_offset - control_point_offsets.begin(); + const int left = control_point_offsets[index] > lookup.evaluated_index ? index - 1 : index; + const int right = left + 1; + + const float factor = std::clamp( + (lookup.evaluated_index + lookup.factor - control_point_offsets[left]) / + (control_point_offsets[right] - control_point_offsets[left]), + 0.0f, + 1.0f); + + return {left, right, factor}; +} + +static void trim_poly_spline(Spline &spline, + const Spline::LookupResult &start_lookup, + const Spline::LookupResult &end_lookup) +{ + /* Poly splines have a 1 to 1 mapping between control points and evaluated points. */ + const TrimLocation start = { + start_lookup.evaluated_index, start_lookup.next_evaluated_index, start_lookup.factor}; + const TrimLocation end = { + end_lookup.evaluated_index, end_lookup.next_evaluated_index, end_lookup.factor}; + + const int size = end.right_index - start.left_index + 1; + + linear_trim_data<float3>(start, end, spline.positions()); + linear_trim_data<float>(start, end, spline.radii()); + linear_trim_data<float>(start, end, spline.tilts()); + + spline.attributes.foreach_attribute( + [&](StringRefNull name, const AttributeMetaData &UNUSED(meta_data)) { + std::optional<GMutableSpan> src = spline.attributes.get_for_write(name); + BLI_assert(src); + attribute_math::convert_to_static_type(src->type(), [&](auto dummy) { + using T = decltype(dummy); + linear_trim_data<T>(start, end, src->typed<T>()); + }); + return true; + }, + ATTR_DOMAIN_POINT); + + spline.resize(size); +} + +/** + * Trim NURB splines by converting to a poly spline. + */ +static PolySpline trim_nurbs_spline(const Spline &spline, + const Spline::LookupResult &start_lookup, + const Spline::LookupResult &end_lookup) +{ + /* Since this outputs a poly spline, the evaluated indices are the control point indices. */ + const TrimLocation start = { + start_lookup.evaluated_index, start_lookup.next_evaluated_index, start_lookup.factor}; + const TrimLocation end = { + end_lookup.evaluated_index, end_lookup.next_evaluated_index, end_lookup.factor}; + + const int size = end.right_index - start.left_index + 1; + + /* Create poly spline and copy trimmed data to it. */ + PolySpline new_spline; + new_spline.resize(size); + + /* Copy generic attribute data. */ + spline.attributes.foreach_attribute( + [&](StringRefNull name, const AttributeMetaData &meta_data) { + std::optional<GSpan> src = spline.attributes.get_for_read(name); + BLI_assert(src); + if (!new_spline.attributes.create(name, meta_data.data_type)) { + BLI_assert_unreachable(); + return false; + } + std::optional<GMutableSpan> dst = new_spline.attributes.get_for_write(name); + BLI_assert(dst); + + attribute_math::convert_to_static_type(src->type(), [&](auto dummy) { + using T = decltype(dummy); + GVArray_Typed<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>()); + linear_trim_to_output_data<T>( + start, end, eval_data->get_internal_span(), dst->typed<T>()); + }); + return true; + }, + ATTR_DOMAIN_POINT); + + linear_trim_to_output_data<float3>( + start, end, spline.evaluated_positions(), new_spline.positions()); + + GVArray_Typed<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii()); + linear_trim_to_output_data<float>( + start, end, evaluated_radii->get_internal_span(), new_spline.radii()); + + GVArray_Typed<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts()); + linear_trim_to_output_data<float>( + start, end, evaluated_tilts->get_internal_span(), new_spline.tilts()); + + return new_spline; +} + +/** + * Trim Bezier splines by adjusting the first and last handles + * and control points to maintain the original shape. + */ +static void trim_bezier_spline(Spline &spline, + const Spline::LookupResult &start_lookup, + const Spline::LookupResult &end_lookup) +{ + BezierSpline &bezier_spline = static_cast<BezierSpline &>(spline); + Span<int> control_offsets = bezier_spline.control_point_offsets(); + + const TrimLocation start = lookup_control_point_position(start_lookup, control_offsets); + TrimLocation end = lookup_control_point_position(end_lookup, control_offsets); + + /* The number of control points in the resulting spline. */ + const int size = end.right_index - start.left_index + 1; + + /* Trim the spline attributes. Done before end.factor recalculation as it needs + * the original end.factor value. */ + linear_trim_data<float>(start, end, bezier_spline.radii()); + linear_trim_data<float>(start, end, bezier_spline.tilts()); + spline.attributes.foreach_attribute( + [&](StringRefNull name, const AttributeMetaData &UNUSED(meta_data)) { + std::optional<GMutableSpan> src = spline.attributes.get_for_write(name); + BLI_assert(src); + attribute_math::convert_to_static_type(src->type(), [&](auto dummy) { + using T = decltype(dummy); + linear_trim_data<T>(start, end, src->typed<T>()); + }); + return true; + }, + ATTR_DOMAIN_POINT); + + /* Recalculate end.factor if the size is two, because the adjustment in the + * position of the control point of the spline to the left of the new end point will change the + * factor between them. */ + if (size == 2) { + if (start_lookup.factor == 1.0f) { + end.factor = 0.0f; + } + else { + end.factor = (end_lookup.evaluated_index + end_lookup.factor - + (start_lookup.evaluated_index + start_lookup.factor)) / + (control_offsets[end.right_index] - + (start_lookup.evaluated_index + start_lookup.factor)); + end.factor = std::clamp(end.factor, 0.0f, 1.0f); + } + } + + BezierSpline::InsertResult start_point = bezier_spline.calculate_segment_insertion( + start.left_index, start.right_index, start.factor); + + /* Update the start control point parameters so they are used calculating the new end point. */ + bezier_spline.positions()[start.left_index] = start_point.position; + bezier_spline.handle_positions_right()[start.left_index] = start_point.right_handle; + bezier_spline.handle_positions_left()[start.right_index] = start_point.handle_next; + + const BezierSpline::InsertResult end_point = bezier_spline.calculate_segment_insertion( + end.left_index, end.right_index, end.factor); + + /* If size is two, then the start point right handle needs to change to reflect the end point + * previous handle update. */ + if (size == 2) { + start_point.right_handle = end_point.handle_prev; + } + + /* Shift control point position data to start at beginning of array. */ + if (start.left_index > 0) { + shift_slice_to_start(bezier_spline.positions(), start.left_index, size); + shift_slice_to_start(bezier_spline.handle_positions_left(), start.left_index, size); + shift_slice_to_start(bezier_spline.handle_positions_right(), start.left_index, size); + } + + bezier_spline.positions().first() = start_point.position; + bezier_spline.positions()[size - 1] = end_point.position; + + bezier_spline.handle_positions_left().first() = start_point.left_handle; + bezier_spline.handle_positions_left()[size - 1] = end_point.left_handle; + + bezier_spline.handle_positions_right().first() = start_point.right_handle; + bezier_spline.handle_positions_right()[size - 1] = end_point.right_handle; + + /* If there is at least one control point between the endpoints, update the control + * point handle to the right of the start point and to the left of the end point. */ + if (size > 2) { + bezier_spline.handle_positions_left()[start.right_index - start.left_index] = + start_point.handle_next; + bezier_spline.handle_positions_right()[end.left_index - start.left_index] = + end_point.handle_prev; + } + + bezier_spline.resize(size); +} + +static void geo_node_curve_trim_exec(GeoNodeExecParams params) +{ + const NodeGeometryCurveTrim &node_storage = *(NodeGeometryCurveTrim *)params.node().storage; + const GeometryNodeCurveInterpolateMode mode = (GeometryNodeCurveInterpolateMode) + node_storage.mode; + + GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve"); + geometry_set = bke::geometry_set_realize_instances(geometry_set); + if (!geometry_set.has_curve()) { + params.set_output("Curve", std::move(geometry_set)); + return; + } + + CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>(); + CurveEval &curve = *curve_component.get_for_write(); + MutableSpan<SplinePtr> splines = curve.splines(); + + const float start = mode == GEO_NODE_CURVE_INTERPOLATE_FACTOR ? + params.extract_input<float>("Start") : + params.extract_input<float>("Start_001"); + const float end = mode == GEO_NODE_CURVE_INTERPOLATE_FACTOR ? + params.extract_input<float>("End") : + params.extract_input<float>("End_001"); + + threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { + for (const int i : range) { + Spline &spline = *splines[i]; + + /* Currently this node doesn't support cyclic splines, it could in the future though. */ + if (spline.is_cyclic()) { + continue; + } + + /* Return a spline with one point instead of implicitly + * reversing the sline or switching the parameters. */ + if (end < start) { + spline.resize(1); + continue; + } + + const Spline::LookupResult start_lookup = + (mode == GEO_NODE_CURVE_INTERPOLATE_LENGTH) ? + spline.lookup_evaluated_length(std::clamp(start, 0.0f, spline.length())) : + spline.lookup_evaluated_factor(std::clamp(start, 0.0f, 1.0f)); + const Spline::LookupResult end_lookup = + (mode == GEO_NODE_CURVE_INTERPOLATE_LENGTH) ? + spline.lookup_evaluated_length(std::clamp(end, 0.0f, spline.length())) : + spline.lookup_evaluated_factor(std::clamp(end, 0.0f, 1.0f)); + + switch (spline.type()) { + case Spline::Type::Bezier: + trim_bezier_spline(spline, start_lookup, end_lookup); + break; + case Spline::Type::Poly: + trim_poly_spline(spline, start_lookup, end_lookup); + break; + case Spline::Type::NURBS: + splines[i] = std::make_unique<PolySpline>( + trim_nurbs_spline(spline, start_lookup, end_lookup)); + break; + } + splines[i]->mark_cache_invalid(); + } + }); + + params.set_output("Curve", std::move(geometry_set)); +} + +} // namespace blender::nodes + +void register_node_type_geo_curve_trim() +{ + static bNodeType ntype; + geo_node_type_base(&ntype, GEO_NODE_CURVE_TRIM, "Curve Trim", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, geo_node_curve_trim_in, geo_node_curve_trim_out); + ntype.geometry_node_execute = blender::nodes::geo_node_curve_trim_exec; + ntype.draw_buttons = geo_node_curve_trim_layout; + node_type_storage( + &ntype, "NodeGeometryCurveTrim", node_free_standard_storage, node_copy_standard_storage); + node_type_init(&ntype, geo_node_curve_trim_init); + node_type_update(&ntype, geo_node_curve_trim_update); + nodeRegisterType(&ntype); +} diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 90f54c50a6d..84d804f8bdf 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -20,8 +20,8 @@ #pragma once -struct AnimationEvalContext; struct ARegionType; +struct AnimationEvalContext; struct ChannelDriver; /* DNA_anim_types.h */ struct ID; /* DNA_ID.h */ struct ListBase; /* DNA_listBase.h */ diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c index 3d5aabcfda9..24887b24eb6 100644 --- a/source/blender/python/bmesh/bmesh_py_ops_call.c +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -608,7 +608,7 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot) /* keep switch in same order as above */ switch (slot->slot_type) { case BMO_OP_SLOT_BOOL: - item = PyBool_FromLong((BMO_SLOT_AS_BOOL(slot))); + item = PyBool_FromLong(BMO_SLOT_AS_BOOL(slot)); break; case BMO_OP_SLOT_INT: item = PyLong_FromLong(BMO_SLOT_AS_INT(slot)); diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index c1e28182c53..1c3334f1adc 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -189,7 +189,7 @@ static PyObject *bpy_bm_utils_vert_dissolve(PyObject *UNUSED(self), PyObject *ar bm = py_vert->bm; - return PyBool_FromLong((BM_vert_dissolve(bm, py_vert->v))); + return PyBool_FromLong(BM_vert_dissolve(bm, py_vert->v)); } PyDoc_STRVAR(bpy_bm_utils_vert_splice_doc, diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index 8dc5a6c629c..d66643c5d61 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -283,7 +283,7 @@ void BPY_app_handlers_reset(const short do_all) for (i = PyList_GET_SIZE(ls) - 1; i >= 0; i--) { - if ((PyFunction_Check((item = PyList_GET_ITEM(ls, i)))) && + if (PyFunction_Check((item = PyList_GET_ITEM(ls, i))) && (dict_ptr = _PyObject_GetDictPtr(item)) && (*dict_ptr) && (PyDict_GetItem(*dict_ptr, perm_id_str) != NULL)) { /* keep */ diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 14e25e02d84..f332d547965 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -1779,7 +1779,7 @@ static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, item = seq_fast_items[i]; - if ((PyTuple_CheckExact(item)) && (item_size = PyTuple_GET_SIZE(item)) && + if (PyTuple_CheckExact(item) && (item_size = PyTuple_GET_SIZE(item)) && (item_size >= 3 && item_size <= 5) && (tmp.identifier = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) && (tmp.name = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) && diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index dc98e3313c9..8b8130f3cc2 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -2998,7 +2998,7 @@ static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNU return -1; } - if ((mathutils_array_parse(tvec, 3, 3, value, "Matrix.translation")) == -1) { + if (mathutils_array_parse(tvec, 3, 3, value, "Matrix.translation") == -1) { return -1; } diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index 88b3bddddf6..a2dfaf501d6 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -1505,6 +1505,9 @@ static PyObject *list_of_lists_from_arrays(const int *array, PyObject *ret, *sublist; int i, j, sublist_len, sublist_start, val; + if (array == NULL) { + return PyList_New(0); + } ret = PyList_New(toplevel_len); for (i = 0; i < toplevel_len; i++) { sublist_len = len_table[i]; @@ -1521,7 +1524,7 @@ static PyObject *list_of_lists_from_arrays(const int *array, PyDoc_STRVAR( M_Geometry_delaunay_2d_cdt_doc, - ".. function:: delaunay_2d_cdt(vert_coords, edges, faces, output_type, epsilon)\n" + ".. function:: delaunay_2d_cdt(vert_coords, edges, faces, output_type, epsilon [,need_ids])\n" "\n" " Computes the Constrained Delaunay Triangulation of a set of vertices,\n" " with edges and faces that must appear in the triangulation.\n" @@ -1533,6 +1536,8 @@ PyDoc_STRVAR( " input element indices corresponding to the positionally same output element.\n" " For edges, the orig indices start with the input edges and then continue\n" " with the edges implied by each of the faces (n of them for an n-gon).\n" + " If the need_ids argument is supplied, and False, then the code skips the preparation\n" + " of the orig arrays, which may save some time." "\n" " :arg vert_coords: Vertex coordinates (2d)\n" " :type vert_coords: list of :class:`mathutils.Vector`\n" @@ -1543,10 +1548,14 @@ PyDoc_STRVAR( " :arg output_type: What output looks like. 0 => triangles with convex hull. " "1 => triangles inside constraints. " "2 => the input constraints, intersected. " - "3 => like 2 but with extra edges to make valid BMesh faces.\n" + "3 => like 2 but detect holes and omit them from output. " + "4 => like 2 but with extra edges to make valid BMesh faces. " + "5 => like 4 but detect holes and omit them from output.\n" " :type output_type: int\\n" " :arg epsilon: For nearness tests; should not be zero\n" " :type epsilon: float\n" + " :arg need_ids: are the orig output arrays needed? (optional, default True)\n" + " :type need_args: bool\n" " :return: Output tuple, (vert_coords, edges, faces, orig_verts, orig_edges, orig_faces)\n" " :rtype: (list of `mathutils.Vector`, " "list of (int, int), " @@ -1561,6 +1570,7 @@ static PyObject *M_Geometry_delaunay_2d_cdt(PyObject *UNUSED(self), PyObject *ar PyObject *vert_coords, *edges, *faces, *item; int output_type; float epsilon; + bool need_ids = true; float(*in_coords)[2] = NULL; int(*in_edges)[2] = NULL; int *in_faces = NULL; @@ -1578,8 +1588,14 @@ static PyObject *M_Geometry_delaunay_2d_cdt(PyObject *UNUSED(self), PyObject *ar PyObject *ret_value = NULL; int i; - if (!PyArg_ParseTuple( - args, "OOOif:delaunay_2d_cdt", &vert_coords, &edges, &faces, &output_type, &epsilon)) { + if (!PyArg_ParseTuple(args, + "OOOif|p:delaunay_2d_cdt", + &vert_coords, + &edges, + &faces, + &output_type, + &epsilon, + &need_ids)) { return NULL; } @@ -1609,6 +1625,7 @@ static PyObject *M_Geometry_delaunay_2d_cdt(PyObject *UNUSED(self), PyObject *ar in.faces_start_table = in_faces_start_table; in.faces_len_table = in_faces_len_table; in.epsilon = epsilon; + in.need_ids = need_ids; res = BLI_delaunay_2d_cdt_calc(&in, output_type); diff --git a/source/blender/sequencer/SEQ_iterator.h b/source/blender/sequencer/SEQ_iterator.h index aa2e182e1c0..e4c9f20f736 100644 --- a/source/blender/sequencer/SEQ_iterator.h +++ b/source/blender/sequencer/SEQ_iterator.h @@ -30,9 +30,9 @@ extern "C" { #include "BLI_ghash.h" struct Editing; -struct Sequence; struct GSet; struct GSetIterator; +struct Sequence; #define SEQ_ITERATOR_FOREACH(var, collection) \ for (SeqIterator iter = {{{NULL}}}; \ diff --git a/source/blender/sequencer/SEQ_proxy.h b/source/blender/sequencer/SEQ_proxy.h index b06adef2802..7bfe932ff1c 100644 --- a/source/blender/sequencer/SEQ_proxy.h +++ b/source/blender/sequencer/SEQ_proxy.h @@ -34,8 +34,8 @@ struct ListBase; struct Main; struct Scene; struct SeqIndexBuildContext; -struct Sequence; struct SeqRenderData; +struct Sequence; bool SEQ_proxy_rebuild_context(struct Main *bmain, struct Depsgraph *depsgraph, diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h index 706f4064bf3..f4338d13c8f 100644 --- a/source/blender/sequencer/SEQ_sequencer.h +++ b/source/blender/sequencer/SEQ_sequencer.h @@ -32,8 +32,8 @@ extern "C" { struct Editing; struct Scene; struct Sequence; -struct SequencerToolSettings; struct SequenceLookup; +struct SequencerToolSettings; /* RNA enums, just to be more readable */ enum { diff --git a/source/blender/sequencer/SEQ_transform.h b/source/blender/sequencer/SEQ_transform.h index 837a2de5742..9ff827333be 100644 --- a/source/blender/sequencer/SEQ_transform.h +++ b/source/blender/sequencer/SEQ_transform.h @@ -29,8 +29,8 @@ extern "C" { struct ListBase; struct Scene; -struct Sequence; struct SeqCollection; +struct Sequence; int SEQ_transform_get_left_handle_frame(struct Sequence *seq); int SEQ_transform_get_right_handle_frame(struct Sequence *seq); diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c index b9278b9f971..0dc8dfa10d7 100644 --- a/source/blender/sequencer/intern/strip_edit.c +++ b/source/blender/sequencer/intern/strip_edit.c @@ -407,6 +407,8 @@ Sequence *SEQ_edit_strip_split(Main *bmain, BLI_addtail(&left_strips, seq); } + SEQ_collection_free(collection); + /* Sort list, so that no strip can depend on next strip in list. * This is important for SEQ_time_update_sequence functionality. */ SEQ_sort(&left_strips); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 66e91526009..1c994707ca9 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -623,7 +623,7 @@ void WM_uilisttype_free(void); void WM_uilisttype_to_full_list_id(const struct uiListType *ult, const char *list_id, - char *r_ui_list_id); + char r_full_list_id[]); const char *WM_uilisttype_list_id_get(const struct uiListType *ult, struct uiList *list); /* wm_menu_type.c */ diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 0922aaaee53..f01e28f8822 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -457,6 +457,7 @@ static void wm_draw_region_buffer_create(ARegion *region, bool stereo, bool use_ GPUOffScreen *offscreen = GPU_offscreen_create( region->winx, region->winy, false, false, NULL); if (!offscreen) { + WM_report(RPT_ERROR, "Region could not be drawn!"); return; } diff --git a/source/blender/windowmanager/intern/wm_uilist_type.c b/source/blender/windowmanager/intern/wm_uilist_type.c index 468ea7e4d5b..82ba4aa6e6f 100644 --- a/source/blender/windowmanager/intern/wm_uilist_type.c +++ b/source/blender/windowmanager/intern/wm_uilist_type.c @@ -154,7 +154,7 @@ void WM_uilisttype_free(void) /** * The "full" list-ID is an internal name used for storing and identifying a list. It is built like * this: - * "{uiListType.idname}_{list_id}", wherby "list_id" is an optional parameter passed to + * "{uiListType.idname}_{list_id}", whereby "list_id" is an optional parameter passed to * `UILayout.template_list()`. If it is not set, the full list-ID is just "{uiListType.idname}_". * * Note that whenever the Python API refers to the list-ID, it's the short, "non-full" one it @@ -163,7 +163,7 @@ void WM_uilisttype_free(void) */ void WM_uilisttype_to_full_list_id(const uiListType *ult, const char *list_id, - char r_full_list_id[UI_MAX_NAME_STR]) + char r_full_list_id[/*UI_MAX_NAME_STR*/]) { /* We tag the list id with the list type... */ BLI_snprintf(r_full_list_id, UI_MAX_NAME_STR, "%s_%s", ult->idname, list_id ? list_id : ""); |