diff options
Diffstat (limited to 'source/blender/blenkernel')
51 files changed, 1101 insertions, 1083 deletions
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 12d8135ba55..ede300b19dd 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -163,6 +163,30 @@ void BKE_armature_transform(struct bArmature *arm, const float mat[4][4], bool d /* Bounding box. */ struct BoundBox *BKE_armature_boundbox_get(struct Object *ob); +/** + * Calculate the axis-aligned bounds of `pchan` in world-space, + * taking into account custom transform when set. + * + * `r_min` and `r_max` are expanded to fit `pchan` so the caller must initialize them + * (typically using #INIT_MINMAX). + * + * \note The bounds are calculated based on the head & tail of the bone + * or the custom object's bounds (if the bone uses a custom object). + * Visual elements such as the envelopes radius & bendy-bone spline segments are *not* included, + * making this not so useful for viewport culling. + */ +void BKE_pchan_minmax(const struct Object *ob, + const struct bPoseChannel *pchan, + float r_min[3], + float r_max[3]); +/** + * Calculate the axis aligned bounds of the pose of `ob` in world-space. + + * `r_min` and `r_max` are expanded to fit `ob->pose` so the caller must initialize them + * (typically using #INIT_MINMAX). + * + * \note This uses #BKE_pchan_minmax, see its documentation for details on bounds calculation. + */ bool BKE_pose_minmax( struct Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select); diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h index 6020da08f51..ff207997e79 100644 --- a/source/blender/blenkernel/BKE_attribute.h +++ b/source/blender/blenkernel/BKE_attribute.h @@ -40,11 +40,11 @@ struct ReportList; /* Attribute.domain */ typedef enum AttributeDomain { ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */ - ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */ + ATTR_DOMAIN_POINT = 0, /* Mesh, Curve or Point Cloud Point */ ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */ ATTR_DOMAIN_FACE = 2, /* Mesh Face */ ATTR_DOMAIN_CORNER = 3, /* Mesh Corner */ - ATTR_DOMAIN_CURVE = 4, /* Hair Curve */ + ATTR_DOMAIN_CURVE = 4, /* A single curve in a larger curve data-block */ ATTR_DOMAIN_INSTANCE = 5, /* Instance */ ATTR_DOMAIN_NUM diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index fe656166ada..1ba887903c8 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 2 +#define BLENDER_FILE_SUBVERSION 3 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_curves.h b/source/blender/blenkernel/BKE_curves.h new file mode 100644 index 00000000000..99839b20121 --- /dev/null +++ b/source/blender/blenkernel/BKE_curves.h @@ -0,0 +1,68 @@ +/* + * 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. + */ + +#pragma once + +/** \file + * \ingroup bke + * \brief Low-level operations for curves. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct BoundBox; +struct CustomDataLayer; +struct Depsgraph; +struct Curves; +struct Main; +struct Object; +struct Scene; + +void *BKE_curves_add(struct Main *bmain, const char *name); + +struct BoundBox *BKE_curves_boundbox_get(struct Object *ob); + +void BKE_curves_update_customdata_pointers(struct Curves *curves); +bool BKE_curves_customdata_required(struct Curves *curves, struct CustomDataLayer *layer); + +/* Depsgraph */ + +struct Curves *BKE_curves_new_for_eval(const struct Curves *curves_src, + int totpoint, + int totcurve); +struct Curves *BKE_curves_copy_for_eval(struct Curves *curves_src, bool reference); + +void BKE_curves_data_update(struct Depsgraph *depsgraph, + struct Scene *scene, + struct Object *object); + +/* Draw Cache */ + +enum { + BKE_CURVES_BATCH_DIRTY_ALL = 0, +}; + +void BKE_curves_batch_cache_dirty_tag(struct Curves *curves, int mode); +void BKE_curves_batch_cache_free(struct Curves *curves); + +extern void (*BKE_curves_batch_cache_dirty_tag_cb)(struct Curves *curves, int mode); +extern void (*BKE_curves_batch_cache_free_cb)(struct Curves *curves); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index ab7961c479e..6397298c904 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -199,6 +199,17 @@ void BKE_gpencil_stroke_copy_settings(const struct bGPDstroke *gpf_src, struct bGPDstroke *gpf_dst); /** + * Make a copy of a given gpencil frame settings. + */ +void BKE_gpencil_frame_copy_settings(const struct bGPDframe *gpf_src, struct bGPDframe *gpf_dst); + +/** + * Make a copy of a given gpencil stroke settings. + */ +void BKE_gpencil_stroke_copy_settings(const struct bGPDstroke *gpf_src, + struct bGPDstroke *gpf_dst); + +/** * Make a copy of strokes between gpencil frames. * \param gpf_src: Source grease pencil frame * \param gpf_dst: Destination grease pencil frame @@ -742,7 +753,7 @@ int BKE_gpencil_material_find_index_by_name_prefix(struct Object *ob, const char void BKE_gpencil_blend_read_data(struct BlendDataReader *reader, struct bGPdata *gpd); -bool BKE_gpencil_update_on_write_check(const struct Depsgraph *depsgraph, struct bGPdata *gpd); +bool BKE_gpencil_can_avoid_full_copy_on_write(const struct Depsgraph *depsgraph, struct bGPdata *gpd); void BKE_gpencil_update_on_write(struct bGPdata *gpd_orig, struct bGPdata *gpd_eval); diff --git a/source/blender/blenkernel/BKE_gpencil_update_cache.h b/source/blender/blenkernel/BKE_gpencil_update_cache.h index 3f491c266b4..3ac78267922 100644 --- a/source/blender/blenkernel/BKE_gpencil_update_cache.h +++ b/source/blender/blenkernel/BKE_gpencil_update_cache.h @@ -13,7 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * The Original Code is Copyright (C) 2008, Blender Foundation + * The Original Code is Copyright (C) 2022, Blender Foundation * This is a new part of Blender */ @@ -83,9 +83,11 @@ typedef struct GPencilUpdateCacheNode { } GPencilUpdateCacheNode; /** - * Callback that is called in BKE_gpencil_traverse_update_cache at each level. + * Callback that is called in BKE_gpencil_traverse_update_cache at each level. If the callback + * returns true, then the children will not be iterated over and instead continue. * \param cache: The cache at this level. * \param user_data: Pointer to the user_data passed to BKE_gpencil_traverse_update_cache. + * \returns true, if iterating over the children of \a cache should be skipped, false if not. */ typedef bool (*GPencilUpdateCacheIter_Cb)(GPencilUpdateCache *cache, void *user_data); @@ -140,31 +142,11 @@ void BKE_gpencil_tag_light_update(struct bGPdata *gpd, struct bGPDstroke *gps); /** - * - */ -GPencilUpdateCache *BKE_gpencil_duplicate_update_cache_and_data(GPencilUpdateCache *gpd_cache); - -/** - * - */ -bool BKE_gpencil_compare_update_caches(GPencilUpdateCache *cache_a, GPencilUpdateCache *cache_b); - -/** * Frees the GPencilUpdateCache on the gpd->runtime. This will not free the data that the cache * node might point to. It assumes that the cache does not own the data. */ void BKE_gpencil_free_update_cache(struct bGPdata *gpd); -/** - * - */ -void BKE_gpencil_free_update_cache_and_data(GPencilUpdateCache *cache); - -/** - * - */ -void BKE_gpencil_print_update_cache(struct GPencilUpdateCache *cache); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h deleted file mode 100644 index 403e461a9dc..00000000000 --- a/source/blender/blenkernel/BKE_hair.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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. - */ - -#pragma once - -/** \file - * \ingroup bke - * \brief General operations for hairs. - */ -#ifdef __cplusplus -extern "C" { -#endif - -struct BoundBox; -struct CustomDataLayer; -struct Depsgraph; -struct Hair; -struct Main; -struct Object; -struct Scene; - -void *BKE_hair_add(struct Main *bmain, const char *name); - -struct BoundBox *BKE_hair_boundbox_get(struct Object *ob); - -void BKE_hair_update_customdata_pointers(struct Hair *hair); -bool BKE_hair_customdata_required(struct Hair *hair, struct CustomDataLayer *layer); - -/* Depsgraph */ - -struct Hair *BKE_hair_new_for_eval(const struct Hair *hair_src, int totpoint, int totcurve); -struct Hair *BKE_hair_copy_for_eval(struct Hair *hair_src, bool reference); - -void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *object); - -/* Draw Cache */ - -enum { - BKE_HAIR_BATCH_DIRTY_ALL = 0, -}; - -void BKE_hair_batch_cache_dirty_tag(struct Hair *hair, int mode); -void BKE_hair_batch_cache_free(struct Hair *hair); - -extern void (*BKE_hair_batch_cache_dirty_tag_cb)(struct Hair *hair, int mode); -extern void (*BKE_hair_batch_cache_free_cb)(struct Hair *hair); - -#ifdef __cplusplus -} -#endif diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h index df50f773a46..e9e5b183e4a 100644 --- a/source/blender/blenkernel/BKE_idtype.h +++ b/source/blender/blenkernel/BKE_idtype.h @@ -278,7 +278,7 @@ extern IDTypeInfo IDType_ID_PC; extern IDTypeInfo IDType_ID_CF; extern IDTypeInfo IDType_ID_WS; extern IDTypeInfo IDType_ID_LP; -extern IDTypeInfo IDType_ID_HA; +extern IDTypeInfo IDType_ID_CV; extern IDTypeInfo IDType_ID_PT; extern IDTypeInfo IDType_ID_VO; extern IDTypeInfo IDType_ID_SIM; diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index e8065566c97..c81616110cc 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -103,8 +103,12 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain, * \param owner_library: the library in which the overrides should be created. Besides versioning * and resync code path, this should always be NULL (i.e. the local .blend file). * - * \param reference_library: the library from which the linked data being overridden come from - * (i.e. the library of the linked reference ID). + * \param id_root_reference: the linked ID that is considered as the root of the overridden + * hierarchy. + * + * \param id_hierarchy_root: the override ID that is the root of the hierarchy. May be NULL, in + * which case it is assumed that the given `id_root_reference` is tagged for override, and its + * newly created override will be used as hierarchy root. * * \param do_no_main: Create the new override data outside of Main database. * Used for resyncing of linked overrides. @@ -113,7 +117,8 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain, */ bool BKE_lib_override_library_create_from_tag(struct Main *bmain, struct Library *owner_library, - const struct Library *reference_library, + const struct ID *id_root_reference, + struct ID *id_hierarchy_root, bool do_no_main); /** * Advanced 'smart' function to create fully functional overrides. @@ -172,6 +177,15 @@ bool BKE_lib_override_library_proxy_convert(struct Main *bmain, */ void BKE_lib_override_library_main_proxy_convert(struct Main *bmain, struct BlendFileReadReport *reports); + +/** + * Find and set the 'hierarchy root' ID pointer of all library overrides in given `bmain`. + * + * NOTE: Cannot be called from `do_versions_after_linking` as this code needs a single complete + * Main database, not a split-by-libraries one. + */ +void BKE_lib_override_library_main_hierarchy_root_ensure(struct Main *bmain); + /** * Advanced 'smart' function to resync, re-create fully functional overrides up-to-date with linked * data, from an existing override hierarchy. diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 4c6eb31db4b..e4f94110eb1 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -182,7 +182,11 @@ typedef struct Main { ListBase linestyles; ListBase cachefiles; ListBase workspaces; - ListBase hairs; + /** + * \note The name `hair_curves` is chosen to be different than `curves`, + * but they are generic curve data-blocks, not just for hair. + */ + ListBase hair_curves; ListBase pointclouds; ListBase volumes; ListBase simulations; diff --git a/source/blender/blenkernel/BKE_mesh_fair.h b/source/blender/blenkernel/BKE_mesh_fair.h index c4c1af054f0..2884de6d5c1 100644 --- a/source/blender/blenkernel/BKE_mesh_fair.h +++ b/source/blender/blenkernel/BKE_mesh_fair.h @@ -12,15 +12,14 @@ * 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. - * - * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing": - * https://github.com/fedackb/mesh-fairing. */ #pragma once /** \file * \ingroup bke + * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing": + * https://github.com/fedackb/mesh-fairing. */ #include "BLI_utildefines.h" diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index d583b5f0648..359a5662a13 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -274,6 +274,9 @@ typedef struct bNodeType { char *label, int maxlen); + /** Optional override for node class, used for drawing node header. */ + int (*ui_class)(const struct bNode *node); + /** Called when the node is updated in the editor. */ void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node); /** Check and update if internal ID data has changed. */ @@ -1300,12 +1303,13 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i /* filter types */ #define CMP_FILT_SOFT 0 -#define CMP_FILT_SHARP 1 +#define CMP_FILT_SHARP_BOX 1 #define CMP_FILT_LAPLACE 2 #define CMP_FILT_SOBEL 3 #define CMP_FILT_PREWITT 4 #define CMP_FILT_KIRSCH 5 #define CMP_FILT_SHADOW 6 +#define CMP_FILT_SHARP_DIAMOND 7 /* scale node type, in custom1 */ #define CMP_SCALE_RELATIVE 0 diff --git a/source/blender/blenkernel/BKE_node_tree_update.h b/source/blender/blenkernel/BKE_node_tree_update.h index 443ceafb073..834445420ef 100644 --- a/source/blender/blenkernel/BKE_node_tree_update.h +++ b/source/blender/blenkernel/BKE_node_tree_update.h @@ -60,6 +60,8 @@ void BKE_ntree_update_tag_link_removed(struct bNodeTree *ntree); void BKE_ntree_update_tag_link_added(struct bNodeTree *ntree, struct bNodeLink *link); void BKE_ntree_update_tag_link_mute(struct bNodeTree *ntree, struct bNodeLink *link); +/** Used when the a new output node becomes active and therefore changes the output. */ +void BKE_ntree_update_tag_active_output_changed(struct bNodeTree *ntree); /** Used after file loading when run-time data on the tree has not been initialized yet. */ void BKE_ntree_update_tag_missing_runtime_data(struct bNodeTree *ntree); /** Used when the interface sockets/values have changed. */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 4b8c7f9c984..2012f749234 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -433,7 +433,7 @@ void BKE_object_eval_constraints(struct Depsgraph *depsgraph, struct Object *ob); void BKE_object_eval_transform_final(struct Depsgraph *depsgraph, struct Object *ob); -void BKE_object_eval_uber_transform(struct Depsgraph *depsgraph, struct Object *ob); +void BKE_object_eval_uber_transform(struct Depsgraph *depsgraph, struct Object *object); void BKE_object_eval_uber_data(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 804331a3412..b5e60da540e 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -13,11 +13,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * The Original Code is Copyright (C) 2007 by Janne Karhu. - * All rights reserved. - * Adaptive time step - * Classical SPH - * Copyright 2011-2012 AutoCRC + * Copyright 2007 Janne Karhu. All rights reserved. + * 2011-2012 AutoCRC (adaptive time step, Classical SPH). */ #pragma once diff --git a/source/blender/blenkernel/BKE_subdiv_foreach.h b/source/blender/blenkernel/BKE_subdiv_foreach.h index 7d9a589666a..001a4f9401b 100644 --- a/source/blender/blenkernel/BKE_subdiv_foreach.h +++ b/source/blender/blenkernel/BKE_subdiv_foreach.h @@ -74,6 +74,7 @@ typedef void (*SubdivForeachEdgeCb)(const struct SubdivForeachContext *context, void *tls, int coarse_edge_index, int subdiv_edge_index, + bool is_loose, int subdiv_v1, int subdiv_v2); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 7309caa97b0..1483466061f 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -119,6 +119,7 @@ set(SRC intern/crazyspace.c intern/cryptomatte.cc intern/curve.cc + intern/curves.cc intern/curve_bevel.c intern/curve_convert.c intern/curve_decimate.c @@ -157,7 +158,6 @@ set(SRC intern/gpencil_geom.cc intern/gpencil_modifier.c intern/gpencil_update_cache.c - intern/hair.cc intern/icons.cc intern/icons_rasterize.c intern/idprop.c @@ -357,6 +357,7 @@ set(SRC BKE_cryptomatte.h BKE_cryptomatte.hh BKE_curve.h + BKE_curves.h BKE_curve_to_mesh.hh BKE_curveprofile.h BKE_customdata.h @@ -386,7 +387,6 @@ set(SRC BKE_gpencil_geom.h BKE_gpencil_modifier.h BKE_gpencil_update_cache.h - BKE_hair.h BKE_icons.h BKE_idprop.h BKE_idprop.hh diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index 42b72a7cd66..1c0b465d202 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -1284,8 +1284,8 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use /* cache files */ ANIMDATA_IDS_CB(bmain->cachefiles.first); - /* hairs */ - ANIMDATA_IDS_CB(bmain->hairs.first); + /* Hair Curves. */ + ANIMDATA_IDS_CB(bmain->hair_curves.first); /* pointclouds */ ANIMDATA_IDS_CB(bmain->pointclouds.first); @@ -1413,8 +1413,8 @@ void BKE_animdata_fix_paths_rename_all_ex(Main *bmain, /* cache files */ RENAMEFIX_ANIM_IDS(bmain->cachefiles.first); - /* hairs */ - RENAMEFIX_ANIM_IDS(bmain->hairs.first); + /* Hair Curves. */ + RENAMEFIX_ANIM_IDS(bmain->hair_curves.first); /* pointclouds */ RENAMEFIX_ANIM_IDS(bmain->pointclouds.first); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index b5ea68aaadc..c45856adbda 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -3382,8 +3382,8 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float /* cache files */ EVAL_ANIM_IDS(main->cachefiles.first, ADT_RECALC_ANIM); - /* hairs */ - EVAL_ANIM_IDS(main->hairs.first, ADT_RECALC_ANIM); + /* Hair Curves. */ + EVAL_ANIM_IDS(main->hair_curves.first, ADT_RECALC_ANIM); /* pointclouds */ EVAL_ANIM_IDS(main->pointclouds.first, ADT_RECALC_ANIM); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 7feb9d08915..1a9f0a9130d 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2679,6 +2679,35 @@ BoundBox *BKE_armature_boundbox_get(Object *ob) return ob->runtime.bb; } +void BKE_pchan_minmax(const Object *ob, const bPoseChannel *pchan, float r_min[3], float r_max[3]) +{ + const bArmature *arm = ob->data; + const bPoseChannel *pchan_tx = (pchan->custom && pchan->custom_tx) ? pchan->custom_tx : pchan; + const BoundBox *bb_custom = ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) ? + BKE_object_boundbox_get(pchan->custom) : + NULL; + if (bb_custom) { + float mat[4][4], smat[4][4], rmat[4][4], tmp[4][4]; + scale_m4_fl(smat, PCHAN_CUSTOM_BONE_LENGTH(pchan)); + rescale_m4(smat, pchan->custom_scale_xyz); + eulO_to_mat4(rmat, pchan->custom_rotation_euler, ROT_MODE_XYZ); + copy_m4_m4(tmp, pchan_tx->pose_mat); + translate_m4(tmp, + pchan->custom_translation[0], + pchan->custom_translation[1], + pchan->custom_translation[2]); + mul_m4_series(mat, ob->obmat, tmp, rmat, smat); + BKE_boundbox_minmax(bb_custom, mat, r_min, r_max); + } + else { + float vec[3]; + mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head); + minmax_v3v3_v3(r_min, r_max, vec); + mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail); + minmax_v3v3_v3(r_min, r_max, vec); + } +} + bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select) { bool changed = false; @@ -2692,31 +2721,8 @@ bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden * (editarmature.c:2592)... Skip in this case too! */ if (pchan->bone && (!((use_hidden == false) && (PBONE_VISIBLE(arm, pchan->bone) == false)) && !((use_select == true) && ((pchan->bone->flag & BONE_SELECTED) == 0)))) { - bPoseChannel *pchan_tx = (pchan->custom && pchan->custom_tx) ? pchan->custom_tx : pchan; - BoundBox *bb_custom = ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) ? - BKE_object_boundbox_get(pchan->custom) : - NULL; - if (bb_custom) { - float mat[4][4], smat[4][4], rmat[4][4], tmp[4][4]; - scale_m4_fl(smat, PCHAN_CUSTOM_BONE_LENGTH(pchan)); - rescale_m4(smat, pchan->custom_scale_xyz); - eulO_to_mat4(rmat, pchan->custom_rotation_euler, ROT_MODE_XYZ); - copy_m4_m4(tmp, pchan_tx->pose_mat); - translate_m4(tmp, - pchan->custom_translation[0], - pchan->custom_translation[1], - pchan->custom_translation[2]); - mul_m4_series(mat, ob->obmat, tmp, rmat, smat); - BKE_boundbox_minmax(bb_custom, mat, r_min, r_max); - } - else { - float vec[3]; - mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head); - minmax_v3v3_v3(r_min, r_max, vec); - mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail); - minmax_v3v3_v3(r_min, r_max, vec); - } + BKE_pchan_minmax(ob, pchan, r_min, r_max); changed = true; } } diff --git a/source/blender/blenkernel/intern/armature_pose.cc b/source/blender/blenkernel/intern/armature_pose.cc index a62a32d9633..de26b997e76 100644 --- a/source/blender/blenkernel/intern/armature_pose.cc +++ b/source/blender/blenkernel/intern/armature_pose.cc @@ -15,8 +15,6 @@ * * The Original Code is Copyright (C) 2015 Blender Foundation. * All rights reserved. - * - * Defines and code for core node types */ /** \file diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 73a396b2cdd..f19065f039b 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -15,8 +15,6 @@ * * The Original Code is Copyright (C) 2015 Blender Foundation. * All rights reserved. - * - * Defines and code for core node types */ /** \file diff --git a/source/blender/blenkernel/intern/attribute.c b/source/blender/blenkernel/intern/attribute.c index 73e00398084..fdd84f3dfd4 100644 --- a/source/blender/blenkernel/intern/attribute.c +++ b/source/blender/blenkernel/intern/attribute.c @@ -15,13 +15,12 @@ * * The Original Code is Copyright (C) 2006 Blender Foundation. * All rights reserved. - * - * Implementation of generic geometry attributes management. This is built - * on top of CustomData, which manages individual domains. */ /** \file * \ingroup bke + * Implementation of generic geometry attributes management. This is built + * on top of CustomData, which manages individual domains. */ #include <string.h> @@ -29,8 +28,8 @@ #include "MEM_guardedalloc.h" #include "DNA_ID.h" +#include "DNA_curves_types.h" #include "DNA_customdata_types.h" -#include "DNA_hair_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_pointcloud_types.h" @@ -38,9 +37,9 @@ #include "BLI_string_utf8.h" #include "BKE_attribute.h" +#include "BKE_curves.h" #include "BKE_customdata.h" #include "BKE_editmesh.h" -#include "BKE_hair.h" #include "BKE_pointcloud.h" #include "BKE_report.h" @@ -88,12 +87,12 @@ static void get_domains(const ID *id, DomainInfo info[ATTR_DOMAIN_NUM]) } break; } - case ID_HA: { - Hair *hair = (Hair *)id; - info[ATTR_DOMAIN_POINT].customdata = &hair->geometry.point_data; - info[ATTR_DOMAIN_POINT].length = hair->geometry.point_size; - info[ATTR_DOMAIN_CURVE].customdata = &hair->geometry.curve_data; - info[ATTR_DOMAIN_CURVE].length = hair->geometry.curve_size; + case ID_CV: { + Curves *curves = (Curves *)id; + info[ATTR_DOMAIN_POINT].customdata = &curves->geometry.point_data; + info[ATTR_DOMAIN_POINT].length = curves->geometry.point_size; + info[ATTR_DOMAIN_CURVE].customdata = &curves->geometry.curve_data; + info[ATTR_DOMAIN_CURVE].length = curves->geometry.curve_size; break; } default: @@ -301,8 +300,8 @@ bool BKE_id_attribute_required(ID *id, CustomDataLayer *layer) case ID_PT: { return BKE_pointcloud_customdata_required((PointCloud *)id, layer); } - case ID_HA: { - return BKE_hair_customdata_required((Hair *)id, layer); + case ID_CV: { + return BKE_curves_customdata_required((Curves *)id, layer); } default: return false; @@ -372,8 +371,8 @@ int *BKE_id_attributes_active_index_p(ID *id) case ID_ME: { return &((Mesh *)id)->attributes_active_index; } - case ID_HA: { - return &((Hair *)id)->attributes_active_index; + case ID_CV: { + return &((Curves *)id)->attributes_active_index; } default: return NULL; diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 86c2593e2e6..07fd859765a 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -374,6 +374,10 @@ static void setup_app_data(bContext *C, BKE_lib_override_library_main_proxy_convert(bmain, reports); } + if (mode != LOAD_UNDO && !blendfile_or_libraries_versions_atleast(bmain, 302, 3)) { + BKE_lib_override_library_main_hierarchy_root_ensure(bmain); + } + bmain->recovered = 0; /* startup.blend or recovered startup */ diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 275500ba2f6..d8ad4dd89e4 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -15,13 +15,12 @@ * * The Original Code is Copyright (C) 2006 Blender Foundation. * All rights reserved. - * Implementation of CDDerivedMesh. - * - * BKE_cdderivedmesh.h contains the function prototypes for this file. */ /** \file * \ingroup bke + * Implementation of #CDDerivedMesh. + * BKE_cdderivedmesh.h contains the function prototypes for this file. */ #include "atomic_ops.h" diff --git a/source/blender/blenkernel/intern/curve.cc b/source/blender/blenkernel/intern/curve.cc index dda2b5076a8..c611e280793 100644 --- a/source/blender/blenkernel/intern/curve.cc +++ b/source/blender/blenkernel/intern/curve.cc @@ -32,6 +32,7 @@ #include "BLI_ghash.h" #include "BLI_index_range.hh" #include "BLI_math.h" +#include "BLI_math_vec_types.hh" #include "BLI_utildefines.h" #include "BLT_translation.h" @@ -59,6 +60,7 @@ #include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_object.h" +#include "BKE_spline.hh" #include "BKE_vfont.h" #include "DEG_depsgraph.h" @@ -68,6 +70,7 @@ #include "BLO_read_write.h" +using blender::float3; using blender::IndexRange; /* globals */ @@ -503,7 +506,10 @@ BoundBox *BKE_curve_boundbox_get(Object *ob) float min[3], max[3]; INIT_MINMAX(min, max); - BKE_curve_minmax(cu, true, min, max); + if (!BKE_curve_minmax(cu, true, min, max)) { + copy_v3_fl(min, -1.0f); + copy_v3_fl(max, 1.0f); + } if (ob->runtime.bb == nullptr) { ob->runtime.bb = (BoundBox *)MEM_mallocN(sizeof(*ob->runtime.bb), __func__); diff --git a/source/blender/blenkernel/intern/curves.cc b/source/blender/blenkernel/intern/curves.cc new file mode 100644 index 00000000000..f5672e9b288 --- /dev/null +++ b/source/blender/blenkernel/intern/curves.cc @@ -0,0 +1,473 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup bke + */ + +#include <cmath> +#include <cstring> + +#include "MEM_guardedalloc.h" + +#include "DNA_curves_types.h" +#include "DNA_defaults.h" +#include "DNA_material_types.h" +#include "DNA_object_types.h" + +#include "BLI_index_range.hh" +#include "BLI_listbase.h" +#include "BLI_math_base.h" +#include "BLI_math_vec_types.hh" +#include "BLI_rand.hh" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BKE_anim_data.h" +#include "BKE_curves.h" +#include "BKE_customdata.h" +#include "BKE_global.h" +#include "BKE_idtype.h" +#include "BKE_lib_id.h" +#include "BKE_lib_query.h" +#include "BKE_lib_remap.h" +#include "BKE_main.h" +#include "BKE_modifier.h" +#include "BKE_object.h" + +#include "BLT_translation.h" + +#include "DEG_depsgraph_query.h" + +#include "BLO_read_write.h" + +using blender::float3; +using blender::IndexRange; +using blender::MutableSpan; +using blender::RandomNumberGenerator; + +static const char *ATTR_POSITION = "position"; +static const char *ATTR_RADIUS = "radius"; + +static void curves_random(Curves *curves); + +static void curves_init_data(ID *id) +{ + Curves *curves = (Curves *)id; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(curves, id)); + + MEMCPY_STRUCT_AFTER(curves, DNA_struct_default_get(Curves), id); + + CustomData_reset(&curves->geometry.point_data); + CustomData_reset(&curves->geometry.curve_data); + + CustomData_add_layer_named(&curves->geometry.point_data, + CD_PROP_FLOAT3, + CD_CALLOC, + nullptr, + curves->geometry.point_size, + ATTR_POSITION); + CustomData_add_layer_named(&curves->geometry.point_data, + CD_PROP_FLOAT, + CD_CALLOC, + nullptr, + curves->geometry.point_size, + ATTR_RADIUS); + + BKE_curves_update_customdata_pointers(curves); + + curves_random(curves); +} + +static void curves_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag) +{ + Curves *curves_dst = (Curves *)id_dst; + const Curves *curves_src = (const Curves *)id_src; + curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat)); + + curves_dst->geometry.point_size = curves_src->geometry.point_size; + curves_dst->geometry.curve_size = curves_src->geometry.curve_size; + + const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE; + CustomData_copy(&curves_src->geometry.point_data, + &curves_dst->geometry.point_data, + CD_MASK_ALL, + alloc_type, + curves_dst->geometry.point_size); + CustomData_copy(&curves_src->geometry.curve_data, + &curves_dst->geometry.curve_data, + CD_MASK_ALL, + alloc_type, + curves_dst->geometry.curve_size); + BKE_curves_update_customdata_pointers(curves_dst); + + curves_dst->geometry.offsets = static_cast<int *>(MEM_dupallocN(curves_src->geometry.offsets)); + + curves_dst->batch_cache = nullptr; +} + +static void curves_free_data(ID *id) +{ + Curves *curves = (Curves *)id; + BKE_animdata_free(&curves->id, false); + + BKE_curves_batch_cache_free(curves); + + CustomData_free(&curves->geometry.point_data, curves->geometry.point_size); + CustomData_free(&curves->geometry.curve_data, curves->geometry.curve_size); + + MEM_SAFE_FREE(curves->geometry.offsets); + + MEM_SAFE_FREE(curves->mat); +} + +static void curves_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Curves *curves = (Curves *)id; + for (int i = 0; i < curves->totcol; i++) { + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, curves->mat[i], IDWALK_CB_USER); + } +} + +static void curves_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Curves *curves = (Curves *)id; + + CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *clayers = nullptr, clayers_buff[CD_TEMP_CHUNK_SIZE]; + CustomData_blend_write_prepare( + &curves->geometry.point_data, &players, players_buff, ARRAY_SIZE(players_buff)); + CustomData_blend_write_prepare( + &curves->geometry.curve_data, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff)); + + /* Write LibData */ + BLO_write_id_struct(writer, Curves, id_address, &curves->id); + BKE_id_blend_write(writer, &curves->id); + + /* Direct data */ + CustomData_blend_write(writer, + &curves->geometry.point_data, + players, + curves->geometry.point_size, + CD_MASK_ALL, + &curves->id); + CustomData_blend_write(writer, + &curves->geometry.curve_data, + clayers, + curves->geometry.curve_size, + CD_MASK_ALL, + &curves->id); + + BLO_write_int32_array(writer, curves->geometry.curve_size + 1, curves->geometry.offsets); + + BLO_write_pointer_array(writer, curves->totcol, curves->mat); + if (curves->adt) { + BKE_animdata_blend_write(writer, curves->adt); + } + + /* Remove temporary data. */ + if (players && players != players_buff) { + MEM_freeN(players); + } + if (clayers && clayers != clayers_buff) { + MEM_freeN(clayers); + } +} + +static void curves_blend_read_data(BlendDataReader *reader, ID *id) +{ + Curves *curves = (Curves *)id; + BLO_read_data_address(reader, &curves->adt); + BKE_animdata_blend_read_data(reader, curves->adt); + + /* Geometry */ + CustomData_blend_read(reader, &curves->geometry.point_data, curves->geometry.point_size); + CustomData_blend_read(reader, &curves->geometry.curve_data, curves->geometry.point_size); + BKE_curves_update_customdata_pointers(curves); + + BLO_read_int32_array(reader, curves->geometry.curve_size + 1, &curves->geometry.offsets); + + /* Materials */ + BLO_read_pointer_array(reader, (void **)&curves->mat); +} + +static void curves_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Curves *curves = (Curves *)id; + for (int a = 0; a < curves->totcol; a++) { + BLO_read_id_address(reader, curves->id.lib, &curves->mat[a]); + } +} + +static void curves_blend_read_expand(BlendExpander *expander, ID *id) +{ + Curves *curves = (Curves *)id; + for (int a = 0; a < curves->totcol; a++) { + BLO_expand(expander, curves->mat[a]); + } +} + +IDTypeInfo IDType_ID_CV = { + /*id_code */ ID_CV, + /*id_filter */ FILTER_ID_CV, + /*main_listbase_index */ INDEX_ID_CV, + /*struct_size */ sizeof(Curves), + /*name */ "Hair Curves", + /*name_plural */ "Hair Curves", + /*translation_context */ BLT_I18NCONTEXT_ID_CURVES, + /*flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE, + /*asset_type_info */ nullptr, + + /*init_data */ curves_init_data, + /*copy_data */ curves_copy_data, + /*free_data */ curves_free_data, + /*make_local */ nullptr, + /*foreach_id */ curves_foreach_id, + /*foreach_cache */ nullptr, + /*foreach_path */ nullptr, + /*owner_get */ nullptr, + + /*blend_write */ curves_blend_write, + /*blend_read_data */ curves_blend_read_data, + /*blend_read_lib */ curves_blend_read_lib, + /*blend_read_expand */ curves_blend_read_expand, + + /*blend_read_undo_preserve */ nullptr, + + /*lib_override_apply_post */ nullptr, +}; + +static void curves_random(Curves *curves) +{ + CurvesGeometry &geometry = curves->geometry; + const int numpoints = 8; + + geometry.curve_size = 500; + + geometry.curve_size = 500; + geometry.point_size = geometry.curve_size * numpoints; + + curves->geometry.offsets = (int *)MEM_calloc_arrayN( + curves->geometry.curve_size + 1, sizeof(int), __func__); + CustomData_realloc(&geometry.point_data, geometry.point_size); + CustomData_realloc(&geometry.curve_data, geometry.curve_size); + BKE_curves_update_customdata_pointers(curves); + + MutableSpan<int> offsets{geometry.offsets, geometry.curve_size + 1}; + MutableSpan<float3> positions{(float3 *)geometry.position, geometry.point_size}; + MutableSpan<float> radii{geometry.radius, geometry.point_size}; + + for (const int i : offsets.index_range()) { + geometry.offsets[i] = numpoints * i; + } + + RandomNumberGenerator rng; + + for (int i = 0; i < geometry.curve_size; i++) { + const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]); + MutableSpan<float3> curve_positions = positions.slice(curve_range); + MutableSpan<float> curve_radii = radii.slice(curve_range); + + const float theta = 2.0f * M_PI * rng.get_float(); + const float phi = saacosf(2.0f * rng.get_float() - 1.0f); + + float3 no = {std::sin(theta) * std::sin(phi), std::cos(theta) * std::sin(phi), std::cos(phi)}; + no = blender::math::normalize(no); + + float3 co = no; + for (int key = 0; key < numpoints; key++) { + float t = key / (float)(numpoints - 1); + curve_positions[key] = co; + curve_radii[key] = 0.02f * (1.0f - t); + + float3 offset = float3(rng.get_float(), rng.get_float(), rng.get_float()) * 2.0f - 1.0f; + co += (offset + no) / numpoints; + } + } +} + +void *BKE_curves_add(Main *bmain, const char *name) +{ + Curves *curves = static_cast<Curves *>(BKE_id_new(bmain, ID_CV, name)); + + return curves; +} + +BoundBox *BKE_curves_boundbox_get(Object *ob) +{ + BLI_assert(ob->type == OB_CURVES); + Curves *curves = static_cast<Curves *>(ob->data); + + if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) { + return ob->runtime.bb; + } + + if (ob->runtime.bb == nullptr) { + ob->runtime.bb = MEM_cnew<BoundBox>(__func__); + + float min[3], max[3]; + INIT_MINMAX(min, max); + + float(*curves_co)[3] = curves->geometry.position; + float *curves_radius = curves->geometry.radius; + for (int a = 0; a < curves->geometry.point_size; a++) { + float *co = curves_co[a]; + float radius = (curves_radius) ? curves_radius[a] : 0.0f; + const float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius}; + const float co_max[3] = {co[0] + radius, co[1] + radius, co[2] + radius}; + DO_MIN(co_min, min); + DO_MAX(co_max, max); + } + + BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max); + } + + return ob->runtime.bb; +} + +void BKE_curves_update_customdata_pointers(Curves *curves) +{ + curves->geometry.position = (float(*)[3])CustomData_get_layer_named( + &curves->geometry.point_data, CD_PROP_FLOAT3, ATTR_POSITION); + curves->geometry.radius = (float *)CustomData_get_layer_named( + &curves->geometry.point_data, CD_PROP_FLOAT, ATTR_RADIUS); +} + +bool BKE_curves_customdata_required(Curves *UNUSED(curves), CustomDataLayer *layer) +{ + return layer->type == CD_PROP_FLOAT3 && STREQ(layer->name, ATTR_POSITION); +} + +/* Dependency Graph */ + +Curves *BKE_curves_new_for_eval(const Curves *curves_src, int totpoint, int totcurve) +{ + Curves *curves_dst = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr)); + + STRNCPY(curves_dst->id.name, curves_src->id.name); + curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat)); + curves_dst->totcol = curves_src->totcol; + + curves_dst->geometry.point_size = totpoint; + curves_dst->geometry.curve_size = totcurve; + CustomData_copy(&curves_src->geometry.point_data, + &curves_dst->geometry.point_data, + CD_MASK_ALL, + CD_CALLOC, + totpoint); + CustomData_copy(&curves_src->geometry.curve_data, + &curves_dst->geometry.curve_data, + CD_MASK_ALL, + CD_CALLOC, + totcurve); + BKE_curves_update_customdata_pointers(curves_dst); + + return curves_dst; +} + +Curves *BKE_curves_copy_for_eval(Curves *curves_src, bool reference) +{ + int flags = LIB_ID_COPY_LOCALIZE; + + if (reference) { + flags |= LIB_ID_COPY_CD_REFERENCE; + } + + Curves *result = (Curves *)BKE_id_copy_ex(nullptr, &curves_src->id, nullptr, flags); + return result; +} + +static Curves *curves_evaluate_modifiers(struct Depsgraph *depsgraph, + struct Scene *scene, + Object *object, + Curves *curves_input) +{ + Curves *curves = curves_input; + + /* Modifier evaluation modes. */ + const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; + ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE; + const ModifierEvalContext mectx = {depsgraph, object, apply_flag}; + + /* Get effective list of modifiers to execute. Some effects like shape keys + * are added as virtual modifiers before the user created modifiers. */ + VirtualModifierData virtualModifierData; + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData); + + /* Evaluate modifiers. */ + for (; md; md = md->next) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast<ModifierType>(md->type)); + + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { + continue; + } + + if ((mti->type == eModifierTypeType_OnlyDeform) && + (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) { + /* Ensure we are not modifying the input. */ + if (curves == curves_input) { + curves = BKE_curves_copy_for_eval(curves, true); + } + + /* Ensure we are not overwriting referenced data. */ + CustomData_duplicate_referenced_layer_named(&curves->geometry.point_data, + CD_PROP_FLOAT3, + ATTR_POSITION, + curves->geometry.point_size); + BKE_curves_update_customdata_pointers(curves); + + /* Created deformed coordinates array on demand. */ + mti->deformVerts( + md, &mectx, nullptr, curves->geometry.position, curves->geometry.point_size); + } + } + + return curves; +} + +void BKE_curves_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object) +{ + /* Free any evaluated data and restore original data. */ + BKE_object_free_derived_caches(object); + + /* Evaluate modifiers. */ + Curves *curves = static_cast<Curves *>(object->data); + Curves *curves_eval = curves_evaluate_modifiers(depsgraph, scene, object, curves); + + /* Assign evaluated object. */ + const bool is_owned = (curves != curves_eval); + BKE_object_eval_assign_data(object, &curves_eval->id, is_owned); +} + +/* Draw Cache */ + +void (*BKE_curves_batch_cache_dirty_tag_cb)(Curves *curves, int mode) = nullptr; +void (*BKE_curves_batch_cache_free_cb)(Curves *curves) = nullptr; + +void BKE_curves_batch_cache_dirty_tag(Curves *curves, int mode) +{ + if (curves->batch_cache) { + BKE_curves_batch_cache_dirty_tag_cb(curves, mode); + } +} + +void BKE_curves_batch_cache_free(Curves *curves) +{ + if (curves->batch_cache) { + BKE_curves_batch_cache_free_cb(curves); + } +} diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 36d511422aa..6db5ae7567f 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -15,13 +15,13 @@ * * The Original Code is Copyright (C) 2006 Blender Foundation. * All rights reserved. - * Implementation of CustomData. - * - * BKE_customdata.h contains the function prototypes for this file. */ /** \file * \ingroup bke + * Implementation of CustomData. + * + * BKE_customdata.h contains the function prototypes for this file. */ #include "MEM_guardedalloc.h" @@ -31,7 +31,6 @@ #include "DNA_ID.h" #include "DNA_customdata_types.h" -#include "DNA_hair_types.h" #include "DNA_meshdata_types.h" #include "BLI_bitmap.h" diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index ceb1195e817..c4e0b924ffa 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -1076,6 +1076,32 @@ void BKE_gpencil_stroke_copy_settings(const bGPDstroke *gps_src, bGPDstroke *gps copy_v4_v4(gps_dst->vert_color_fill, gps_src->vert_color_fill); } +bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy) +{ + gpf_dst->flag = gpf_src->flag; + gpf_dst->key_type = gpf_src->key_type; + gpf_dst->framenum = gpf_src->framenum; +} + +void BKE_gpencil_stroke_copy_settings(const bGPDstroke *gps_src, bGPDstroke *gps_dst) +{ + gps_dst->thickness = gps_src->thickness; + gps_dst->flag = gps_src->flag; + gps_dst->inittime = gps_src->inittime; + gps_dst->mat_nr = gps_src->mat_nr; + copy_v2_v2_short(gps_dst->caps, gps_src->caps); + gps_dst->hardeness = gps_src->hardeness; + copy_v2_v2(gps_dst->aspect_ratio, gps_src->aspect_ratio); + gps_dst->fill_opacity_fac = gps_dst->fill_opacity_fac; + copy_v3_v3(gps_dst->boundbox_min, gps_src->boundbox_min); + copy_v3_v3(gps_dst->boundbox_max, gps_src->boundbox_max); + gps_dst->uv_rotation = gps_src->uv_rotation; + copy_v2_v2(gps_dst->uv_translation, gps_src->uv_translation); + gps_dst->uv_scale = gps_src->uv_scale; + gps_dst->select_index = gps_src->select_index; + copy_v4_v4(gps_dst->vert_color_fill, gps_src->vert_color_fill); +} + void BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bGPdata **gpd_dst) { /* error checking */ @@ -2834,12 +2860,8 @@ void BKE_gpencil_frame_selected_hash(bGPdata *gpd, struct GHash *r_list) } } -bool BKE_gpencil_update_on_write_check(const Depsgraph *depsgraph, bGPdata *gpd) +bool BKE_gpencil_can_avoid_full_copy_on_write(const Depsgraph *depsgraph, bGPdata *gpd) { - if (!U.experimental.use_gpencil_update_cache) { - return false; - } - /* For now, we only use the update cache in the active depsgraph. Othwerwise we might access the * cache while another depsgraph frees it. */ if (!DEG_is_active(depsgraph)) { @@ -3007,20 +3029,11 @@ void BKE_gpencil_update_on_write(bGPdata *gpd_orig, bGPdata *gpd_eval) }; BKE_gpencil_traverse_update_cache(update_cache, &ts, &data); + gpd_eval->flag |= GP_DATA_CACHE_IS_DIRTY; - const bool gpencil_undo_system_inactive = !(U.experimental.use_gpencil_undo_system && - GPENCIL_ANY_MODE(gpd_orig)); - /* If the gpencil undo system is active, make sure to only free the cache if - * GP_DATA_UPDATE_CACHE_DISPOSABLE is set. Even though we already used the cache to update the - * eval object, it might still be needed for the undo system (e.g if a modal operator is running, - * it might call the update-on-write multiple times before an undo step is encoded). Only when - * the undo system marks the cache as disposable can we safely free it here.*/ - if (gpencil_undo_system_inactive || (gpd_orig->flag & GP_DATA_UPDATE_CACHE_DISPOSABLE)) { - /* TODO: This might cause issues when we have multiple depsgraphs? Because the cache might be - * accessed later/concurrently even if it was freed here? */ - BKE_gpencil_free_update_cache(gpd_orig); - } + /* TODO: This might cause issues when we have multiple depsgraphs? */ + BKE_gpencil_free_update_cache(gpd_orig); } /** \} */ diff --git a/source/blender/blenkernel/intern/gpencil_update_cache.c b/source/blender/blenkernel/intern/gpencil_update_cache.c index 2e42ae40f32..323c3a9f2a2 100644 --- a/source/blender/blenkernel/intern/gpencil_update_cache.c +++ b/source/blender/blenkernel/intern/gpencil_update_cache.c @@ -13,7 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * The Original Code is Copyright (C) 2008, Blender Foundation + * The Original Code is Copyright (C) 2022, Blender Foundation * This is a new part of Blender */ @@ -88,40 +88,22 @@ static void cache_node_update(void *node, void *data) GPencilUpdateCache *update_cache = ((GPencilUpdateCacheNode *)node)->cache; GPencilUpdateCache *new_update_cache = (GPencilUpdateCache *)data; - /* IMPORTANT: Because we are comparing the values of the flags here, make sure that any potential - * new flag either respects this ordering or changes the following logic. */ - const bool current_cache_covers_new_cache = new_update_cache->flag < update_cache->flag; - - /* In case: - * - the new cache is a no copy - * - or the new cache is a light copy and the current cache a full copy - * then it means we are already caching "more" and we shouldn't update the current cache. - * So we free the structure and return early. - */ - if (current_cache_covers_new_cache) { + /* If the new cache is already "covered" by the current cache, just free it and return. */ + if (new_update_cache->flag <= update_cache->flag) { update_cache_free(new_update_cache); return; } - /* In case: - * - the cache types are equal - * - or the new cache contains more than the current cache (full copy > light copy > no copy) - * the data pointer is updated. If the cache types are equal, this might be a no-op (when the new - * data pointer is equal to the previous), but is necessary when the data pointer needs to - * change. This can for example happen when the underlying data was reallocated, but the cache - * type stayed the same. - */ update_cache->data = new_update_cache->data; update_cache->flag = new_update_cache->flag; /* In case the new cache does a full update, remove its children since they will be all - * updated by the new cache. */ + * updated by this cache. */ if (new_update_cache->flag == GP_UPDATE_NODE_FULL_COPY && update_cache->children != NULL) { - /* We don't free the tree itself here, because we just want to clear the children, not delete - * the whole node. */ BLI_dlrbTree_free(update_cache->children, cache_node_free); + MEM_freeN(update_cache->children); } - /* Once we updated the data pointer and the flag, we can safely free the new cache structure. */ + update_cache_free(new_update_cache); } @@ -185,11 +167,8 @@ static void update_cache_node_create_ex(GPencilUpdateCache *root_cache, } GPencilUpdateCache *gps_cache = update_cache_alloc(gps_index, node_flag, (bGPDstroke *)data); - BLI_dlrbTree_add(gpf_node->cache->children, - cache_node_compare, - cache_node_alloc, - cache_node_update, - gps_cache); + BLI_dlrbTree_add( + gpf_node->cache->children, cache_node_compare, cache_node_alloc, cache_node_update, gps_cache); BLI_dlrbTree_linkedlist_sync(gpf_node->cache->children); } @@ -255,143 +234,6 @@ static void gpencil_traverse_update_cache_ex(GPencilUpdateCache *parent_cache, } } -typedef struct GPencilUpdateCacheDuplicateTraverseData { - GPencilUpdateCache *new_cache; - int gpl_index; - int gpf_index; -} GPencilUpdateCacheDuplicateTraverseData; - -static bool gpencil_duplicate_update_cache_layer_cb(GPencilUpdateCache *cache, void *user_data) -{ - GPencilUpdateCacheDuplicateTraverseData *td = (GPencilUpdateCacheDuplicateTraverseData *) - user_data; - - if (cache->flag == GP_UPDATE_NODE_FULL_COPY) { - /* Do a full copy of the layer. */ - bGPDlayer *gpl = (bGPDlayer *)cache->data; - bGPDlayer *gpl_new = BKE_gpencil_layer_duplicate(gpl, true, true); - update_cache_node_create_ex(td->new_cache, gpl_new, cache->index, -1, -1, true); - return true; - } - else if (cache->flag == GP_UPDATE_NODE_LIGHT_COPY) { - bGPDlayer *gpl = (bGPDlayer *)cache->data; - bGPDlayer *gpl_new = (bGPDlayer *)MEM_dupallocN(gpl); - - gpl_new->prev = gpl_new->next = NULL; - BLI_listbase_clear(&gpl_new->frames); - BLI_listbase_clear(&gpl_new->mask_layers); - update_cache_node_create_ex(td->new_cache, gpl_new, cache->index, -1, -1, false); - } - td->gpl_index = cache->index; - return false; -} - -static bool gpencil_duplicate_update_cache_frame_cb(GPencilUpdateCache *cache, void *user_data) -{ - GPencilUpdateCacheDuplicateTraverseData *td = (GPencilUpdateCacheDuplicateTraverseData *) - user_data; - if (cache->flag == GP_UPDATE_NODE_FULL_COPY) { - bGPDframe *gpf = (bGPDframe *)cache->data; - bGPDframe *gpf_new = BKE_gpencil_frame_duplicate(gpf, true); - update_cache_node_create_ex(td->new_cache, gpf_new, td->gpl_index, cache->index, -1, true); - return true; - } - else if (cache->flag == GP_UPDATE_NODE_LIGHT_COPY) { - bGPDframe *gpf = (bGPDframe *)cache->data; - bGPDframe *gpf_new = MEM_dupallocN(gpf); - gpf_new->prev = gpf_new->next = NULL; - BLI_listbase_clear(&gpf_new->strokes); - update_cache_node_create_ex(td->new_cache, gpf_new, td->gpl_index, cache->index, -1, false); - } - td->gpf_index = cache->index; - return false; -} - -static bool gpencil_duplicate_update_cache_stroke_cb(GPencilUpdateCache *cache, void *user_data) -{ - GPencilUpdateCacheDuplicateTraverseData *td = (GPencilUpdateCacheDuplicateTraverseData *) - user_data; - - if (cache->flag == GP_UPDATE_NODE_FULL_COPY) { - bGPDstroke *gps = (bGPDstroke *)cache->data; - bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(gps, true, true); - update_cache_node_create_ex( - td->new_cache, gps_new, td->gpl_index, td->gpf_index, cache->index, true); - } - else if (cache->flag == GP_UPDATE_NODE_LIGHT_COPY) { - bGPDstroke *gps = (bGPDstroke *)cache->data; - bGPDstroke *gps_new = MEM_dupallocN(gps); - - gps_new->prev = gps_new->next = NULL; - gps_new->points = NULL; - gps_new->triangles = NULL; - gps_new->dvert = NULL; - gps_new->editcurve = NULL; - - update_cache_node_create_ex( - td->new_cache, gps_new, td->gpl_index, td->gpf_index, cache->index, false); - } - return true; -} - -static bool gpencil_free_update_cache_layer_cb(GPencilUpdateCache *cache, void *UNUSED(user_data)) -{ - if (cache->flag == GP_UPDATE_NODE_FULL_COPY) { - BKE_gpencil_free_frames(cache->data); - BKE_gpencil_free_layer_masks(cache->data); - } - if (cache->data) { - MEM_freeN(cache->data); - } - return cache->flag == GP_UPDATE_NODE_FULL_COPY; -} - -static bool gpencil_free_update_cache_frame_cb(GPencilUpdateCache *cache, void *UNUSED(user_data)) -{ - if (cache->flag == GP_UPDATE_NODE_FULL_COPY) { - BKE_gpencil_free_strokes(cache->data); - } - if (cache->data) { - MEM_freeN(cache->data); - } - return cache->flag == GP_UPDATE_NODE_FULL_COPY; -} - -static bool gpencil_free_update_cache_stroke_cb(GPencilUpdateCache *cache, void *UNUSED(user_data)) -{ - if (cache->flag == GP_UPDATE_NODE_FULL_COPY) { - BKE_gpencil_free_stroke(cache->data); - } - return cache->flag == GP_UPDATE_NODE_FULL_COPY; -} - -static bool gpencil_print_update_cache_layer_cb(GPencilUpdateCache *cache, void *UNUSED(user_data)) -{ - printf(" - Layer: %s | Index: %d | Flag: %d | Tagged Frames: %d\n", - (cache->data ? ((bGPDlayer *)cache->data)->info : "N/A"), - cache->index, - cache->flag, - BLI_listbase_count((ListBase *)cache->children)); - return cache->flag == GP_UPDATE_NODE_FULL_COPY; -} - -static bool gpencil_print_update_cache_frame_cb(GPencilUpdateCache *cache, void *UNUSED(user_data)) -{ - printf(" - Frame: %d | Index: %d | Flag: %d | Tagged Strokes: %d\n", - (cache->data ? ((bGPDframe *)cache->data)->framenum : -1), - cache->index, - cache->flag, - BLI_listbase_count((ListBase *)cache->children)); - return cache->flag == GP_UPDATE_NODE_FULL_COPY; -} - -static bool gpencil_print_update_cache_stroke_cb(GPencilUpdateCache *cache, - void *UNUSED(user_data)) -{ - printf(" - Stroke Index: %d | | Flag: %d\n", cache->index, cache->flag); - return cache->flag == GP_UPDATE_NODE_FULL_COPY; -} - /* -------------------------------------------------------------------- */ /** \name Update Cache API * @@ -412,80 +254,12 @@ void BKE_gpencil_traverse_update_cache(GPencilUpdateCache *cache, void BKE_gpencil_tag_full_update(bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps) { - if (U.experimental.use_gpencil_update_cache) { - update_cache_node_create(gpd, gpl, gpf, gps, true); - } + update_cache_node_create(gpd, gpl, gpf, gps, true); } void BKE_gpencil_tag_light_update(bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps) { - if (U.experimental.use_gpencil_update_cache) { - update_cache_node_create(gpd, gpl, gpf, gps, false); - } -} - -GPencilUpdateCache *BKE_gpencil_duplicate_update_cache_and_data(GPencilUpdateCache *gpd_cache) -{ - GPencilUpdateCache *new_cache = update_cache_alloc(0, gpd_cache->flag, NULL); - bGPdata *gpd_new = NULL; - if (gpd_cache->flag == GP_UPDATE_NODE_FULL_COPY) { - BKE_gpencil_data_duplicate(NULL, gpd_cache->data, &gpd_new); - new_cache->data = gpd_new; - return new_cache; - } - else if (gpd_cache->flag == GP_UPDATE_NODE_LIGHT_COPY) { - gpd_new = MEM_dupallocN(gpd_cache->data); - - /* Clear all the pointers, since they shouldn't store anything. */ - BLI_listbase_clear(&gpd_new->layers); - BLI_listbase_clear(&gpd_new->vertex_group_names); - gpd_new->adt = NULL; - gpd_new->mat = NULL; - gpd_new->runtime.update_cache = NULL; - - new_cache->data = gpd_new; - } - - GPencilUpdateCacheTraverseSettings ts = {{gpencil_duplicate_update_cache_layer_cb, - gpencil_duplicate_update_cache_frame_cb, - gpencil_duplicate_update_cache_stroke_cb}}; - - GPencilUpdateCacheDuplicateTraverseData td = { - .new_cache = new_cache, - .gpl_index = -1, - .gpf_index = -1, - }; - - BKE_gpencil_traverse_update_cache(gpd_cache, &ts, &td); - return new_cache; -} - -/** - * Return true if any of the branches in gpd_cache_b are "strictly greater than" the branches in - * gpd_cache_a, e.g. one of them contains more data than their counterpart. - */ -bool BKE_gpencil_compare_update_caches(GPencilUpdateCache *gpd_cache_a, - GPencilUpdateCache *gpd_cache_b) -{ - if (gpd_cache_b->flag == GP_UPDATE_NODE_FULL_COPY) { - return gpd_cache_a->flag != GP_UPDATE_NODE_FULL_COPY; - } - if (gpd_cache_a->flag == GP_UPDATE_NODE_FULL_COPY) { - return false; - } - - LISTBASE_FOREACH (GPencilUpdateCacheNode *, node_b, gpd_cache_b->children) { - GPencilUpdateCacheNode *node_a = (GPencilUpdateCacheNode *)BLI_dlrbTree_search_exact( - gpd_cache_a->children, cache_node_compare, node_b->cache); - if (node_a == NULL) { - return true; - } - - if (BKE_gpencil_compare_update_caches(node_a->cache, node_b->cache)) { - return true; - } - } - return false; + update_cache_node_create(gpd, gpl, gpf, gps, false); } void BKE_gpencil_free_update_cache(bGPdata *gpd) @@ -495,43 +269,6 @@ void BKE_gpencil_free_update_cache(bGPdata *gpd) update_cache_free(gpd_cache); gpd->runtime.update_cache = NULL; } - gpd->flag &= ~GP_DATA_UPDATE_CACHE_DISPOSABLE; -} - -void BKE_gpencil_free_update_cache_and_data(GPencilUpdateCache *gpd_cache) -{ - if (gpd_cache->data != NULL) { - if (gpd_cache->flag == GP_UPDATE_NODE_FULL_COPY) { - BKE_gpencil_free_data(gpd_cache->data, true); - MEM_freeN(gpd_cache->data); - update_cache_free(gpd_cache); - return; - } - MEM_freeN(gpd_cache->data); - } - - GPencilUpdateCacheTraverseSettings ts = {{gpencil_free_update_cache_layer_cb, - gpencil_free_update_cache_frame_cb, - gpencil_free_update_cache_stroke_cb}}; - - BKE_gpencil_traverse_update_cache(gpd_cache, &ts, NULL); - update_cache_free(gpd_cache); -} - -void BKE_gpencil_print_update_cache(GPencilUpdateCache *update_cache) -{ - if (update_cache == NULL) { - printf("No update cache\n"); - return; - } - printf("Update cache: - Flag: %d | Tagged Layers: %d\n", - update_cache->flag, - BLI_listbase_count((ListBase *)update_cache->children)); - - GPencilUpdateCacheTraverseSettings ts = {{gpencil_print_update_cache_layer_cb, - gpencil_print_update_cache_frame_cb, - gpencil_print_update_cache_stroke_cb}}; - BKE_gpencil_traverse_update_cache(update_cache, &ts, NULL); } /** \} */ diff --git a/source/blender/blenkernel/intern/hair.cc b/source/blender/blenkernel/intern/hair.cc deleted file mode 100644 index bddadc3bcfd..00000000000 --- a/source/blender/blenkernel/intern/hair.cc +++ /dev/null @@ -1,474 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** \file - * \ingroup bke - */ - -#include <cmath> -#include <cstring> - -#include "MEM_guardedalloc.h" - -#include "DNA_defaults.h" -#include "DNA_hair_types.h" -#include "DNA_material_types.h" -#include "DNA_object_types.h" - -#include "BLI_index_range.hh" -#include "BLI_listbase.h" -#include "BLI_math_base.h" -#include "BLI_math_vec_types.hh" -#include "BLI_rand.hh" -#include "BLI_string.h" -#include "BLI_utildefines.h" - -#include "BKE_anim_data.h" -#include "BKE_customdata.h" -#include "BKE_global.h" -#include "BKE_hair.h" -#include "BKE_idtype.h" -#include "BKE_lib_id.h" -#include "BKE_lib_query.h" -#include "BKE_lib_remap.h" -#include "BKE_main.h" -#include "BKE_modifier.h" -#include "BKE_object.h" - -#include "BLT_translation.h" - -#include "DEG_depsgraph_query.h" - -#include "BLO_read_write.h" - -using blender::float3; -using blender::IndexRange; -using blender::MutableSpan; -using blender::RandomNumberGenerator; - -static const char *HAIR_ATTR_POSITION = "position"; -static const char *HAIR_ATTR_RADIUS = "radius"; - -/* Hair datablock */ - -static void hair_random(Hair *hair); - -static void hair_init_data(ID *id) -{ - Hair *hair = (Hair *)id; - BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(hair, id)); - - MEMCPY_STRUCT_AFTER(hair, DNA_struct_default_get(Hair), id); - - CustomData_reset(&hair->geometry.point_data); - CustomData_reset(&hair->geometry.curve_data); - - CustomData_add_layer_named(&hair->geometry.point_data, - CD_PROP_FLOAT3, - CD_CALLOC, - nullptr, - hair->geometry.point_size, - HAIR_ATTR_POSITION); - CustomData_add_layer_named(&hair->geometry.point_data, - CD_PROP_FLOAT, - CD_CALLOC, - nullptr, - hair->geometry.point_size, - HAIR_ATTR_RADIUS); - - BKE_hair_update_customdata_pointers(hair); - - hair_random(hair); -} - -static void hair_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag) -{ - Hair *hair_dst = (Hair *)id_dst; - const Hair *hair_src = (const Hair *)id_src; - hair_dst->mat = static_cast<Material **>(MEM_dupallocN(hair_src->mat)); - - hair_dst->geometry.point_size = hair_src->geometry.point_size; - hair_dst->geometry.curve_size = hair_src->geometry.curve_size; - - const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE; - CustomData_copy(&hair_src->geometry.point_data, - &hair_dst->geometry.point_data, - CD_MASK_ALL, - alloc_type, - hair_dst->geometry.point_size); - CustomData_copy(&hair_src->geometry.curve_data, - &hair_dst->geometry.curve_data, - CD_MASK_ALL, - alloc_type, - hair_dst->geometry.curve_size); - BKE_hair_update_customdata_pointers(hair_dst); - - hair_dst->geometry.offsets = static_cast<int *>(MEM_dupallocN(hair_src->geometry.offsets)); - - hair_dst->batch_cache = nullptr; -} - -static void hair_free_data(ID *id) -{ - Hair *hair = (Hair *)id; - BKE_animdata_free(&hair->id, false); - - BKE_hair_batch_cache_free(hair); - - CustomData_free(&hair->geometry.point_data, hair->geometry.point_size); - CustomData_free(&hair->geometry.curve_data, hair->geometry.curve_size); - - MEM_SAFE_FREE(hair->geometry.offsets); - - MEM_SAFE_FREE(hair->mat); -} - -static void hair_foreach_id(ID *id, LibraryForeachIDData *data) -{ - Hair *hair = (Hair *)id; - for (int i = 0; i < hair->totcol; i++) { - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, hair->mat[i], IDWALK_CB_USER); - } -} - -static void hair_blend_write(BlendWriter *writer, ID *id, const void *id_address) -{ - Hair *hair = (Hair *)id; - - CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE]; - CustomDataLayer *clayers = nullptr, clayers_buff[CD_TEMP_CHUNK_SIZE]; - CustomData_blend_write_prepare( - &hair->geometry.point_data, &players, players_buff, ARRAY_SIZE(players_buff)); - CustomData_blend_write_prepare( - &hair->geometry.curve_data, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff)); - - /* Write LibData */ - BLO_write_id_struct(writer, Hair, id_address, &hair->id); - BKE_id_blend_write(writer, &hair->id); - - /* Direct data */ - CustomData_blend_write(writer, - &hair->geometry.point_data, - players, - hair->geometry.point_size, - CD_MASK_ALL, - &hair->id); - CustomData_blend_write(writer, - &hair->geometry.curve_data, - clayers, - hair->geometry.curve_size, - CD_MASK_ALL, - &hair->id); - - BLO_write_int32_array(writer, hair->geometry.curve_size + 1, hair->geometry.offsets); - - BLO_write_pointer_array(writer, hair->totcol, hair->mat); - if (hair->adt) { - BKE_animdata_blend_write(writer, hair->adt); - } - - /* Remove temporary data. */ - if (players && players != players_buff) { - MEM_freeN(players); - } - if (clayers && clayers != clayers_buff) { - MEM_freeN(clayers); - } -} - -static void hair_blend_read_data(BlendDataReader *reader, ID *id) -{ - Hair *hair = (Hair *)id; - BLO_read_data_address(reader, &hair->adt); - BKE_animdata_blend_read_data(reader, hair->adt); - - /* Geometry */ - CustomData_blend_read(reader, &hair->geometry.point_data, hair->geometry.point_size); - CustomData_blend_read(reader, &hair->geometry.curve_data, hair->geometry.point_size); - BKE_hair_update_customdata_pointers(hair); - - BLO_read_int32_array(reader, hair->geometry.curve_size + 1, &hair->geometry.offsets); - - /* Materials */ - BLO_read_pointer_array(reader, (void **)&hair->mat); -} - -static void hair_blend_read_lib(BlendLibReader *reader, ID *id) -{ - Hair *hair = (Hair *)id; - for (int a = 0; a < hair->totcol; a++) { - BLO_read_id_address(reader, hair->id.lib, &hair->mat[a]); - } -} - -static void hair_blend_read_expand(BlendExpander *expander, ID *id) -{ - Hair *hair = (Hair *)id; - for (int a = 0; a < hair->totcol; a++) { - BLO_expand(expander, hair->mat[a]); - } -} - -IDTypeInfo IDType_ID_HA = { - /*id_code */ ID_HA, - /*id_filter */ FILTER_ID_HA, - /*main_listbase_index */ INDEX_ID_HA, - /*struct_size */ sizeof(Hair), - /*name */ "Hair", - /*name_plural */ "hairs", - /*translation_context */ BLT_I18NCONTEXT_ID_HAIR, - /*flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE, - /*asset_type_info */ nullptr, - - /*init_data */ hair_init_data, - /*copy_data */ hair_copy_data, - /*free_data */ hair_free_data, - /*make_local */ nullptr, - /*foreach_id */ hair_foreach_id, - /*foreach_cache */ nullptr, - /*foreach_path */ nullptr, - /*owner_get */ nullptr, - - /*blend_write */ hair_blend_write, - /*blend_read_data */ hair_blend_read_data, - /*blend_read_lib */ hair_blend_read_lib, - /*blend_read_expand */ hair_blend_read_expand, - - /*blend_read_undo_preserve */ nullptr, - - /*lib_override_apply_post */ nullptr, -}; - -static void hair_random(Hair *hair) -{ - CurvesGeometry &geometry = hair->geometry; - const int numpoints = 8; - - geometry.curve_size = 500; - - geometry.curve_size = 500; - geometry.point_size = geometry.curve_size * numpoints; - - hair->geometry.offsets = (int *)MEM_calloc_arrayN( - hair->geometry.curve_size + 1, sizeof(int), __func__); - CustomData_realloc(&geometry.point_data, geometry.point_size); - CustomData_realloc(&geometry.curve_data, geometry.curve_size); - BKE_hair_update_customdata_pointers(hair); - - MutableSpan<int> offsets{geometry.offsets, geometry.curve_size + 1}; - MutableSpan<float3> positions{(float3 *)geometry.position, geometry.point_size}; - MutableSpan<float> radii{geometry.radius, geometry.point_size}; - - for (const int i : offsets.index_range()) { - geometry.offsets[i] = numpoints * i; - } - - RandomNumberGenerator rng; - - for (int i = 0; i < geometry.curve_size; i++) { - const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]); - MutableSpan<float3> curve_positions = positions.slice(curve_range); - MutableSpan<float> curve_radii = radii.slice(curve_range); - - const float theta = 2.0f * M_PI * rng.get_float(); - const float phi = saacosf(2.0f * rng.get_float() - 1.0f); - - float3 no = {std::sin(theta) * std::sin(phi), std::cos(theta) * std::sin(phi), std::cos(phi)}; - no = blender::math::normalize(no); - - float3 co = no; - for (int key = 0; key < numpoints; key++) { - float t = key / (float)(numpoints - 1); - curve_positions[key] = co; - curve_radii[key] = 0.02f * (1.0f - t); - - float3 offset = float3(rng.get_float(), rng.get_float(), rng.get_float()) * 2.0f - 1.0f; - co += (offset + no) / numpoints; - } - } -} - -void *BKE_hair_add(Main *bmain, const char *name) -{ - Hair *hair = static_cast<Hair *>(BKE_id_new(bmain, ID_HA, name)); - - return hair; -} - -BoundBox *BKE_hair_boundbox_get(Object *ob) -{ - BLI_assert(ob->type == OB_HAIR); - Hair *hair = static_cast<Hair *>(ob->data); - - if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) { - return ob->runtime.bb; - } - - if (ob->runtime.bb == nullptr) { - ob->runtime.bb = MEM_cnew<BoundBox>(__func__); - - float min[3], max[3]; - INIT_MINMAX(min, max); - - float(*hair_co)[3] = hair->geometry.position; - float *hair_radius = hair->geometry.radius; - for (int a = 0; a < hair->geometry.point_size; a++) { - float *co = hair_co[a]; - float radius = (hair_radius) ? hair_radius[a] : 0.0f; - const float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius}; - const float co_max[3] = {co[0] + radius, co[1] + radius, co[2] + radius}; - DO_MIN(co_min, min); - DO_MAX(co_max, max); - } - - BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max); - } - - return ob->runtime.bb; -} - -void BKE_hair_update_customdata_pointers(Hair *hair) -{ - hair->geometry.position = (float(*)[3])CustomData_get_layer_named( - &hair->geometry.point_data, CD_PROP_FLOAT3, HAIR_ATTR_POSITION); - hair->geometry.radius = (float *)CustomData_get_layer_named( - &hair->geometry.point_data, CD_PROP_FLOAT, HAIR_ATTR_RADIUS); -} - -bool BKE_hair_customdata_required(Hair *UNUSED(hair), CustomDataLayer *layer) -{ - return layer->type == CD_PROP_FLOAT3 && STREQ(layer->name, HAIR_ATTR_POSITION); -} - -/* Dependency Graph */ - -Hair *BKE_hair_new_for_eval(const Hair *hair_src, int totpoint, int totcurve) -{ - Hair *hair_dst = static_cast<Hair *>(BKE_id_new_nomain(ID_HA, nullptr)); - - STRNCPY(hair_dst->id.name, hair_src->id.name); - hair_dst->mat = static_cast<Material **>(MEM_dupallocN(hair_src->mat)); - hair_dst->totcol = hair_src->totcol; - - hair_dst->geometry.point_size = totpoint; - hair_dst->geometry.curve_size = totcurve; - CustomData_copy(&hair_src->geometry.point_data, - &hair_dst->geometry.point_data, - CD_MASK_ALL, - CD_CALLOC, - totpoint); - CustomData_copy(&hair_src->geometry.curve_data, - &hair_dst->geometry.curve_data, - CD_MASK_ALL, - CD_CALLOC, - totcurve); - BKE_hair_update_customdata_pointers(hair_dst); - - return hair_dst; -} - -Hair *BKE_hair_copy_for_eval(Hair *hair_src, bool reference) -{ - int flags = LIB_ID_COPY_LOCALIZE; - - if (reference) { - flags |= LIB_ID_COPY_CD_REFERENCE; - } - - Hair *result = (Hair *)BKE_id_copy_ex(nullptr, &hair_src->id, nullptr, flags); - return result; -} - -static Hair *hair_evaluate_modifiers(struct Depsgraph *depsgraph, - struct Scene *scene, - Object *object, - Hair *hair_input) -{ - Hair *hair = hair_input; - - /* Modifier evaluation modes. */ - const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); - const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; - ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE; - const ModifierEvalContext mectx = {depsgraph, object, apply_flag}; - - /* Get effective list of modifiers to execute. Some effects like shape keys - * are added as virtual modifiers before the user created modifiers. */ - VirtualModifierData virtualModifierData; - ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData); - - /* Evaluate modifiers. */ - for (; md; md = md->next) { - const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast<ModifierType>(md->type)); - - if (!BKE_modifier_is_enabled(scene, md, required_mode)) { - continue; - } - - if ((mti->type == eModifierTypeType_OnlyDeform) && - (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) { - /* Ensure we are not modifying the input. */ - if (hair == hair_input) { - hair = BKE_hair_copy_for_eval(hair, true); - } - - /* Ensure we are not overwriting referenced data. */ - CustomData_duplicate_referenced_layer_named(&hair->geometry.point_data, - CD_PROP_FLOAT3, - HAIR_ATTR_POSITION, - hair->geometry.point_size); - BKE_hair_update_customdata_pointers(hair); - - /* Created deformed coordinates array on demand. */ - mti->deformVerts(md, &mectx, nullptr, hair->geometry.position, hair->geometry.point_size); - } - } - - return hair; -} - -void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object) -{ - /* Free any evaluated data and restore original data. */ - BKE_object_free_derived_caches(object); - - /* Evaluate modifiers. */ - Hair *hair = static_cast<Hair *>(object->data); - Hair *hair_eval = hair_evaluate_modifiers(depsgraph, scene, object, hair); - - /* Assign evaluated object. */ - const bool is_owned = (hair != hair_eval); - BKE_object_eval_assign_data(object, &hair_eval->id, is_owned); -} - -/* Draw Cache */ - -void (*BKE_hair_batch_cache_dirty_tag_cb)(Hair *hair, int mode) = nullptr; -void (*BKE_hair_batch_cache_free_cb)(Hair *hair) = nullptr; - -void BKE_hair_batch_cache_dirty_tag(Hair *hair, int mode) -{ - if (hair->batch_cache) { - BKE_hair_batch_cache_dirty_tag_cb(hair, mode); - } -} - -void BKE_hair_batch_cache_free(Hair *hair) -{ - if (hair->batch_cache) { - BKE_hair_batch_cache_free_cb(hair); - } -} diff --git a/source/blender/blenkernel/intern/idtype.c b/source/blender/blenkernel/intern/idtype.c index e6fd6c14d42..98bbd920615 100644 --- a/source/blender/blenkernel/intern/idtype.c +++ b/source/blender/blenkernel/intern/idtype.c @@ -15,9 +15,6 @@ * * The Original Code is Copyright (C) 2005 by the Blender Foundation. * All rights reserved. - * Modifier stack implementation. - * - * BKE_modifier.h contains the function prototypes for this file. */ /** \file @@ -110,7 +107,7 @@ static void id_type_init(void) INIT_TYPE(ID_CF); INIT_TYPE(ID_WS); INIT_TYPE(ID_LP); - INIT_TYPE(ID_HA); + INIT_TYPE(ID_CV); INIT_TYPE(ID_PT); INIT_TYPE(ID_VO); INIT_TYPE(ID_SIM); @@ -237,7 +234,7 @@ uint64_t BKE_idtype_idcode_to_idfilter(const short idcode) CASE_IDFILTER(CU); CASE_IDFILTER(GD); CASE_IDFILTER(GR); - CASE_IDFILTER(HA); + CASE_IDFILTER(CV); CASE_IDFILTER(IM); CASE_IDFILTER(LA); CASE_IDFILTER(LS); @@ -286,7 +283,7 @@ short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter) CASE_IDFILTER(CU); CASE_IDFILTER(GD); CASE_IDFILTER(GR); - CASE_IDFILTER(HA); + CASE_IDFILTER(CV); CASE_IDFILTER(IM); CASE_IDFILTER(LA); CASE_IDFILTER(LS); @@ -334,7 +331,7 @@ int BKE_idtype_idcode_to_index(const short idcode) CASE_IDINDEX(CU); CASE_IDINDEX(GD); CASE_IDINDEX(GR); - CASE_IDINDEX(HA); + CASE_IDINDEX(CV); CASE_IDINDEX(IM); CASE_IDINDEX(IP); CASE_IDINDEX(KE); @@ -393,7 +390,7 @@ short BKE_idtype_idcode_from_index(const int index) CASE_IDCODE(CU); CASE_IDCODE(GD); CASE_IDCODE(GR); - CASE_IDCODE(HA); + CASE_IDCODE(CV); CASE_IDCODE(IM); CASE_IDCODE(IP); CASE_IDCODE(KE); diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 314351e4ad7..961f63b1f82 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -161,6 +161,8 @@ void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, const bool do_f (ID *)src_id; id_us_plus(dst_id->override_library->reference); + dst_id->override_library->hierarchy_root = src_id->override_library->hierarchy_root; + if (do_full_copy) { BLI_duplicatelist(&dst_id->override_library->properties, &src_id->override_library->properties); @@ -293,6 +295,7 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain, * mess in case there are a lot of hidden, non-instantiated, non-properly organized dependencies. * Ref T94650. */ local_id->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY; + local_id->override_library->hierarchy_root = local_id; if (do_tagged_remap) { Key *reference_key, *local_key = NULL; @@ -328,9 +331,18 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain, bool BKE_lib_override_library_create_from_tag(Main *bmain, Library *owner_library, - const Library *reference_library, + const ID *id_root_reference, + ID *id_hierarchy_root, const bool do_no_main) { + BLI_assert(id_root_reference != NULL); + BLI_assert(id_hierarchy_root != NULL || (id_root_reference->tag & LIB_TAG_DOIT) != 0); + BLI_assert(id_hierarchy_root == NULL || + (ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root) && + id_hierarchy_root->override_library->reference == id_root_reference)); + + const Library *reference_library = id_root_reference->lib; + ID *reference_id; bool success = true; @@ -383,6 +395,11 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain, /* Only remap new local ID's pointers, we don't want to force our new overrides onto our whole * existing linked IDs usages. */ if (success) { + if (id_root_reference->newid != NULL) { + id_hierarchy_root = id_root_reference->newid; + } + BLI_assert(id_hierarchy_root != NULL); + for (todo_id_iter = todo_ids.first; todo_id_iter != NULL; todo_id_iter = todo_id_iter->next) { reference_id = todo_id_iter->data; ID *local_id = reference_id->newid; @@ -391,6 +408,8 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain, continue; } + local_id->override_library->hierarchy_root = id_hierarchy_root; + Key *reference_key, *local_key = NULL; if ((reference_key = BKE_key_from_id(reference_id)) != NULL) { local_key = BKE_key_from_id(reference_id->newid); @@ -459,6 +478,7 @@ typedef struct LibOverrideGroupTagData { Main *bmain; Scene *scene; ID *id_root; + ID *hierarchy_root_id; uint tag; uint missing_tag; /* Whether we are looping on override data, or their references (linked) one. */ @@ -769,6 +789,8 @@ static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData * BLI_assert(ID_IS_OVERRIDE_LIBRARY(id_owner)); BLI_assert(data->is_override); + ID *id_hierarchy_root = data->hierarchy_root_id; + if (ID_IS_OVERRIDE_LIBRARY_REAL(id_owner) && (id_owner->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY) != 0) { return; @@ -800,9 +822,15 @@ static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData * if (ELEM(to_id, NULL, id_owner)) { continue; } + /* Different libraries or different hierarchy roots are break points in override hierarchies. + */ if (!ID_IS_OVERRIDE_LIBRARY(to_id) || (to_id->lib != id_owner->lib)) { continue; } + if (ID_IS_OVERRIDE_LIBRARY_REAL(to_id) && + to_id->override_library->hierarchy_root != id_hierarchy_root) { + continue; + } Library *reference_lib = lib_override_get(bmain, id_owner)->reference->lib; ID *to_id_reference = lib_override_get(bmain, to_id)->reference; @@ -832,6 +860,11 @@ static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data) BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); BLI_assert(data->is_override); + ID *id_hierarchy_root = data->hierarchy_root_id; + BLI_assert(id_hierarchy_root != NULL); + BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root)); + UNUSED_VARS_NDEBUG(id_hierarchy_root); + if (id_root->override_library->reference->tag & LIB_TAG_MISSING) { id_root->tag |= data->missing_tag; } @@ -865,7 +898,10 @@ static bool lib_override_library_create_do(Main *bmain, BKE_main_relations_free(bmain); lib_override_group_tag_data_clear(&data); - return BKE_lib_override_library_create_from_tag(bmain, owner_library, id_root->lib, false); + const bool success = BKE_lib_override_library_create_from_tag( + bmain, owner_library, id_root, NULL, false); + + return success; } static void lib_override_library_create_post_process(Main *bmain, @@ -1047,6 +1083,189 @@ bool BKE_lib_override_library_template_create(struct ID *id) return true; } +static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level, int *r_best_level) +{ + if (curr_level > 1000) { + CLOG_ERROR(&LOG, + "Levels of dependency relationships between library overrides IDs is way too high, " + "skipping further processing loops (involves at least '%s')", + id->name); + BLI_assert(0); + return NULL; + } + + if (!ID_IS_OVERRIDE_LIBRARY(id)) { + BLI_assert(0); + return NULL; + } + + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id); + BLI_assert(entry != NULL); + + int best_level_candidate = curr_level; + ID *best_root_id_candidate = id; + + for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != NULL; + from_id_entry = from_id_entry->next) { + if ((from_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) { + /* Never consider non-overridable relationships as actual dependencies. */ + continue; + } + + ID *from_id = from_id_entry->id_pointer.from; + if (ELEM(from_id, NULL, id)) { + continue; + } + if (!ID_IS_OVERRIDE_LIBRARY(from_id) || (from_id->lib != id->lib)) { + continue; + } + + int level_candidate = curr_level + 1; + /* Recursively process the parent. */ + ID *root_id_candidate = lib_override_root_find( + bmain, from_id, curr_level + 1, &level_candidate); + if (level_candidate > best_level_candidate && root_id_candidate != NULL) { + best_root_id_candidate = root_id_candidate; + best_level_candidate = level_candidate; + } + } + + *r_best_level = best_level_candidate; + return best_root_id_candidate; +} + +static void lib_override_root_hierarchy_set(Main *bmain, ID *id_root, ID *id, ID *id_from) +{ + if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + if (id->override_library->hierarchy_root == id_root) { + /* Already set, nothing else to do here, sub-hierarchy is also assumed to be properly set + * then. */ + return; + } + + /* Hierarchy root already set, and not matching currently proposed one, try to find which is + * best. */ + if (id->override_library->hierarchy_root != NULL) { + /* Check if given `id_from` matches with the hierarchy of the linked reference ID, in which + * case we assume that the given hierarchy root is the 'real' one. + * + * NOTE: This can fail if user mixed dependencies between several overrides of a same + * reference linked hierarchy. Not much to be done in that case, it's virtually impossible to + * fix this automatically in a reliable way. */ + if (id_from == NULL || !ID_IS_OVERRIDE_LIBRARY_REAL(id_from)) { + /* Too complicated to deal with for now. */ + CLOG_WARN(&LOG, + "Inconsistency in library override hierarchy of ID '%s'.\n" + "\tNot enough data to verify validity of current proposed root '%s', assuming " + "already set one '%s' is valid.", + id->name, + id_root->name, + id->override_library->hierarchy_root->name); + return; + } + + ID *id_from_ref = id_from->override_library->reference; + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, + id->override_library->reference); + BLI_assert(entry != NULL); + + bool do_replace_root = false; + for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != NULL; + from_id_entry = from_id_entry->next) { + if ((from_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) { + /* Never consider non-overridable relationships as actual dependencies. */ + continue; + } + + if (id_from_ref == from_id_entry->id_pointer.from) { + /* A matching parent was found in reference linked data, assume given hierarchy root is + * the valid one. */ + do_replace_root = true; + CLOG_WARN( + &LOG, + "Inconsistency in library override hierarchy of ID '%s'.\n" + "\tCurrent proposed root '%s' detected as valid, will replace already set one '%s'.", + id->name, + id_root->name, + id->override_library->hierarchy_root->name); + break; + } + } + + if (!do_replace_root) { + CLOG_WARN( + &LOG, + "Inconsistency in library override hierarchy of ID '%s'.\n" + "\tCurrent proposed root '%s' not detected as valid, keeping already set one '%s'.", + id->name, + id_root->name, + id->override_library->hierarchy_root->name); + return; + } + } + + id->override_library->hierarchy_root = id_root; + } + + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id); + BLI_assert(entry != NULL); + + for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL; + to_id_entry = to_id_entry->next) { + if ((to_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) { + /* Never consider non-overridable relationships as actual dependencies. */ + continue; + } + + ID *to_id = *to_id_entry->id_pointer.to; + if (ELEM(to_id, NULL, id)) { + continue; + } + if (!ID_IS_OVERRIDE_LIBRARY(to_id) || (to_id->lib != id->lib)) { + continue; + } + + /* Recursively process the sub-hierarchy. */ + lib_override_root_hierarchy_set(bmain, id_root, to_id, id); + } +} + +void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain) +{ + ID *id; + + BKE_main_relations_create(bmain, 0); + + FOREACH_MAIN_ID_BEGIN (bmain, id) { + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + continue; + } + if (id->override_library->hierarchy_root != NULL) { + continue; + } + + int best_level = 0; + ID *id_root = lib_override_root_find(bmain, id, best_level, &best_level); + + if (!ELEM(id_root->override_library->hierarchy_root, id_root, NULL)) { + CLOG_WARN(&LOG, + "Potential inconsistency in library override hierarchy of ID '%s', detected as " + "part of the hierarchy of '%s', which has a different root '%s'", + id->name, + id_root->name, + id_root->override_library->hierarchy_root->name); + continue; + } + + lib_override_root_hierarchy_set(bmain, id_root, id_root, NULL); + + BLI_assert(id->override_library->hierarchy_root != NULL); + } + FOREACH_MAIN_ID_END; + + BKE_main_relations_free(bmain); +} + static void lib_override_library_remap(Main *bmain, const ID *id_root_reference, GHash *linkedref_to_old_override) @@ -1112,6 +1331,7 @@ static bool lib_override_library_resync(Main *bmain, LibOverrideGroupTagData data = {.bmain = bmain, .scene = scene, .id_root = id_root, + .hierarchy_root_id = id_root->override_library->hierarchy_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING, .is_override = true, @@ -1214,7 +1434,7 @@ static bool lib_override_library_resync(Main *bmain, * override IDs (including within the old overrides themselves, since those are tagged too * above). */ const bool success = BKE_lib_override_library_create_from_tag( - bmain, NULL, id_root_reference->lib, true); + bmain, NULL, id_root_reference, id_root->override_library->hierarchy_root, true); if (!success) { return success; @@ -1533,46 +1753,20 @@ static void lib_override_resync_tagging_finalize_recurse(Main *bmain, * * NOTE: Related to `lib_override_resync_tagging_finalize` above. */ -static ID *lib_override_library_main_resync_find_root_recurse(ID *id, int *level) -{ - (*level)++; - ID *return_id = id; - - switch (GS(id->name)) { - case ID_GR: { - /* Find the highest valid collection in the parenting hierarchy. - * Note that in practice, in any decent common case there is only one well defined root - * collection anyway. */ - int max_level = *level; - Collection *collection = (Collection *)id; - LISTBASE_FOREACH (CollectionParent *, collection_parent_iter, &collection->parents) { - Collection *collection_parent = collection_parent_iter->collection; - if (ID_IS_OVERRIDE_LIBRARY_REAL(collection_parent) && - collection_parent->id.lib == id->lib) { - int tmp_level = *level; - ID *tmp_id = lib_override_library_main_resync_find_root_recurse(&collection_parent->id, - &tmp_level); - if (tmp_level > max_level) { - max_level = tmp_level; - return_id = tmp_id; - } - } - } - break; - } - case ID_OB: { - Object *object = (Object *)id; - if (object->parent != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(object->parent) && - object->parent->id.lib == id->lib) { - return_id = lib_override_library_main_resync_find_root_recurse(&object->parent->id, level); - } - break; +static ID *lib_override_library_main_resync_root_get(Main *bmain, ID *id) +{ + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id); + if (id_type->owner_get != NULL) { + id = id_type->owner_get(bmain, id); } - default: - break; + BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id)); } - return return_id; + ID *hierarchy_root_id = id->override_library->hierarchy_root; + BLI_assert(hierarchy_root_id != NULL); + BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(hierarchy_root_id)); + return hierarchy_root_id; } /* Ensure resync of all overrides at one level of indirect usage. @@ -1714,14 +1908,13 @@ static void lib_override_library_main_resync_on_library_indirect_level( Library *library = id->lib; - int level = 0; /* In complex non-supported cases, with several different override hierarchies sharing * relations between each-other, we may end up not actually updating/replacing the given * root id (see e.g. pro/shots/110_rextoria/110_0150_A/110_0150_A.anim.blend of sprites * project repository, r2687). * This can lead to infinite loop here, at least avoid this. */ id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC; - id = lib_override_library_main_resync_find_root_recurse(id, &level); + id = lib_override_library_main_resync_root_get(bmain, id); id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC; BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id)); BLI_assert(id->lib == library); @@ -1879,6 +2072,7 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root) LibOverrideGroupTagData data = {.bmain = bmain, .scene = NULL, .id_root = id_root, + .hierarchy_root_id = id_root->override_library->hierarchy_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING, .is_override = true, diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c index e73b53c4bf8..f49af9abffe 100644 --- a/source/blender/blenkernel/intern/lib_query.c +++ b/source/blender/blenkernel/intern/lib_query.c @@ -323,6 +323,8 @@ static bool library_foreach_ID_link(Main *bmain, IDWALK_CB_USER | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE); CALLBACK_INVOKE_ID(id->override_library->storage, IDWALK_CB_USER | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE); + + CALLBACK_INVOKE_ID(id->override_library->hierarchy_root, IDWALK_CB_LOOPBACK); } IDP_foreach_property(id->properties, @@ -471,7 +473,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) return ELEM(id_type_used, ID_MA); case ID_WS: return ELEM(id_type_used, ID_SCR, ID_SCE); - case ID_HA: + case ID_CV: return ELEM(id_type_used, ID_MA); case ID_PT: return ELEM(id_type_used, ID_MA); diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c index e4e0466416a..8e375ff16b5 100644 --- a/source/blender/blenkernel/intern/lib_remap.c +++ b/source/blender/blenkernel/intern/lib_remap.c @@ -97,14 +97,14 @@ static void foreach_libblock_remap_callback_skip(const ID *UNUSED(id_owner), const int cb_flag, const bool is_indirect, const bool is_reference, - const bool is_never_null, + const bool violates_never_null, const bool UNUSED(is_obj), const bool is_obj_editmode) { if (is_indirect) { id_remap_data->skipped_indirect++; } - else if (is_never_null || is_obj_editmode || is_reference) { + else if (violates_never_null || is_obj_editmode || is_reference) { id_remap_data->skipped_direct++; } else { @@ -127,10 +127,10 @@ static void foreach_libblock_remap_callback_apply(ID *id_owner, IDRemap *id_remap_data, const int cb_flag, const bool is_indirect, - const bool is_never_null, + const bool violates_never_null, const bool force_user_refcount) { - if (!is_never_null) { + if (!violates_never_null) { *id_ptr = new_id; DEG_id_tag_update_ex(id_remap_data->bmain, id_self, @@ -210,8 +210,8 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data) * remapped in this situation. */ const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id_owner) && (id_remap_data->flag & ID_REMAP_FORCE_OBDATA_IN_EDITMODE) == 0); - const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) && - (id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0); + const bool violates_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) && + (id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0); const bool skip_reference = (id_remap_data->flag & ID_REMAP_SKIP_OVERRIDE_LIBRARY) != 0; const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0; const bool force_user_refcount = (id_remap_data->flag & ID_REMAP_FORCE_USER_REFCOUNT) != 0; @@ -239,7 +239,7 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data) /* Special hack in case it's Object->data and we are in edit mode, and new_id is not NULL * (otherwise, we follow common NEVER_NULL flags). * (skipped_indirect too). */ - if ((is_never_null && skip_never_null) || + if ((violates_never_null && skip_never_null) || (is_obj_editmode && (((Object *)id_owner)->data == *id_p) && new_id != NULL) || (skip_indirect && is_indirect) || (is_reference && skip_reference)) { foreach_libblock_remap_callback_skip(id_owner, @@ -248,7 +248,7 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data) cb_flag, is_indirect, is_reference, - is_never_null, + violates_never_null, is_obj, is_obj_editmode); } @@ -261,7 +261,7 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data) id_remap_data, cb_flag, is_indirect, - is_never_null, + violates_never_null, force_user_refcount); } @@ -558,7 +558,7 @@ static void libblock_remap_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_ case ID_ME: case ID_CU: case ID_MB: - case ID_HA: + case ID_CV: case ID_PT: case ID_VO: if (new_id) { /* Only affects us in case obdata was relinked (changed). */ diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c index 64731be57ac..53b1a9c9e16 100644 --- a/source/blender/blenkernel/intern/main.c +++ b/source/blender/blenkernel/intern/main.c @@ -643,8 +643,8 @@ ListBase *which_libbase(Main *bmain, short type) return &(bmain->cachefiles); case ID_WS: return &(bmain->workspaces); - case ID_HA: - return &(bmain->hairs); + case ID_CV: + return &(bmain->hair_curves); case ID_PT: return &(bmain->pointclouds); case ID_VO: @@ -688,7 +688,7 @@ int set_listbasepointers(Main *bmain, ListBase *lb[/*INDEX_ID_MAX*/]) lb[INDEX_ID_ME] = &(bmain->meshes); lb[INDEX_ID_CU] = &(bmain->curves); lb[INDEX_ID_MB] = &(bmain->metaballs); - lb[INDEX_ID_HA] = &(bmain->hairs); + lb[INDEX_ID_CV] = &(bmain->hair_curves); lb[INDEX_ID_PT] = &(bmain->pointclouds); lb[INDEX_ID_VO] = &(bmain->volumes); diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 15469f910b4..1c1b2c2cd27 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -36,10 +36,10 @@ #include "DNA_anim_types.h" #include "DNA_collection_types.h" #include "DNA_curve_types.h" +#include "DNA_curves_types.h" #include "DNA_customdata_types.h" #include "DNA_defaults.h" #include "DNA_gpencil_types.h" -#include "DNA_hair_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -341,9 +341,9 @@ Material ***BKE_object_material_array_p(Object *ob) bGPdata *gpd = ob->data; return &(gpd->mat); } - if (ob->type == OB_HAIR) { - Hair *hair = ob->data; - return &(hair->mat); + if (ob->type == OB_CURVES) { + Curves *curves = ob->data; + return &(curves->mat); } if (ob->type == OB_POINTCLOUD) { PointCloud *pointcloud = ob->data; @@ -374,9 +374,9 @@ short *BKE_object_material_len_p(Object *ob) bGPdata *gpd = ob->data; return &(gpd->totcol); } - if (ob->type == OB_HAIR) { - Hair *hair = ob->data; - return &(hair->totcol); + if (ob->type == OB_CURVES) { + Curves *curves = ob->data; + return &(curves->totcol); } if (ob->type == OB_POINTCLOUD) { PointCloud *pointcloud = ob->data; @@ -403,8 +403,8 @@ Material ***BKE_id_material_array_p(ID *id) return &(((MetaBall *)id)->mat); case ID_GD: return &(((bGPdata *)id)->mat); - case ID_HA: - return &(((Hair *)id)->mat); + case ID_CV: + return &(((Curves *)id)->mat); case ID_PT: return &(((PointCloud *)id)->mat); case ID_VO: @@ -429,8 +429,8 @@ short *BKE_id_material_len_p(ID *id) return &(((MetaBall *)id)->totcol); case ID_GD: return &(((bGPdata *)id)->totcol); - case ID_HA: - return &(((Hair *)id)->totcol); + case ID_CV: + return &(((Curves *)id)->totcol); case ID_PT: return &(((PointCloud *)id)->totcol); case ID_VO: @@ -454,7 +454,7 @@ static void material_data_index_remove_id(ID *id, short index) BKE_curve_material_index_remove((Curve *)id, index); break; case ID_MB: - case ID_HA: + case ID_CV: case ID_PT: case ID_VO: /* No material indices for these object data types. */ @@ -509,7 +509,7 @@ static void material_data_index_clear_id(ID *id) BKE_curve_material_index_clear((Curve *)id); break; case ID_MB: - case ID_HA: + case ID_CV: case ID_PT: case ID_VO: /* No material indices for these object data types. */ diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index ac6b0a04def..3c5cdb1ba78 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -15,6 +15,11 @@ * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. + */ + +/** \file + * \ingroup bke + * * MetaBalls are created from a single Object (with a name without number in it), * here the DispList and BoundBox also is located. * All objects with the same name (but with a number in it) are added to this. @@ -22,10 +27,6 @@ * texture coordinates are patched within the displist */ -/** \file - * \ingroup bke - */ - #include <ctype.h> #include <float.h> #include <math.h> diff --git a/source/blender/blenkernel/intern/mesh_fair.cc b/source/blender/blenkernel/intern/mesh_fair.cc index 50db1bc1564..d0a57310fcf 100644 --- a/source/blender/blenkernel/intern/mesh_fair.cc +++ b/source/blender/blenkernel/intern/mesh_fair.cc @@ -12,13 +12,12 @@ * 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. - * - * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing": - * https://github.com/fedackb/mesh-fairing. */ /** \file * \ingroup bke + * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing": + * https://github.com/fedackb/mesh-fairing. */ #include "BLI_map.hh" diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 08a17060549..1b3c7e01be8 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -43,6 +43,7 @@ #include "BLI_span.hh" #include "BLI_stack.h" #include "BLI_task.h" +#include "BLI_task.hh" #include "BLI_utildefines.h" #include "BKE_customdata.h" @@ -373,22 +374,28 @@ const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3] return (const float(*)[3])CustomData_get_layer(&mesh->vdata, CD_NORMAL); } - Mesh &mesh_mutable = *const_cast<Mesh *>(mesh); + float(*vert_normals)[3]; + float(*poly_normals)[3]; - float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(&mesh_mutable); - float(*poly_normals)[3] = BKE_mesh_poly_normals_for_write(&mesh_mutable); + /* Isolate task because a mutex is locked and computing normals is multi-threaded. */ + blender::threading::isolate_task([&]() { + Mesh &mesh_mutable = *const_cast<Mesh *>(mesh); - mesh_calc_normals_poly_and_vertex(mesh_mutable.mvert, - mesh_mutable.totvert, - mesh_mutable.mloop, - mesh_mutable.totloop, - mesh_mutable.mpoly, - mesh_mutable.totpoly, - poly_normals, - vert_normals); + vert_normals = BKE_mesh_vertex_normals_for_write(&mesh_mutable); + poly_normals = BKE_mesh_poly_normals_for_write(&mesh_mutable); - BKE_mesh_vertex_normals_clear_dirty(&mesh_mutable); - BKE_mesh_poly_normals_clear_dirty(&mesh_mutable); + mesh_calc_normals_poly_and_vertex(mesh_mutable.mvert, + mesh_mutable.totvert, + mesh_mutable.mloop, + mesh_mutable.totloop, + mesh_mutable.mpoly, + mesh_mutable.totpoly, + poly_normals, + vert_normals); + + BKE_mesh_vertex_normals_clear_dirty(&mesh_mutable); + BKE_mesh_poly_normals_clear_dirty(&mesh_mutable); + }); BLI_mutex_unlock(normals_mutex); return vert_normals; @@ -413,19 +420,24 @@ const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3] return (const float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL); } - Mesh &mesh_mutable = *const_cast<Mesh *>(mesh); + float(*poly_normals)[3]; + + /* Isolate task because a mutex is locked and computing normals is multi-threaded. */ + blender::threading::isolate_task([&]() { + Mesh &mesh_mutable = *const_cast<Mesh *>(mesh); - float(*poly_normals)[3] = BKE_mesh_poly_normals_for_write(&mesh_mutable); + poly_normals = BKE_mesh_poly_normals_for_write(&mesh_mutable); - BKE_mesh_calc_normals_poly(mesh_mutable.mvert, - mesh_mutable.totvert, - mesh_mutable.mloop, - mesh_mutable.totloop, - mesh_mutable.mpoly, - mesh_mutable.totpoly, - poly_normals); + BKE_mesh_calc_normals_poly(mesh_mutable.mvert, + mesh_mutable.totvert, + mesh_mutable.mloop, + mesh_mutable.totloop, + mesh_mutable.mpoly, + mesh_mutable.totpoly, + poly_normals); - BKE_mesh_poly_normals_clear_dirty(&mesh_mutable); + BKE_mesh_poly_normals_clear_dirty(&mesh_mutable); + }); BLI_mutex_unlock(normals_mutex); return poly_normals; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 829ef08a8fb..4cedaff7c00 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -15,13 +15,12 @@ * * The Original Code is Copyright (C) 2005 by the Blender Foundation. * All rights reserved. - * Modifier stack implementation. - * - * BKE_modifier.h contains the function prototypes for this file. */ /** \file * \ingroup bke + * Modifier stack implementation. + * BKE_modifier.h contains the function prototypes for this file. */ /* Allow using deprecated functionality for .blend file I/O. */ diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c index 839c457dd84..9ecd0901689 100644 --- a/source/blender/blenkernel/intern/multires_reshape_smooth.c +++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c @@ -825,6 +825,7 @@ static void foreach_edge(const struct SubdivForeachContext *foreach_context, void *UNUSED(tls), const int coarse_edge_index, const int UNUSED(subdiv_edge_index), + const bool is_loose, const int subdiv_v1, const int subdiv_v2) { @@ -832,7 +833,9 @@ static void foreach_edge(const struct SubdivForeachContext *foreach_context, const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; if (reshape_smooth_context->smoothing_type == MULTIRES_SUBDIVIDE_LINEAR) { - store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, (char)255); + if (!is_loose) { + store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, (char)255); + } return; } diff --git a/source/blender/blenkernel/intern/node_tree_update.cc b/source/blender/blenkernel/intern/node_tree_update.cc index 0555707b64c..9f3ce68ca69 100644 --- a/source/blender/blenkernel/intern/node_tree_update.cc +++ b/source/blender/blenkernel/intern/node_tree_update.cc @@ -273,6 +273,12 @@ static OutputFieldDependency find_group_output_dependencies( while (!sockets_to_check.is_empty()) { const InputSocketRef *input_socket = sockets_to_check.pop(); + if (!input_socket->is_directly_linked() && + !field_state_by_socket_id[input_socket->id()].is_single) { + /* This socket uses a field as input by default. */ + return OutputFieldDependency::ForFieldSource(); + } + for (const OutputSocketRef *origin_socket : input_socket->directly_linked_sockets()) { const NodeRef &origin_node = origin_socket->node(); const SocketFieldState &origin_state = field_state_by_socket_id[origin_socket->id()]; @@ -1608,6 +1614,11 @@ void BKE_ntree_update_tag_link_mute(bNodeTree *ntree, bNodeLink *UNUSED(link)) add_tree_tag(ntree, NTREE_CHANGED_LINK); } +void BKE_ntree_update_tag_active_output_changed(bNodeTree *ntree) +{ + add_tree_tag(ntree, NTREE_CHANGED_ANY); +} + void BKE_ntree_update_tag_missing_runtime_data(bNodeTree *ntree) { add_tree_tag(ntree, NTREE_CHANGED_ALL); diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index 04d60c096f2..8faae6efb26 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -89,6 +89,7 @@ #include "BKE_constraint.h" #include "BKE_crazyspace.h" #include "BKE_curve.h" +#include "BKE_curves.h" #include "BKE_deform.h" #include "BKE_displist.h" #include "BKE_duplilist.h" @@ -103,7 +104,6 @@ #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" -#include "BKE_hair.h" #include "BKE_icons.h" #include "BKE_idprop.h" #include "BKE_idtype.h" @@ -1415,7 +1415,7 @@ bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type) } /* Only geometry objects should be able to get modifiers T25291. */ - if (ELEM(ob->type, OB_POINTCLOUD, OB_VOLUME, OB_HAIR)) { + if (ELEM(ob->type, OB_POINTCLOUD, OB_VOLUME, OB_CURVES)) { return (mti->modifyGeometrySet != nullptr); } if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { @@ -2098,8 +2098,8 @@ static const char *get_obdata_defname(int type) return DATA_("Armature"); case OB_SPEAKER: return DATA_("Speaker"); - case OB_HAIR: - return DATA_("Hair"); + case OB_CURVES: + return DATA_("HairCurves"); case OB_POINTCLOUD: return DATA_("PointCloud"); case OB_VOLUME: @@ -2173,8 +2173,8 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name) return BKE_lightprobe_add(bmain, name); case OB_GPENCIL: return BKE_gpencil_data_addnew(bmain, name); - case OB_HAIR: - return BKE_hair_add(bmain, name); + case OB_CURVES: + return BKE_curves_add(bmain, name); case OB_POINTCLOUD: return BKE_pointcloud_add_default(bmain, name); case OB_VOLUME: @@ -2211,8 +2211,8 @@ int BKE_object_obdata_to_type(const ID *id) return OB_ARMATURE; case ID_LP: return OB_LIGHTPROBE; - case ID_HA: - return OB_HAIR; + case ID_CV: + return OB_CURVES; case ID_PT: return OB_POINTCLOUD; case ID_VO: @@ -2729,8 +2729,8 @@ Object *BKE_object_duplicate(Main *bmain, Object *ob, uint dupflag, uint duplica id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags); } break; - case OB_HAIR: - if (dupflag & USER_DUP_HAIR) { + case OB_CURVES: + if (dupflag & USER_DUP_CURVES) { id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags); } break; @@ -3624,8 +3624,8 @@ BoundBox *BKE_object_boundbox_get(Object *ob) case OB_GPENCIL: bb = BKE_gpencil_boundbox_get(ob); break; - case OB_HAIR: - bb = BKE_hair_boundbox_get(ob); + case OB_CURVES: + bb = BKE_curves_boundbox_get(ob); break; case OB_POINTCLOUD: bb = BKE_pointcloud_boundbox_get(ob); @@ -3826,8 +3826,8 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us } break; } - case OB_HAIR: { - BoundBox bb = *BKE_hair_boundbox_get(ob); + case OB_CURVES: { + BoundBox bb = *BKE_curves_boundbox_get(ob); BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); changed = true; break; @@ -4941,7 +4941,7 @@ bool BKE_object_supports_material_slots(struct Object *ob) OB_SURF, OB_FONT, OB_MBALL, - OB_HAIR, + OB_CURVES, OB_POINTCLOUD, OB_VOLUME, OB_GPENCIL); diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 9c2b48303b2..6352fd19239 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -13,7 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * The Original Code is Copyright (C) 20014 by Blender Foundation. + * The Original Code is Copyright (C) 2014 by Blender Foundation. * All rights reserved. */ @@ -41,12 +41,12 @@ #include "BKE_armature.h" #include "BKE_constraint.h" #include "BKE_curve.h" +#include "BKE_curves.h" #include "BKE_displist.h" #include "BKE_editmesh.h" #include "BKE_effect.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" -#include "BKE_hair.h" #include "BKE_image.h" #include "BKE_key.h" #include "BKE_lattice.h" @@ -214,8 +214,8 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o BKE_gpencil_update_layer_transforms(depsgraph, ob); break; } - case OB_HAIR: - BKE_hair_data_update(depsgraph, scene, ob); + case OB_CURVES: + BKE_curves_data_update(depsgraph, scene, ob); break; case OB_POINTCLOUD: BKE_pointcloud_data_update(depsgraph, scene, ob); @@ -304,7 +304,6 @@ void BKE_object_sync_to_original(Depsgraph *depsgraph, Object *object) void BKE_object_eval_uber_transform(Depsgraph *UNUSED(depsgraph), Object *UNUSED(object)) { - return; } void BKE_object_data_batch_cache_dirty_tag(ID *object_data) @@ -326,8 +325,8 @@ void BKE_object_data_batch_cache_dirty_tag(ID *object_data) case ID_GD: BKE_gpencil_batch_cache_dirty_tag((struct bGPdata *)object_data); break; - case ID_HA: - BKE_hair_batch_cache_dirty_tag((struct Hair *)object_data, BKE_HAIR_BATCH_DIRTY_ALL); + case ID_CV: + BKE_curves_batch_cache_dirty_tag((struct Curves *)object_data, BKE_CURVES_BATCH_DIRTY_ALL); break; case ID_PT: BKE_pointcloud_batch_cache_dirty_tag((struct PointCloud *)object_data, diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 97326c24a61..dacc24c32da 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -15,13 +15,13 @@ * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. - * - * Based on original code by Drew Whitehouse / Houdini Ocean Toolkit - * OpenMP hints by Christian Schnellhammer */ /** \file * \ingroup bke + * + * Based on original code by Drew Whitehouse / Houdini Ocean Toolkit + * OpenMP hints by Christian Schnellhammer */ #include <math.h> diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index e489f9e2bac..6953ecf38c3 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -13,11 +13,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * The Original Code is Copyright (C) 2007 by Janne Karhu. - * All rights reserved. - * Adaptive time step - * Classical SPH - * Copyright 2011-2012 AutoCRC + * Copyright 2007 Janne Karhu. All rights reserved. + * 2011-2012 AutoCRC (adaptive time step, Classical SPH). */ /** \file diff --git a/source/blender/blenkernel/intern/subdiv_foreach.c b/source/blender/blenkernel/intern/subdiv_foreach.c index 69bead27fe6..b510a9b3bba 100644 --- a/source/blender/blenkernel/intern/subdiv_foreach.c +++ b/source/blender/blenkernel/intern/subdiv_foreach.c @@ -734,7 +734,7 @@ static int subdiv_foreach_edges_row(SubdivForeachTaskContext *ctx, const int v1 = vertex_index; const int v2 = vertex_index + 1; ctx->foreach_context->edge( - ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, v1, v2); + ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, false, v1, v2); vertex_index += 1; } return subdiv_edge_index; @@ -762,7 +762,7 @@ static int subdiv_foreach_edges_column(SubdivForeachTaskContext *ctx, const int v1 = vertex_index; const int v2 = vertex_index + num_edges_per_row; ctx->foreach_context->edge( - ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, v1, v2); + ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, false, v1, v2); vertex_index += 1; } return subdiv_edge_index; @@ -862,7 +862,7 @@ static void subdiv_foreach_edges_all_patches_regular(SubdivForeachTaskContext *c const int v1 = (flip) ? (start_edge_vertex + (resolution - i - 3)) : (start_edge_vertex + i); const int v2 = side_start_index + side_stride * i; ctx->foreach_context->edge( - ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, v1, v2); + ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, false, v1, v2); } } } @@ -926,7 +926,7 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c const int v1 = current_patch_vertex_index; const int v2 = next_path_vertex_index; ctx->foreach_context->edge( - ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, v1, v2); + ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, false, v1, v2); current_patch_vertex_index += ptex_face_inner_resolution + 1; next_path_vertex_index += 1; } @@ -940,7 +940,7 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c const int v1 = center_vertex_index; const int v2 = current_patch_end_vertex_index; ctx->foreach_context->edge( - ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, v1, v2); + ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, false, v1, v2); } } /* Connect inner path of patch to boundary. */ @@ -964,7 +964,7 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c (start_edge_vertex + i); const int v2 = side_start_index + i; ctx->foreach_context->edge( - ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, v1, v2); + ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, false, v1, v2); } } if (ptex_face_resolution >= 3) { @@ -978,7 +978,7 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c (start_edge_vertex + i); const int v2 = side_start_index + (ptex_face_inner_resolution + 1) * i; ctx->foreach_context->edge( - ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, v1, v2); + ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, false, v1, v2); } } prev_coarse_loop = coarse_loop; @@ -1015,6 +1015,8 @@ static void subdiv_foreach_boundary_edges(SubdivForeachTaskContext *ctx, const int resolution = ctx->settings->resolution; const int num_subdiv_vertices_per_coarse_edge = resolution - 2; const int num_subdiv_edges_per_coarse_edge = resolution - 1; + const bool is_loose = !BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, coarse_edge_index); + int subdiv_edge_index = ctx->edge_boundary_offset + coarse_edge_index * num_subdiv_edges_per_coarse_edge; int last_vertex_index = ctx->vertices_corner_offset + coarse_edge->v1; @@ -1023,13 +1025,13 @@ static void subdiv_foreach_boundary_edges(SubdivForeachTaskContext *ctx, const int v2 = ctx->vertices_edge_offset + coarse_edge_index * num_subdiv_vertices_per_coarse_edge + i; ctx->foreach_context->edge( - ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, v1, v2); + ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, is_loose, v1, v2); last_vertex_index = v2; } const int v1 = last_vertex_index; const int v2 = ctx->vertices_corner_offset + coarse_edge->v2; ctx->foreach_context->edge( - ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, v1, v2); + ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, is_loose, v1, v2); } /** \} */ diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c index c334d9a2c33..09af77d5f09 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_mesh.c @@ -767,6 +767,7 @@ static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context, void *UNUSED(tls), const int coarse_edge_index, const int subdiv_edge_index, + const bool UNUSED(is_loose), const int subdiv_v1, const int subdiv_v2) { diff --git a/source/blender/blenkernel/intern/vfontdata_freetype.c b/source/blender/blenkernel/intern/vfontdata_freetype.c index 9b79d5635d1..60b7e4e5c8b 100644 --- a/source/blender/blenkernel/intern/vfontdata_freetype.c +++ b/source/blender/blenkernel/intern/vfontdata_freetype.c @@ -15,6 +15,10 @@ * * The Original Code is written by Rob Haarsma (phase) * All rights reserved. + */ + +/** \file + * \ingroup bke * * This code parses the Freetype font outline data to chains of Blender's bezier-triples. * Additional information can be found at the bottom of this file. @@ -22,10 +26,6 @@ * Code that uses exotic character maps is present but commented out. */ -/** \file - * \ingroup bke - */ - #include <ft2build.h> #include FT_FREETYPE_H /* not needed yet */ diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index a4f20f980b4..138c75acd7b 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -15,11 +15,11 @@ * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. - * Functions for writing avi-format files. - * Added interface for generic movie support (ton) */ /** \file + * Functions for writing AVI-format files. + * Added interface for generic movie support (ton) * \ingroup bke */ |