diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
30 files changed, 747 insertions, 182 deletions
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 58337bcf488..2cc715464ad 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -56,7 +56,7 @@ # ifdef WITH_BINRELOC # include "binreloc.h" # endif -/* mkdtemp on OSX (and probably all *BSD?), not worth making specific check for this OS. */ +/* #mkdtemp on OSX (and probably all *BSD?), not worth making specific check for this OS. */ # include <unistd.h> #endif /* WIN32 */ @@ -120,7 +120,7 @@ static char *blender_version_decimal(const int ver) } /** - * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath, + * Concatenates path_base, (optional) path_sep and (optional) folder_name into \a targetpath, * returning true if result points to a directory. */ static bool test_path(char *targetpath, @@ -138,14 +138,14 @@ static bool test_path(char *targetpath, BLI_strncpy(tmppath, path_base, sizeof(tmppath)); } - /* rare cases folder_name is omitted (when looking for ~/.config/blender/2.xx dir only) */ + /* Rare cases folder_name is omitted (when looking for `~/.config/blender/2.xx` dir only). */ if (folder_name) { BLI_join_dirfile(targetpath, targetpath_len, tmppath, folder_name); } else { BLI_strncpy(targetpath, tmppath, targetpath_len); } - /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile) + /* FIXME: why is "//" on front of \a tmppath expanded to "/" (by BLI_join_dirfile) * if folder_name is specified but not otherwise? */ if (BLI_is_dir(targetpath)) { @@ -190,7 +190,7 @@ static bool test_env_path(char *path, const char *envvar) /** * Constructs in \a targetpath the name of a directory relative to a version-specific - * subdirectory in the parent directory of the Blender executable. + * sub-directory in the parent directory of the Blender executable. * * \param targetpath: String to return path * \param folder_name: Optional folder name within version-specific directory @@ -307,7 +307,7 @@ static bool get_path_environment_notest(char *targetpath, * \param targetpath: String to return path * \param folder_name: default name of folder within user area * \param subfolder_name: optional name of subfolder within folder - * \param ver: Blender version, used to construct a subdirectory name + * \param ver: Blender version, used to construct a sub-directory name * \return true if it was able to construct such a path. */ static bool get_path_user(char *targetpath, @@ -350,8 +350,8 @@ static bool get_path_user(char *targetpath, * * \param targetpath: String to return path * \param folder_name: default name of folder within installation area - * \param subfolder_name: optional name of subfolder within folder - * \param ver: Blender version, used to construct a subdirectory name + * \param subfolder_name: optional name of sub-folder within folder + * \param ver: Blender version, used to construct a sub-directory name * \return true if it was able to construct such a path. */ static bool get_path_system(char *targetpath, @@ -635,7 +635,7 @@ const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, con * adds the correct extension (.com .exe etc) from * $PATHEXT if necessary. Also on Windows it translates * the name to its 8.3 version to prevent problems with - * spaces and stuff. Final result is returned in fullname. + * spaces and stuff. Final result is returned in \a fullname. * * \param fullname: The full path and full name of the executable * (must be FILE_MAX minimum) @@ -975,7 +975,7 @@ static void where_is_temp(char *fullname, char *basename, const size_t maxlen, c /** * Sets btempdir_base to userdir if specified and is a valid directory, otherwise * chooses a suitable OS-specific temporary directory. - * Sets btempdir_session to a mkdtemp-generated sub-dir of btempdir_base. + * Sets btempdir_session to a #mkdtemp generated sub-dir of btempdir_base. * * \note On Window userdir will be set to the temporary directory! */ @@ -1019,7 +1019,11 @@ void BKE_tempdir_session_purge(void) } /* Gets a good default directory for fonts */ -bool BKE_appdir_font_folder_default(char *dir) + +bool BKE_appdir_font_folder_default( + /* This parameter can only be `const` on non-windows platforms. + * NOLINTNEXTLINE: readability-non-const-parameter. */ + char *dir) { bool success = false; #ifdef WIN32 diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 7c8c1cf6653..f45cd5b679a 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -1037,7 +1037,7 @@ static void cloth_free_errorsprings(Cloth *cloth, } BLI_INLINE void cloth_bend_poly_dir( - ClothVertex *verts, int i, int j, int *inds, int len, float r_dir[3]) + ClothVertex *verts, int i, int j, const int *inds, int len, float r_dir[3]) { float cent[3] = {0}; float fact = 1.0f / len; diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index c894534c504..e9e44ac05e5 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1157,7 +1157,7 @@ void BKE_nurb_knot_calc_v(Nurb *nu) } static void basisNurb( - float t, short order, int pnts, float *knots, float *basis, int *start, int *end) + float t, short order, int pnts, const float *knots, float *basis, int *start, int *end) { float d, e; int i, i1 = 0, i2 = 0, j, orderpluspnts, opp2, o2; @@ -3560,8 +3560,13 @@ static void free_arrays(void *buffer) } /* computes in which direction to change h[i] to satisfy conditions better */ -static float bezier_relax_direction( - float *a, float *b, float *c, float *d, float *h, int i, int count) +static float bezier_relax_direction(const float *a, + const float *b, + const float *c, + const float *d, + const float *h, + int i, + int count) { /* current deviation between sides of the equation */ float state = a[i] * h[(i + count - 1) % count] + b[i] * h[i] + c[i] * h[(i + 1) % count] - d[i]; @@ -3577,8 +3582,15 @@ static void bezier_lock_unknown(float *a, float *b, float *c, float *d, int i, f d[i] = value; } -static void bezier_restore_equation( - float *a, float *b, float *c, float *d, float *a0, float *b0, float *c0, float *d0, int i) +static void bezier_restore_equation(float *a, + float *b, + float *c, + float *d, + const float *a0, + const float *b0, + const float *c0, + const float *d0, + int i) { a[i] = a0[i]; b[i] = b0[i]; @@ -3586,8 +3598,14 @@ static void bezier_restore_equation( d[i] = d0[i]; } -static bool tridiagonal_solve_with_limits( - float *a, float *b, float *c, float *d, float *h, float *hmin, float *hmax, int solve_count) +static bool tridiagonal_solve_with_limits(float *a, + float *b, + float *c, + float *d, + float *h, + const float *hmin, + const float *hmax, + int solve_count) { float *a0, *b0, *c0, *d0; float **arrays[] = {&a0, &b0, &c0, &d0, NULL}; @@ -3726,7 +3744,7 @@ static bool tridiagonal_solve_with_limits( /* clang-format on */ static void bezier_eq_continuous( - float *a, float *b, float *c, float *d, float *dy, float *l, int i) + float *a, float *b, float *c, float *d, const float *dy, const float *l, int i) { a[i] = l[i] * l[i]; b[i] = 2.0f * (l[i] + 1); @@ -3735,7 +3753,7 @@ static void bezier_eq_continuous( } static void bezier_eq_noaccel_right( - float *a, float *b, float *c, float *d, float *dy, float *l, int i) + float *a, float *b, float *c, float *d, const float *dy, const float *l, int i) { a[i] = 0.0f; b[i] = 2.0f; @@ -3744,7 +3762,7 @@ static void bezier_eq_noaccel_right( } static void bezier_eq_noaccel_left( - float *a, float *b, float *c, float *d, float *dy, float *l, int i) + float *a, float *b, float *c, float *d, const float *dy, const float *l, int i) { a[i] = l[i] * l[i]; b[i] = 2.0f * l[i]; @@ -4823,7 +4841,7 @@ float (*BKE_curve_nurbs_key_vert_coords_alloc(ListBase *lb, float *key, int *r_v return cos; } -void BKE_curve_nurbs_key_vert_tilts_apply(ListBase *lb, float *key) +void BKE_curve_nurbs_key_vert_tilts_apply(ListBase *lb, const float *key) { Nurb *nu; int i; diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 48e0ee50d43..9bdd80fd668 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -562,7 +562,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map CustomData *cd_dst, const bool use_dupref_dst, const int tolayers, - bool *use_layers_src, + const bool *use_layers_src, const int num_layers_src, cd_datatransfer_interp interp, void *interp_data) diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index b97935d57f2..98fc5f9a23a 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -249,7 +249,7 @@ void BKE_defvert_sync_mapped(MDeformVert *dvert_dst, /** * be sure all flip_map values are valid */ -void BKE_defvert_remap(MDeformVert *dvert, int *map, const int map_len) +void BKE_defvert_remap(MDeformVert *dvert, const int *map, const int map_len) { MDeformWeight *dw = dvert->dw; unsigned int i; @@ -1184,7 +1184,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map, CustomData *cd_dst, const bool UNUSED(use_dupref_dst), const int tolayers, - bool *use_layers_src, + const bool *use_layers_src, const int num_layers_src) { int idx_src; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 2e1fa519284..b9279ace39f 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -588,7 +588,7 @@ static bool boundsIntersectDist(Bounds3D *b1, Bounds3D *b2, const float dist) } /* check whether bounds intersects a point with given radius */ -static bool boundIntersectPoint(Bounds3D *b, float point[3], const float radius) +static bool boundIntersectPoint(Bounds3D *b, const float point[3], const float radius) { if (!b->valid) { return false; @@ -4780,13 +4780,16 @@ static void dynamic_paint_paint_single_point_cb_ex(void *__restrict userdata, } } -static int dynamicPaint_paintSinglePoint(Depsgraph *depsgraph, - DynamicPaintSurface *surface, - float *pointCoord, - DynamicPaintBrushSettings *brush, - Object *brushOb, - Scene *scene, - float timescale) +static int dynamicPaint_paintSinglePoint( + Depsgraph *depsgraph, + DynamicPaintSurface *surface, + /* Cannot be const, because it is assigned to non-const variable. + * NOLINTNEXTLINE: readability-non-const-parameter. */ + float *pointCoord, + DynamicPaintBrushSettings *brush, + Object *brushOb, + Scene *scene, + float timescale) { PaintSurfaceData *sData = surface->data; float brush_radius = brush->paint_distance * surface->radius_scale; @@ -5456,11 +5459,14 @@ static void dynamic_paint_effect_drip_cb(void *__restrict userdata, } } -static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, - float *force, - PaintPoint *prevPoint, - float timescale, - float steps) +static void dynamicPaint_doEffectStep( + DynamicPaintSurface *surface, + /* Cannot be const, because it is assigned to non-const variable. + * NOLINTNEXTLINE: readability-non-const-parameter. */ + float *force, + PaintPoint *prevPoint, + float timescale, + float steps) { PaintSurfaceData *sData = surface->data; diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index bc14f525c2c..746aff1697c 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1277,7 +1277,7 @@ short test_time_fcurve(FCurve *fcu) * than the horizontal distance between (v1-v4). * This is to prevent curve loops. */ -void correct_bezpart(float v1[2], float v2[2], float v3[2], float v4[2]) +void correct_bezpart(const float v1[2], float v2[2], float v3[2], const float v4[2]) { float h1[2], h2[2], len1, len2, len, fac; diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 1f748487841..52a3521189b 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -137,9 +137,9 @@ bool BKE_fluid_reallocate_fluid(FluidDomainSettings *fds, int res[3], int free_o void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds, int o_res[3], int n_res[3], - int o_min[3], - int n_min[3], - int o_max[3], + const int o_min[3], + const int n_min[3], + const int o_max[3], int o_shift[3], int n_shift[3]) { @@ -491,6 +491,17 @@ static void manta_set_domain_from_mesh(FluidDomainSettings *fds, fds->cell_size[2] /= (float)fds->base_res[2]; } +static void update_final_gravity(FluidDomainSettings *fds, Scene *scene) +{ + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + copy_v3_v3(fds->gravity_final, scene->physics_settings.gravity); + } + else { + copy_v3_v3(fds->gravity_final, fds->gravity); + } + mul_v3_fl(fds->gravity_final, fds->effector_weights->global_gravity); +} + static bool BKE_fluid_modifier_init( FluidModifierData *fmd, Depsgraph *depsgraph, Object *ob, Scene *scene, Mesh *me) { @@ -502,10 +513,7 @@ static bool BKE_fluid_modifier_init( /* Set domain dimensions from mesh. */ manta_set_domain_from_mesh(fds, ob, me, true); /* Set domain gravity, use global gravity if enabled. */ - if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { - copy_v3_v3(fds->gravity, scene->physics_settings.gravity); - } - mul_v3_fl(fds->gravity, fds->effector_weights->global_gravity); + update_final_gravity(fds, scene); /* Reset domain values. */ zero_v3_int(fds->shift); zero_v3(fds->shift_f); @@ -559,7 +567,7 @@ static bool BKE_fluid_modifier_init( // forward declaration static void manta_smoke_calc_transparency(FluidDomainSettings *fds, ViewLayer *view_layer); static float calc_voxel_transp( - float *result, float *input, int res[3], int *pixel, float *t_ray, float correct); + float *result, const float *input, int res[3], int *pixel, float *t_ray, float correct); static void update_distances(int index, float *fesh_distances, BVHTreeFromMesh *tree_data, @@ -594,8 +602,8 @@ static int get_light(ViewLayer *view_layer, float *light) static void clamp_bounds_in_domain(FluidDomainSettings *fds, int min[3], int max[3], - float *min_vel, - float *max_vel, + const float *min_vel, + const float *max_vel, int margin, float dt) { @@ -1830,7 +1838,7 @@ static void sample_mesh(FluidFlowSettings *ffs, float *velocity_map, int index, const int base_res[3], - float flow_center[3], + const float flow_center[3], BVHTreeFromMesh *tree_data, const float ray_start[3], const float *vert_vel, @@ -3328,17 +3336,13 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obj mverts->co[1] = manta_liquid_get_vertex_y_at(fds->fluid, i); mverts->co[2] = manta_liquid_get_vertex_z_at(fds->fluid, i); - /* If reading raw data directly from manta, normalize now (e.g. during replay mode). - * If reading data from files from disk, omit this normalization. */ - if (!manta_liquid_mesh_from_file(fds->fluid)) { - // normalize to unit cube around 0 - mverts->co[0] -= ((float)fds->res[0] * fds->mesh_scale) * 0.5f; - mverts->co[1] -= ((float)fds->res[1] * fds->mesh_scale) * 0.5f; - mverts->co[2] -= ((float)fds->res[2] * fds->mesh_scale) * 0.5f; - mverts->co[0] *= fds->dx / fds->mesh_scale; - mverts->co[1] *= fds->dx / fds->mesh_scale; - mverts->co[2] *= fds->dx / fds->mesh_scale; - } + /* Adjust coordinates from Mantaflow to match viewport scaling. */ + float tmp[3] = {(float)fds->res[0], (float)fds->res[1], (float)fds->res[2]}; + /* Scale to unit cube around 0. */ + mul_v3_fl(tmp, fds->mesh_scale * 0.5f); + sub_v3_v3(mverts->co, tmp); + /* Apply scaling of domain object. */ + mul_v3_fl(mverts->co, fds->dx / fds->mesh_scale); mul_v3_v3(mverts->co, co_scale); add_v3_v3(mverts->co, co_offset); @@ -3808,10 +3812,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, fds->time_per_frame = 0; /* Ensure that gravity is copied over every frame (could be keyframed). */ - if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { - copy_v3_v3(fds->gravity, scene->physics_settings.gravity); - mul_v3_fl(fds->gravity, fds->effector_weights->global_gravity); - } + update_final_gravity(fds, scene); int next_frame = scene_framenr + 1; int prev_frame = scene_framenr - 1; @@ -4118,43 +4119,47 @@ static void BKE_fluid_modifier_process( struct Mesh *BKE_fluid_modifier_do( FluidModifierData *fmd, Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me) { - /* Lock so preview render does not read smoke data while it gets modified. */ - if ((fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain) { - BLI_rw_mutex_lock(fmd->domain->fluid_mutex, THREAD_LOCK_WRITE); - } - - BKE_fluid_modifier_process(fmd, depsgraph, scene, ob, me); - - if ((fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain) { - BLI_rw_mutex_unlock(fmd->domain->fluid_mutex); - } - /* Optimization: Do not update viewport during bakes (except in replay mode) * Reason: UI is locked and updated liquid / smoke geometry is not visible anyways. */ bool needs_viewport_update = false; - if (fmd->domain) { - FluidDomainSettings *fds = fmd->domain; - /* Always update viewport in cache replay mode. */ - if (fds->cache_type == FLUID_DOMAIN_CACHE_REPLAY || - fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) { - needs_viewport_update = true; + /* Optimization: Only process modifier if object is not being altered. */ + if (!G.moving) { + /* Lock so preview render does not read smoke data while it gets modified. */ + if ((fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain) { + BLI_rw_mutex_lock(fmd->domain->fluid_mutex, THREAD_LOCK_WRITE); } - /* In other cache modes, only update the viewport when no bake is going on. */ - else { - bool with_mesh; - with_mesh = fds->flags & FLUID_DOMAIN_USE_MESH; - bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide; - baking_data = fds->cache_flag & FLUID_DOMAIN_BAKING_DATA; - baking_noise = fds->cache_flag & FLUID_DOMAIN_BAKING_NOISE; - baking_mesh = fds->cache_flag & FLUID_DOMAIN_BAKING_MESH; - baking_particles = fds->cache_flag & FLUID_DOMAIN_BAKING_PARTICLES; - baking_guide = fds->cache_flag & FLUID_DOMAIN_BAKING_GUIDE; - - if (with_mesh && !baking_data && !baking_noise && !baking_mesh && !baking_particles && - !baking_guide) { + + BKE_fluid_modifier_process(fmd, depsgraph, scene, ob, me); + + if ((fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain) { + BLI_rw_mutex_unlock(fmd->domain->fluid_mutex); + } + + if (fmd->domain) { + FluidDomainSettings *fds = fmd->domain; + + /* Always update viewport in cache replay mode. */ + if (fds->cache_type == FLUID_DOMAIN_CACHE_REPLAY || + fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) { needs_viewport_update = true; } + /* In other cache modes, only update the viewport when no bake is going on. */ + else { + bool with_mesh; + with_mesh = fds->flags & FLUID_DOMAIN_USE_MESH; + bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide; + baking_data = fds->cache_flag & FLUID_DOMAIN_BAKING_DATA; + baking_noise = fds->cache_flag & FLUID_DOMAIN_BAKING_NOISE; + baking_mesh = fds->cache_flag & FLUID_DOMAIN_BAKING_MESH; + baking_particles = fds->cache_flag & FLUID_DOMAIN_BAKING_PARTICLES; + baking_guide = fds->cache_flag & FLUID_DOMAIN_BAKING_GUIDE; + + if (with_mesh && !baking_data && !baking_noise && !baking_mesh && !baking_particles && + !baking_guide) { + needs_viewport_update = true; + } + } } } @@ -4196,7 +4201,7 @@ struct Mesh *BKE_fluid_modifier_do( } static float calc_voxel_transp( - float *result, float *input, int res[3], int *pixel, float *t_ray, float correct) + float *result, const float *input, int res[3], int *pixel, float *t_ray, float correct) { const size_t index = manta_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]); diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index dfb0fff1239..b92f86d7aea 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -1146,7 +1146,7 @@ void BKE_gpencil_stroke_2d_flat_ref(const bGPDspoint *ref_points, static void gpencil_calc_stroke_fill_uv(const float (*points2d)[2], bGPDstroke *gps, const float minv[2], - float maxv[2], + const float maxv[2], float (*r_uv)[2]) { const float s = sin(gps->uv_rotation); diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index af8ab22e14b..46a41df0391 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -529,7 +529,13 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float t[4], int cycl) return 0; } -static void flerp(int tot, float *in, float *f0, float *f1, float *f2, float *f3, float *t) +static void flerp(int tot, + float *in, + const float *f0, + const float *f1, + const float *f2, + const float *f3, + const float *t) { int a; @@ -538,7 +544,7 @@ static void flerp(int tot, float *in, float *f0, float *f1, float *f2, float *f3 } } -static void rel_flerp(int tot, float *in, float *ref, float *out, float fac) +static void rel_flerp(int tot, float *in, const float *ref, const float *out, float fac) { int a; diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 457d096f983..58856729f24 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -38,6 +38,7 @@ #include "BKE_key.h" #include "BKE_lib_id.h" #include "BKE_lib_override.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_main.h" @@ -66,20 +67,6 @@ static void lib_override_library_property_clear(IDOverrideLibraryProperty *op); static void lib_override_library_property_operation_clear( IDOverrideLibraryPropertyOperation *opop); -/* Temp, for until library override is ready and tested enough to go 'public', - * we hide it by default in UI and such. */ -static bool _lib_override_library_enabled = true; - -void BKE_lib_override_library_enable(const bool do_enable) -{ - _lib_override_library_enabled = do_enable; -} - -bool BKE_lib_override_library_is_enabled() -{ - return _lib_override_library_enabled; -} - /** Initialize empty overriding of \a reference_id by \a local_id. */ IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id) { @@ -368,6 +355,56 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain) return success; } +static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id) +{ + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id); + + /* This way we won't process again that ID should we encounter it again through another + * relationship hierarchy. + * Note that this does not free any memory from relations, so we can still use the entries. + */ + BKE_main_relations_ID_remove(bmain, id); + + for (; entry != NULL; entry = entry->next) { + /* We only consider IDs from the same library. */ + if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) { + if (lib_override_hierarchy_recursive_tag(bmain, *entry->id_pointer)) { + id->tag |= LIB_TAG_DOIT; + } + } + } + + return (id->tag & LIB_TAG_DOIT) != 0; +} + +/** + * Tag all IDs in given \a bmain that use (depends on) given \a id_root ID. + * + * This will include all local IDs, and all IDs from the same library as the \a id_root. + * + * \param id_root The root of the hierarchy of dependencies to be tagged. + * \param do_create_main_relashionships Whether main relations needs to be created or already exist + * (in any case, they will be freed by this function). + */ +void BKE_lib_override_library_dependencies_tag(struct Main *bmain, + struct ID *id_root, + const uint tag, + const bool do_create_main_relashionships) +{ + id_root->tag |= tag; + + if (do_create_main_relashionships) { + BKE_main_relations_create(bmain, 0); + } + + /* Then we tag all intermediary data-blocks in-between two overridden ones (e.g. if a shapekey + * has a driver using an armature object's bone, we need to override the shapekey/obdata, the + * objects using them, etc.) */ + lib_override_hierarchy_recursive_tag(bmain, id_root); + + BKE_main_relations_free(bmain); +} + /* We only build override GHash on request. */ BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_mapping_ensure( IDOverrideLibrary *override) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 49c909850de..7e859799a4e 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -624,7 +624,7 @@ void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float co, bezt->vec[1], bezt->vec[2], bezt_next->vec[0], bezt_next->vec[1], u); } -BLI_INLINE void orthogonal_direction_get(float vec[2], float result[2]) +BLI_INLINE void orthogonal_direction_get(const float vec[2], float result[2]) { result[0] = -vec[1]; result[1] = vec[0]; diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 412ccd3ab39..7f98266becc 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -1256,7 +1256,7 @@ static float maskrasterize_layer_z_depth_quad( return w[2] + w[3]; /* we can make this assumption for small speedup */ } -static float maskrasterize_layer_isect(unsigned int *face, +static float maskrasterize_layer_isect(const unsigned int *face, float (*cos)[3], const float dist_orig, const float xy[2]) @@ -1489,6 +1489,8 @@ static void maskrasterize_buffer_cb(void *__restrict userdata, void BKE_maskrasterize_buffer(MaskRasterHandle *mr_handle, const unsigned int width, const unsigned int height, + /* Cannot be const, because it is assigned to non-const variable. + * NOLINTNEXTLINE: readability-non-const-parameter. */ float *buffer) { const float x_inv = 1.0f / (float)width; diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index b298a6a2787..49957b584ad 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -2888,7 +2888,7 @@ void BKE_mesh_loops_to_mface_corners( void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, MFace *mface, - int *polyindices, + const int *polyindices, unsigned int (*loopindices)[4], const int num_faces) { @@ -2981,7 +2981,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, void BKE_mesh_tangent_loops_to_tessdata(CustomData *fdata, CustomData *ldata, MFace *mface, - int *polyindices, + const int *polyindices, unsigned int (*loopindices)[4], const int num_faces, const char *layer_name) diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index 4ed9b31dbb5..686f58a0ceb 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -953,7 +953,7 @@ void BKE_mesh_loop_islands_free(MeshIslandStore *island_store) void BKE_mesh_loop_islands_add(MeshIslandStore *island_store, const int item_num, - int *items_indices, + const int *items_indices, const int num_island_items, int *island_item_indices, const int num_innercut_items, diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index 404d6a581ae..a4991675d2d 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -1071,7 +1071,7 @@ static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, BLI_bitmap *done_edges, MeshElemMap *edge_to_poly_map, const bool is_edge_innercut, - int *poly_island_index_map, + const int *poly_island_index_map, float (*poly_centers)[3], unsigned char *poly_status) { diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 7e78be6d66e..71d49dd1c19 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -175,7 +175,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden, return subd; } -static BLI_bitmap *multires_mdisps_downsample_hidden(BLI_bitmap *old_hidden, +static BLI_bitmap *multires_mdisps_downsample_hidden(const BLI_bitmap *old_hidden, int old_level, int new_level) { diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.c b/source/blender/blenkernel/intern/multires_unsubdivide.c index 6bd7b6b6a98..fa1a53f946e 100644 --- a/source/blender/blenkernel/intern/multires_unsubdivide.c +++ b/source/blender/blenkernel/intern/multires_unsubdivide.c @@ -80,7 +80,7 @@ /** * Used to check if a vertex is in a disconnected element ID. */ -static bool is_vertex_in_id(BMVert *v, int *elem_id, int elem) +static bool is_vertex_in_id(BMVert *v, const int *elem_id, int elem) { const int v_index = BM_elem_index_get(v); return elem_id[v_index] == elem; diff --git a/source/blender/blenkernel/intern/node_tree_multi_function.cc b/source/blender/blenkernel/intern/node_tree_multi_function.cc index 02437d98732..4e505db9b9d 100644 --- a/source/blender/blenkernel/intern/node_tree_multi_function.cc +++ b/source/blender/blenkernel/intern/node_tree_multi_function.cc @@ -16,6 +16,8 @@ #include "BKE_node_tree_multi_function.hh" +#include "BLI_float3.hh" + namespace blender { namespace bke { @@ -136,11 +138,72 @@ static fn::MFOutputSocket *try_find_origin(CommonMFNetworkBuilderData &common, } if (from_dsockets.size() == 1) { - return &common.network_map.lookup(*from_dsockets[0]); + if (is_multi_function_data_socket(from_dsockets[0]->bsocket())) { + return &common.network_map.lookup(*from_dsockets[0]); + } + else { + return nullptr; + } + } + else { + if (is_multi_function_data_socket(from_group_inputs[0]->bsocket())) { + return &common.network_map.lookup(*from_group_inputs[0]); + } + else { + return nullptr; + } + } +} + +static const fn::MultiFunction *try_get_conversion_function(fn::MFDataType from, fn::MFDataType to) +{ + if (from == fn::MFDataType::ForSingle<float>()) { + if (to == fn::MFDataType::ForSingle<int32_t>()) { + static fn::CustomMF_Convert<float, int32_t> function; + return &function; + } + if (to == fn::MFDataType::ForSingle<float3>()) { + static fn::CustomMF_Convert<float, float3> function; + return &function; + } + } + if (from == fn::MFDataType::ForSingle<float3>()) { + if (to == fn::MFDataType::ForSingle<float>()) { + static fn::CustomMF_SI_SO<float3, float> function{"Vector Length", + [](float3 a) { return a.length(); }}; + return &function; + } + } + if (from == fn::MFDataType::ForSingle<int32_t>()) { + if (to == fn::MFDataType::ForSingle<float>()) { + static fn::CustomMF_Convert<int32_t, float> function; + return &function; + } + if (to == fn::MFDataType::ForSingle<float3>()) { + static fn::CustomMF_SI_SO<int32_t, float3> function{ + "int32 to float3", [](int32_t a) { return float3((float)a); }}; + return &function; + } + } + + return nullptr; +} + +static fn::MFOutputSocket &insert_default_value_for_type(CommonMFNetworkBuilderData &common, + fn::MFDataType type) +{ + const fn::MultiFunction *default_fn; + if (type.is_single()) { + default_fn = &common.resources.construct<fn::CustomMF_GenericConstant>( + AT, type.single_type(), type.single_type().default_value()); } else { - return &common.network_map.lookup(*from_group_inputs[0]); + default_fn = &common.resources.construct<fn::CustomMF_GenericConstantArray>( + AT, fn::GSpan(type.vector_base_type())); } + + fn::MFNode &node = common.network.add_function(*default_fn); + return node.output(0); } static void insert_links(CommonMFNetworkBuilderData &common) @@ -149,24 +212,34 @@ static void insert_links(CommonMFNetworkBuilderData &common) if (!to_dsocket->is_available()) { continue; } - - if (!is_multi_function_data_socket(to_dsocket->bsocket())) { + if (!to_dsocket->is_linked()) { continue; } - - fn::MFOutputSocket *from_socket = try_find_origin(common, *to_dsocket); - if (from_socket == nullptr) { + if (!is_multi_function_data_socket(to_dsocket->bsocket())) { continue; } Span<fn::MFInputSocket *> to_sockets = common.network_map.lookup(*to_dsocket); BLI_assert(to_sockets.size() >= 1); + fn::MFDataType to_type = to_sockets[0]->data_type(); + + fn::MFOutputSocket *from_socket = try_find_origin(common, *to_dsocket); + if (from_socket == nullptr) { + from_socket = &insert_default_value_for_type(common, to_type); + } fn::MFDataType from_type = from_socket->data_type(); - fn::MFDataType to_type = to_sockets[0]->data_type(); if (from_type != to_type) { - /* Todo: Try inserting implicit conversion. */ + const fn::MultiFunction *conversion_fn = try_get_conversion_function(from_type, to_type); + if (conversion_fn != nullptr) { + fn::MFNode &node = common.network.add_function(*conversion_fn); + common.network.add_link(*from_socket, node.input(0)); + from_socket = &node.output(0); + } + else { + from_socket = &insert_default_value_for_type(common, to_type); + } } for (fn::MFInputSocket *to_socket : to_sockets) { diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c index 6ca1442497a..51ec89cf77d 100644 --- a/source/blender/blenkernel/intern/object_deform.c +++ b/source/blender/blenkernel/intern/object_deform.c @@ -68,7 +68,7 @@ static Lattice *object_defgroup_lattice_get(ID *id) * * \param map: an array mapping old indices to new indices. */ -void BKE_object_defgroup_remap_update_users(Object *ob, int *map) +void BKE_object_defgroup_remap_update_users(Object *ob, const int *map) { ModifierData *md; ParticleSystem *psys; diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 609c5c1e580..f94ef946851 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -147,19 +147,19 @@ static void init_complex(fftw_complex cmpl, float real, float image) cmpl[1] = image; } -static void add_comlex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl2) +static void add_comlex_c(fftw_complex res, const fftw_complex cmpl1, const fftw_complex cmpl2) { res[0] = cmpl1[0] + cmpl2[0]; res[1] = cmpl1[1] + cmpl2[1]; } -static void mul_complex_f(fftw_complex res, fftw_complex cmpl, float f) +static void mul_complex_f(fftw_complex res, const fftw_complex cmpl, float f) { res[0] = cmpl[0] * (double)f; res[1] = cmpl[1] * (double)f; } -static void mul_complex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl2) +static void mul_complex_c(fftw_complex res, const fftw_complex cmpl1, const fftw_complex cmpl2) { fftwf_complex temp; temp[0] = cmpl1[0] * cmpl2[0] - cmpl1[1] * cmpl2[1]; @@ -178,7 +178,7 @@ static float image_c(fftw_complex cmpl) return cmpl[1]; } -static void conj_complex(fftw_complex res, fftw_complex cmpl1) +static void conj_complex(fftw_complex res, const fftw_complex cmpl1) { res[0] = cmpl1[0]; res[1] = -cmpl1[1]; diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 7b9b2484dbe..e0dccd4d14a 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -433,7 +433,7 @@ static void psys_uv_to_w(float u, float v, int quad, float *w) } /* Find the index in "sum" array before "value" is crossed. */ -static int distribute_binary_search(float *sum, int n, float value) +static int distribute_binary_search(const float *sum, int n, float value) { int mid, low = 0, high = n - 1; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index cd821077292..bf9aea81181 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -4966,6 +4966,7 @@ void particle_system_update(struct Depsgraph *depsgraph, psys_orig->flag = (psys->flag & ~PSYS_SHARED_CACHES); psys_orig->cfra = psys->cfra; psys_orig->recalc = psys->recalc; + psys_orig->part->totpart = part->totpart; } } diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 870a1f3d673..67988427bd2 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -358,7 +358,7 @@ static void update_vb(PBVH *pbvh, PBVHNode *node, BBC *prim_bbc, int offset, int /* Returns the number of visible quads in the nodes' grids. */ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden, - int *grid_indices, + const int *grid_indices, int totgrid, int gridsize) { diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index ce5402551b6..9a9d8dc215b 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -206,7 +206,7 @@ static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNUS return 1; } static void ptcache_softbody_read( - int index, void *soft_v, void **data, float UNUSED(cfra), float *old_data) + int index, void *soft_v, void **data, float UNUSED(cfra), const float *old_data) { SoftBody *soft = soft_v; BodyPoint *bp = soft->bpoint + index; @@ -220,8 +220,13 @@ static void ptcache_softbody_read( PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec); } } -static void ptcache_softbody_interpolate( - int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_softbody_interpolate(int index, + void *soft_v, + void **data, + float cfra, + float cfra1, + float cfra2, + const float *old_data) { SoftBody *soft = soft_v; BodyPoint *bp = soft->bpoint + index; @@ -316,7 +321,7 @@ static int ptcache_particle_write(int index, void *psys_v, void **data, int cfra return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time); } static void ptcache_particle_read( - int index, void *psys_v, void **data, float cfra, float *old_data) + int index, void *psys_v, void **data, float cfra, const float *old_data) { ParticleSystem *psys = psys_v; ParticleData *pa; @@ -383,8 +388,13 @@ static void ptcache_particle_read( unit_qt(pa->state.rot); } } -static void ptcache_particle_interpolate( - int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_particle_interpolate(int index, + void *psys_v, + void **data, + float cfra, + float cfra1, + float cfra2, + const float *old_data) { ParticleSystem *psys = psys_v; ParticleData *pa; @@ -528,7 +538,7 @@ static int ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED return 1; } static void ptcache_cloth_read( - int index, void *cloth_v, void **data, float UNUSED(cfra), float *old_data) + int index, void *cloth_v, void **data, float UNUSED(cfra), const float *old_data) { ClothModifierData *clmd = cloth_v; Cloth *cloth = clmd->clothObject; @@ -545,8 +555,13 @@ static void ptcache_cloth_read( PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst); } } -static void ptcache_cloth_interpolate( - int index, void *cloth_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_cloth_interpolate(int index, + void *cloth_v, + void **data, + float cfra, + float cfra1, + float cfra2, + const float *old_data) { ClothModifierData *clmd = cloth_v; Cloth *cloth = clmd->clothObject; @@ -1509,7 +1524,7 @@ static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSE return 1; } static void ptcache_rigidbody_read( - int index, void *rb_v, void **data, float UNUSED(cfra), float *old_data) + int index, void *rb_v, void **data, float UNUSED(cfra), const float *old_data) { RigidBodyWorld *rbw = rb_v; Object *ob = NULL; @@ -1534,8 +1549,13 @@ static void ptcache_rigidbody_read( } } } -static void ptcache_rigidbody_interpolate( - int index, void *rb_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_rigidbody_interpolate(int index, + void *rb_v, + void **data, + float cfra, + float cfra1, + float cfra2, + const float *old_data) { RigidBodyWorld *rbw = rb_v; Object *ob = NULL; @@ -1887,7 +1907,7 @@ static int ptcache_sim_particle_write(int index, void *state_v, void **data, int return 1; } static void ptcache_sim_particle_read( - int index, void *state_v, void **data, float UNUSED(cfra), float *UNUSED(old_data)) + int index, void *state_v, void **data, float UNUSED(cfra), const float *UNUSED(old_data)) { ParticleSimulationState *state = (ParticleSimulationState *)state_v; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index de233a8d473..4a2ad88bb28 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -2668,7 +2668,7 @@ static void RVAddBitmaps_float(float *a, float *b, float *c, int width, int heig } static void RVIsolateHighlights_float( - float *in, float *out, int width, int height, float threshold, float boost, float clamp) + const float *in, float *out, int width, int height, float threshold, float boost, float clamp) { int x, y, index; float intensity; @@ -3423,7 +3423,7 @@ static void do_gaussian_blur_effect_byte_x(Sequence *seq, int y, int frame_width, int UNUSED(frame_height), - unsigned char *rect, + const unsigned char *rect, unsigned char *out) { #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4) @@ -3473,7 +3473,7 @@ static void do_gaussian_blur_effect_byte_y(Sequence *seq, int y, int UNUSED(frame_width), int frame_height, - unsigned char *rect, + const unsigned char *rect, unsigned char *out) { #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4) diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index 604cbf476a8..a630170d6d5 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -57,7 +57,7 @@ typedef void (*modifier_apply_threaded_cb)(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v); typedef struct ModifierInitData { @@ -223,7 +223,7 @@ static void whiteBalance_apply_threaded(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v) { int x, y; @@ -331,7 +331,7 @@ static void curves_apply_threaded(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v) { CurveMapping *curve_mapping = (CurveMapping *)data_v; @@ -461,7 +461,7 @@ static void hue_correct_apply_threaded(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v) { CurveMapping *curve_mapping = (CurveMapping *)data_v; @@ -556,7 +556,7 @@ static void brightcontrast_apply_threaded(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v) { BrightContrastThreadData *data = (BrightContrastThreadData *)data_v; @@ -658,7 +658,7 @@ static void maskmodifier_apply_threaded(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *UNUSED(data_v)) { int x, y; @@ -755,7 +755,7 @@ static void tonemapmodifier_apply_threaded_simple(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v) { AvgLogLum *avg = (AvgLogLum *)data_v; @@ -814,7 +814,7 @@ static void tonemapmodifier_apply_threaded_photoreceptor(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v) { AvgLogLum *avg = (AvgLogLum *)data_v; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 01d2176ba30..7339c887151 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1090,6 +1090,64 @@ void BKE_sequence_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, cons BKE_sequence_calc(scene, seq); } +void BKE_sequence_movie_reload_if_needed(struct Main *bmain, + struct Scene *scene, + struct Sequence *seq, + bool *r_was_reloaded, + bool *r_can_produce_frames) +{ + BLI_assert(seq->type == SEQ_TYPE_MOVIE || + !"This function is only implemented for movie strips."); + + bool must_reload = false; + + /* The Sequence struct allows for multiple anim structs to be associated with one strip. This + * function will return true only if there is at least one 'anim' AND all anims can produce + * frames. */ + + if (BLI_listbase_is_empty(&seq->anims)) { + /* No anim present, so reloading is always necessary. */ + must_reload = true; + } + else { + LISTBASE_FOREACH (StripAnim *, sanim, &seq->anims) { + if (!IMB_anim_can_produce_frames(sanim->anim)) { + /* Anim cannot produce frames, try reloading. */ + must_reload = true; + break; + } + }; + } + + if (!must_reload) { + /* There are one or more anims, and all can produce frames. */ + *r_was_reloaded = false; + *r_can_produce_frames = true; + return; + } + + BKE_sequence_reload_new_file(bmain, scene, seq, true); + *r_was_reloaded = true; + + if (BLI_listbase_is_empty(&seq->anims)) { + /* No anims present after reloading => no frames can be produced. */ + *r_can_produce_frames = false; + return; + } + + /* Check if there are still anims that cannot produce frames. */ + LISTBASE_FOREACH (StripAnim *, sanim, &seq->anims) { + if (!IMB_anim_can_produce_frames(sanim->anim)) { + /* There still is an anim that cannot produce frames. */ + *r_can_produce_frames = false; + return; + } + }; + + /* There are one or more anims, and all can produce frames. */ + *r_can_produce_frames = true; +} + void BKE_sequencer_sort(Scene *scene) { /* all strips together per kind, and in order of y location ("machine") */ @@ -2390,7 +2448,7 @@ static void color_balance_byte_float(StripColorBalance *cb_, static void color_balance_float_float(StripColorBalance *cb_, float *rect_float, - float *mask_rect_float, + const float *mask_rect_float, int width, int height, float mul) diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc index 35ef664dce3..e163bb8da8d 100644 --- a/source/blender/blenkernel/intern/simulation.cc +++ b/source/blender/blenkernel/intern/simulation.cc @@ -176,6 +176,10 @@ static void ensure_attributes_exist(ParticleSimulationState *state) CustomData_add_layer_named( &state->attributes, CD_LOCATION, CD_CALLOC, nullptr, state->tot_particles, "Velocity"); } + if (CustomData_get_layer_named(&state->attributes, CD_PROP_INT32, "ID") == nullptr) { + CustomData_add_layer_named( + &state->attributes, CD_PROP_INT32, CD_CALLOC, nullptr, state->tot_particles, "ID"); + } } static void copy_states_to_cow(Simulation *simulation_orig, Simulation *simulation_cow) @@ -211,11 +215,8 @@ static void copy_states_to_cow(Simulation *simulation_orig, Simulation *simulati } } -using AttributeNodeMap = Map<fn::MFDummyNode *, std::pair<std::string, fn::MFDataType>>; - -static AttributeNodeMap deduplicate_attribute_nodes(fn::MFNetwork &network, - MFNetworkTreeMap &network_map, - const DerivedNodeTree &tree) +static Map<const fn::MFOutputSocket *, std::string> deduplicate_attribute_nodes( + fn::MFNetwork &network, MFNetworkTreeMap &network_map, const DerivedNodeTree &tree) { Span<const DNode *> attribute_dnodes = tree.nodes_by_type("SimulationNodeParticleAttribute"); uint amount = attribute_dnodes.size(); @@ -247,11 +248,11 @@ static AttributeNodeMap deduplicate_attribute_nodes(fn::MFNetwork &network, attribute_nodes_by_name_and_type; for (uint i : IndexRange(amount)) { attribute_nodes_by_name_and_type - .lookup_or_add_default({attribute_names[i], name_sockets[i]->data_type()}) + .lookup_or_add_default({attribute_names[i], name_sockets[i]->node().output(0).data_type()}) .append(&name_sockets[i]->node()); } - AttributeNodeMap final_attribute_nodes; + Map<const fn::MFOutputSocket *, std::string> attribute_inputs; for (auto item : attribute_nodes_by_name_and_type.items()) { StringRef attribute_name = item.key.first; fn::MFDataType data_type = item.key.second; @@ -264,10 +265,10 @@ static AttributeNodeMap deduplicate_attribute_nodes(fn::MFNetwork &network, } network.remove(nodes); - final_attribute_nodes.add_new(&new_attribute_socket.node().as_dummy(), item.key); + attribute_inputs.add_new(&new_attribute_socket, attribute_name); } - return final_attribute_nodes; + return attribute_inputs; } class CustomDataAttributesRef { @@ -282,7 +283,16 @@ class CustomDataAttributesRef { fn::AttributesInfoBuilder builder; for (const CustomDataLayer &layer : Span(custom_data.layers, custom_data.totlayer)) { buffers_.append(layer.data); - builder.add<float3>(layer.name, {0, 0, 0}); + switch (layer.type) { + case CD_PROP_INT32: { + builder.add<int32_t>(layer.name, 0); + break; + } + case CD_LOCATION: { + builder.add<float3>(layer.name, {0, 0, 0}); + break; + } + } } info_ = std::make_unique<fn::AttributesInfo>(builder); size_ = size; @@ -386,6 +396,322 @@ static void update_simulation_state_list(Simulation *simulation, const DerivedNo add_missing_particle_states(simulation, state_names); } +class ParticleFunctionInput { + public: + virtual ~ParticleFunctionInput() = default; + virtual void add_input(fn::AttributesRef attributes, + fn::MFParamsBuilder ¶ms, + ResourceCollector &resources) const = 0; +}; + +class ParticleFunction { + private: + const fn::MultiFunction *global_fn_; + const fn::MultiFunction *per_particle_fn_; + Array<const ParticleFunctionInput *> global_inputs_; + Array<const ParticleFunctionInput *> per_particle_inputs_; + Array<bool> output_is_global_; + Vector<uint> global_output_indices_; + Vector<uint> per_particle_output_indices_; + Vector<fn::MFDataType> output_types_; + Vector<StringRefNull> output_names_; + + friend class ParticleFunctionEvaluator; + + public: + ParticleFunction(const fn::MultiFunction *global_fn, + const fn::MultiFunction *per_particle_fn, + Span<const ParticleFunctionInput *> global_inputs, + Span<const ParticleFunctionInput *> per_particle_inputs, + Span<bool> output_is_global) + : global_fn_(global_fn), + per_particle_fn_(per_particle_fn), + global_inputs_(global_inputs), + per_particle_inputs_(per_particle_inputs), + output_is_global_(output_is_global) + { + for (uint i : output_is_global_.index_range()) { + if (output_is_global_[i]) { + uint param_index = global_inputs_.size() + global_output_indices_.size(); + fn::MFParamType param_type = global_fn_->param_type(param_index); + BLI_assert(param_type.is_output()); + output_types_.append(param_type.data_type()); + output_names_.append(global_fn_->param_name(param_index)); + global_output_indices_.append(i); + } + else { + uint param_index = per_particle_inputs_.size() + per_particle_output_indices_.size(); + fn::MFParamType param_type = per_particle_fn_->param_type(param_index); + BLI_assert(param_type.is_output()); + output_types_.append(param_type.data_type()); + output_names_.append(per_particle_fn_->param_name(param_index)); + per_particle_output_indices_.append(i); + } + } + } +}; + +class ParticleFunctionEvaluator { + private: + ResourceCollector resources_; + const ParticleFunction &particle_fn_; + IndexMask mask_; + fn::MFContextBuilder global_context_; + fn::MFContextBuilder per_particle_context_; + fn::AttributesRef particle_attributes_; + Vector<void *> outputs_; + bool is_computed_ = false; + + public: + ParticleFunctionEvaluator(const ParticleFunction &particle_fn, + IndexMask mask, + fn::AttributesRef particle_attributes) + : particle_fn_(particle_fn), + mask_(mask), + particle_attributes_(particle_attributes), + outputs_(particle_fn_.output_types_.size(), nullptr) + { + } + + ~ParticleFunctionEvaluator() + { + for (uint output_index : outputs_.index_range()) { + void *buffer = outputs_[output_index]; + fn::MFDataType data_type = particle_fn_.output_types_[output_index]; + BLI_assert(data_type.is_single()); /* For now. */ + const fn::CPPType &type = data_type.single_type(); + + if (particle_fn_.output_is_global_[output_index]) { + type.destruct(buffer); + } + else { + type.destruct_indices(outputs_[0], mask_); + } + } + } + + void compute() + { + BLI_assert(!is_computed_); + this->compute_globals(); + this->compute_per_particle(); + is_computed_ = true; + } + + template<typename T> fn::VSpan<T> get(uint output_index, StringRef expected_name) const + { + return this->get(output_index, expected_name).typed<T>(); + } + + fn::GVSpan get(uint output_index, StringRef expected_name) const + { +#ifdef DEBUG + StringRef real_name = particle_fn_.output_names_[output_index]; + BLI_assert(expected_name == real_name); + BLI_assert(is_computed_); +#endif + UNUSED_VARS_NDEBUG(expected_name); + const void *buffer = outputs_[output_index]; + const fn::CPPType &type = particle_fn_.output_types_[output_index].single_type(); + if (particle_fn_.output_is_global_[output_index]) { + return fn::GVSpan::FromSingleWithMaxSize(type, buffer); + } + else { + return fn::GVSpan(fn::GSpan(type, buffer, mask_.min_array_size())); + } + } + + private: + void compute_globals() + { + if (particle_fn_.global_fn_ == nullptr) { + return; + } + + fn::MFParamsBuilder params(*particle_fn_.global_fn_, mask_.min_array_size()); + + /* Add input parameters. */ + for (const ParticleFunctionInput *input : particle_fn_.global_inputs_) { + input->add_input(particle_attributes_, params, resources_); + } + + /* Add output parameters. */ + for (uint output_index : particle_fn_.global_output_indices_) { + fn::MFDataType data_type = particle_fn_.output_types_[output_index]; + BLI_assert(data_type.is_single()); /* For now. */ + + const fn::CPPType &type = data_type.single_type(); + void *buffer = resources_.linear_allocator().allocate(type.size(), type.alignment()); + params.add_uninitialized_single_output(fn::GMutableSpan(type, buffer, 1)); + outputs_[output_index] = buffer; + } + + particle_fn_.global_fn_->call({0}, params, global_context_); + } + + void compute_per_particle() + { + if (particle_fn_.per_particle_fn_ == nullptr) { + return; + } + + fn::MFParamsBuilder params(*particle_fn_.per_particle_fn_, mask_.min_array_size()); + + /* Add input parameters. */ + for (const ParticleFunctionInput *input : particle_fn_.per_particle_inputs_) { + input->add_input(particle_attributes_, params, resources_); + } + + /* Add output parameters. */ + for (uint output_index : particle_fn_.per_particle_output_indices_) { + fn::MFDataType data_type = particle_fn_.output_types_[output_index]; + BLI_assert(data_type.is_single()); /* For now. */ + + const fn::CPPType &type = data_type.single_type(); + void *buffer = resources_.linear_allocator().allocate(type.size() * mask_.min_array_size(), + type.alignment()); + params.add_uninitialized_single_output( + fn::GMutableSpan(type, buffer, mask_.min_array_size())); + outputs_[output_index] = buffer; + } + + particle_fn_.per_particle_fn_->call(mask_, params, global_context_); + } +}; + +class ParticleAttributeInput : public ParticleFunctionInput { + private: + std::string attribute_name_; + const fn::CPPType &attribute_type_; + + public: + ParticleAttributeInput(std::string attribute_name, const fn::CPPType &attribute_type) + : attribute_name_(std::move(attribute_name)), attribute_type_(attribute_type) + { + } + + void add_input(fn::AttributesRef attributes, + fn::MFParamsBuilder ¶ms, + ResourceCollector &UNUSED(resources)) const override + { + std::optional<fn::GSpan> span = attributes.try_get(attribute_name_, attribute_type_); + if (span.has_value()) { + params.add_readonly_single_input(*span); + } + else { + params.add_readonly_single_input(fn::GVSpan::FromDefault(attribute_type_)); + } + } +}; + +static const ParticleFunction *create_particle_function_for_inputs( + Span<const fn::MFInputSocket *> sockets_to_compute, + ResourceCollector &resources, + const Map<const fn::MFOutputSocket *, std::string> &attribute_inputs) +{ + BLI_assert(sockets_to_compute.size() >= 1); + const fn::MFNetwork &network = sockets_to_compute[0]->node().network(); + + VectorSet<const fn::MFOutputSocket *> dummy_deps; + VectorSet<const fn::MFInputSocket *> unlinked_input_deps; + network.find_dependencies(sockets_to_compute, dummy_deps, unlinked_input_deps); + BLI_assert(unlinked_input_deps.size() == 0); + + Vector<const ParticleFunctionInput *> per_particle_inputs; + for (const fn::MFOutputSocket *socket : dummy_deps) { + StringRef attribute_name = attribute_inputs.lookup(socket); + per_particle_inputs.append(&resources.construct<ParticleAttributeInput>( + AT, attribute_name, socket->data_type().single_type())); + } + + const fn::MultiFunction &per_particle_fn = resources.construct<fn::MFNetworkEvaluator>( + AT, dummy_deps.as_span(), sockets_to_compute); + + Array<bool> output_is_global(sockets_to_compute.size(), false); + + const ParticleFunction &particle_fn = resources.construct<ParticleFunction>( + AT, + nullptr, + &per_particle_fn, + Span<const ParticleFunctionInput *>(), + per_particle_inputs.as_span(), + output_is_global.as_span()); + + return &particle_fn; +} + +class ParticleForce { + public: + virtual ~ParticleForce() = default; + virtual void add_force(fn::AttributesRef attributes, + MutableSpan<float3> r_combined_force) const = 0; +}; + +class ParticleFunctionForce : public ParticleForce { + private: + const ParticleFunction &particle_fn_; + + public: + ParticleFunctionForce(const ParticleFunction &particle_fn) : particle_fn_(particle_fn) + { + } + + void add_force(fn::AttributesRef attributes, MutableSpan<float3> r_combined_force) const override + { + IndexMask mask = IndexRange(attributes.size()); + ParticleFunctionEvaluator evaluator{particle_fn_, mask, attributes}; + evaluator.compute(); + fn::VSpan<float3> forces = evaluator.get<float3>(0, "Force"); + for (uint i : mask) { + r_combined_force[i] += forces[i]; + } + } +}; + +static Vector<const ParticleForce *> create_forces_for_particle_simulation( + const DNode &simulation_node, + MFNetworkTreeMap &network_map, + ResourceCollector &resources, + const Map<const fn::MFOutputSocket *, std::string> &attribute_inputs) +{ + Vector<const ParticleForce *> forces; + for (const DOutputSocket *origin_socket : simulation_node.input(2, "Forces").linked_sockets()) { + const DNode &origin_node = origin_socket->node(); + if (origin_node.idname() != "SimulationNodeForce") { + continue; + } + + const fn::MFInputSocket &force_socket = network_map.lookup_dummy( + origin_node.input(0, "Force")); + + const ParticleFunction *particle_fn = create_particle_function_for_inputs( + {&force_socket}, resources, attribute_inputs); + + if (particle_fn == nullptr) { + continue; + } + + const ParticleForce &force = resources.construct<ParticleFunctionForce>(AT, *particle_fn); + forces.append(&force); + } + return forces; +} + +static Map<std::string, Vector<const ParticleForce *>> collect_forces( + MFNetworkTreeMap &network_map, + ResourceCollector &resources, + const Map<const fn::MFOutputSocket *, std::string> &attribute_inputs) +{ + Map<std::string, Vector<const ParticleForce *>> forces_by_simulation; + for (const DNode *dnode : network_map.tree().nodes_by_type("SimulationNodeParticleSimulation")) { + std::string name = dnode_to_path(*dnode); + Vector<const ParticleForce *> forces = create_forces_for_particle_simulation( + *dnode, network_map, resources, attribute_inputs); + forces_by_simulation.add_new(std::move(name), std::move(forces)); + } + return forces_by_simulation; +} + static void simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation *simulation_cow) { int current_frame = scene->r.cfra; @@ -406,12 +732,15 @@ static void simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulatio fn::MFNetwork network; ResourceCollector resources; MFNetworkTreeMap network_map = insert_node_tree_into_mf_network(network, tree, resources); - AttributeNodeMap attribute_node_map = deduplicate_attribute_nodes(network, network_map, tree); + // WM_clipboard_text_set(tree.to_dot().c_str(), false); + Map<const fn::MFOutputSocket *, std::string> attribute_inputs = deduplicate_attribute_nodes( + network, network_map, tree); fn::mf_network_optimization::constant_folding(network, resources); fn::mf_network_optimization::common_subnetwork_elimination(network); fn::mf_network_optimization::dead_node_removal(network); - UNUSED_VARS(attribute_node_map); - // WM_clipboard_text_set(network.to_dot().c_str(), false); + + Map<std::string, Vector<const ParticleForce *>> forces_by_simulation = collect_forces( + network_map, resources, attribute_inputs); if (current_frame == 1) { reinitialize_empty_simulation_states(simulation_orig, tree); @@ -420,7 +749,7 @@ static void simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulatio simulation_orig->current_frame = 1; LISTBASE_FOREACH (ParticleSimulationState *, state, &simulation_orig->states) { - state->tot_particles = 100; + state->tot_particles = 1000; CustomData_realloc(&state->attributes, state->tot_particles); ensure_attributes_exist(state); @@ -430,10 +759,12 @@ static void simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulatio fn::MutableAttributesRef attributes = custom_data_attributes; MutableSpan<float3> positions = attributes.get<float3>("Position"); MutableSpan<float3> velocities = attributes.get<float3>("Velocity"); + MutableSpan<int32_t> ids = attributes.get<int32_t>("ID"); for (uint i : positions.index_range()) { - positions[i] = {i / 10.0f, 0, 0}; + positions[i] = {i / 100.0f, 0, 0}; velocities[i] = {0, BLI_rng_get_float(rng), BLI_rng_get_float(rng) * 2 + 1}; + ids[i] = i; } } @@ -456,8 +787,14 @@ static void simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulatio MutableSpan<float3> positions = attributes.get<float3>("Position"); MutableSpan<float3> velocities = attributes.get<float3>("Velocity"); + Array<float3> force_vectors{(uint)state->tot_particles, {0, 0, 0}}; + Span<const ParticleForce *> forces = forces_by_simulation.lookup_as(state->head.name); + for (const ParticleForce *force : forces) { + force->add_force(attributes, force_vectors); + } + for (uint i : positions.index_range()) { - velocities[i].z += -1.0f * time_step; + velocities[i] += force_vectors[i] * time_step; positions[i] += velocities[i] * time_step; } } diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index e155dedeef0..0809e8dda6d 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -507,9 +507,7 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack, /* Might not be final place for this to be called - probably only want to call it from some * undo handlers, not all of them? */ - if (BKE_lib_override_library_is_enabled()) { - BKE_lib_override_library_main_operations_create(G_MAIN, false); - } + BKE_lib_override_library_main_operations_create(G_MAIN, false); /* Remove all undos after (also when 'ustack->step_active == NULL'). */ while (ustack->steps.last != ustack->step_active) { |